Rumpk Stability, NipBox Boot, and Repository Cleanup
- Fixed Rumpk RISC-V Trap Handler (SSCRATCH swap, align(4), SUM bit) to prevent double faults. - Stabilized Userland Transition (fence.i, MMU activation) allowing NipBox execution. - Restored Forge pipeline to build NipBox from source. - Documented critical RISC-V trap mechanics in .agent/tips. - Committed pending repository cleanup (obsolete websites) and new core modules.
This commit is contained in:
parent
bd03bed91f
commit
6e78b7f458
|
|
@ -0,0 +1,34 @@
|
|||
# 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.
|
||||
|
||||
## Sovereign Init: The Genesis Process
|
||||
##
|
||||
## Responsible for bootstrapping the system, starting core services,
|
||||
## and managing the lifecycle of the user environment.
|
||||
|
||||
import ../../libs/membrane/libc
|
||||
|
||||
# --- Entry Point ---
|
||||
|
||||
proc main() =
|
||||
# 1. Pledge Sovereignty
|
||||
discard pledge(0xFFFFFFFFFFFFFFFF'u64) # PLEDGE_ALL
|
||||
|
||||
print("\n")
|
||||
print("\x1b[1;35m╔═══════════════════════════════════════╗\x1b[0m\n")
|
||||
print("\x1b[1;35m║ SOVEREIGN INIT (NexInit v0.1) ║\x1b[0m\n")
|
||||
print("\x1b[1;35m╚═══════════════════════════════════════╝\x1b[0m\n\n")
|
||||
|
||||
print("[INIT] System Ready. Starting heartbeat...\n")
|
||||
|
||||
while true:
|
||||
# 🕵️ DIAGNOSTIC: BREATHER
|
||||
pump_membrane_stack()
|
||||
yield_fiber()
|
||||
|
||||
when isMainModule:
|
||||
main()
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/* Minimal linker script for test binary */
|
||||
ENTRY(_start)
|
||||
MEMORY
|
||||
{
|
||||
RAM (rwx) : ORIGIN = 0x88000000, LENGTH = 128M
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x88000000;
|
||||
|
||||
.text : {
|
||||
*(.text._start)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} > RAM
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
/* Memory Layout (64MB Userspace):
|
||||
* User RAM: 0x86000000 - 0x89FFFFFF (64MB)
|
||||
* Stack starts at 0x89FFFFF0 and grows down
|
||||
/* Memory Layout (128MB Userspace):
|
||||
* User RAM: 0x88000000 - 0x8FFFFFFF (128MB)
|
||||
* Stack starts at 0x8FFFFFE0 and grows down
|
||||
* Requires QEMU -m 256M to ensure valid physical backing
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
RAM (rwx) : ORIGIN = 0x86000000, LENGTH = 64M
|
||||
RAM (rwx) : ORIGIN = 0x88000000, LENGTH = 128M
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x86000000;
|
||||
. = 0x88000000;
|
||||
|
||||
.text : {
|
||||
*(.text._start)
|
||||
|
|
@ -23,14 +23,23 @@ SECTIONS
|
|||
*(.rodata.*)
|
||||
} > RAM
|
||||
|
||||
.sdata : {
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.sdata .sdata.* .srodata .srodata.*)
|
||||
} > RAM
|
||||
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
} > RAM
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(8);
|
||||
__bss_start = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
__bss_end = .;
|
||||
} > RAM
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,36 @@
|
|||
.global _start
|
||||
_start:
|
||||
# 🕵️ DIAGNOSTIC: BREATHE
|
||||
# li t0, 0x10000000
|
||||
# li t1, 0x23 # '#'
|
||||
# sb t1, 0(t0)
|
||||
li t0, 0x10000000
|
||||
li t1, 0x23 # '#'
|
||||
sb t1, 0(t0)
|
||||
|
||||
# Clear BSS (64-bit aligned zeroing)
|
||||
la t0, __bss_start
|
||||
la t1, __bss_end
|
||||
1: bge t0, t1, 2f
|
||||
sd zero, 0(t0)
|
||||
addi t0, t0, 8
|
||||
j 1b
|
||||
2:
|
||||
fence rw, rw
|
||||
|
||||
# 🔧 CRITICAL FIX: Set up stack pointer for userland
|
||||
# Stack grows down from top of 128MB userland RAM (0x90000000 - 32 bytes for alignment)
|
||||
li sp, 0x8FFFFFE0
|
||||
|
||||
# 🔧 CRITICAL FIX: Set up global pointer for RISC-V ABI
|
||||
# Global pointer should point to .sdata section for efficient global access
|
||||
# For userland at 0x88000000, set gp to middle of address space
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
# 🕵️ DIAGNOSTIC: READY TO CALL MAIN
|
||||
# li t1, 0x21 # '!'
|
||||
# sb t1, 0(t0)
|
||||
li t0, 0x10000000
|
||||
li t1, 0x21 # '!'
|
||||
sb t1, 0(t0)
|
||||
|
||||
# Call main(0, NULL)
|
||||
li a0, 0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
# Minimal userland test - pure loop
|
||||
# Tests instruction fetch only. No memory stores.
|
||||
|
||||
.section .text._start, "ax"
|
||||
.global _start
|
||||
_start:
|
||||
# Just loop forever
|
||||
j _start
|
||||
|
|
@ -1,5 +1,16 @@
|
|||
// Rumpk Boot Header
|
||||
// Multiboot2 / EFI entry point definition
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Boot Header
|
||||
//!
|
||||
//! Defines the Multiboot2 header for GRUB/QEMU and the bare-metal entry point.
|
||||
//! Handles BSS clearing and stack initialization before jumping to the Nim kernel.
|
||||
//!
|
||||
//! SAFETY: Executed in the earliest boot stage with no environment initialized.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
|
|
|
|||
62
build.zig
62
build.zig
|
|
@ -1,6 +1,14 @@
|
|||
// Rumpk Build System
|
||||
// Orchestrates L0 (Zig) and L1 (Nim) compilation
|
||||
// Markus Maiwald (Architect) | Voxis Forge (AI)
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Build System
|
||||
//!
|
||||
//! Orchestrates L0 (Zig) and L1 (Nim) compilation.
|
||||
//! Builds the Hardware Abstraction Layer as a static library.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
|
|
@ -12,50 +20,66 @@ pub fn build(b: *std.Build) void {
|
|||
// L0: Hardware Abstraction Layer (Zig)
|
||||
// =========================================================
|
||||
|
||||
const hal = b.addStaticLibrary(.{
|
||||
.name = "rumpk_hal",
|
||||
// NOTE(Build): Zig 0.15.x API - using addLibrary with static linkage
|
||||
const hal_mod = b.createModule(.{
|
||||
.root_source_file = b.path("hal/abi.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
// Freestanding kernel - no libc, no red zone, no stack checks
|
||||
hal_mod.red_zone = false;
|
||||
hal_mod.stack_check = false;
|
||||
|
||||
// Freestanding kernel - no libc
|
||||
hal.root_module.red_zone = false;
|
||||
hal.root_module.stack_check = .none;
|
||||
|
||||
// Microui Integration (Phase 3.5b)
|
||||
hal.addIncludePath(b.path("libs/microui"));
|
||||
hal.addCSourceFile(.{
|
||||
.file = b.path("libs/microui/microui.c"),
|
||||
.flags = &.{"-std=c99"},
|
||||
const hal = b.addLibrary(.{
|
||||
.name = "rumpk_hal",
|
||||
.root_module = hal_mod,
|
||||
.linkage = .static,
|
||||
});
|
||||
|
||||
b.installArtifact(hal);
|
||||
|
||||
// TODO(Build): Microui needs stdio.h stubs for freestanding.
|
||||
// Re-enable after creating libs/microui/stdio_stub.h
|
||||
// Microui Integration (Phase 3.5b)
|
||||
// hal_mod.addIncludePath(b.path("libs/microui"));
|
||||
// hal_mod.addCSourceFile(.{
|
||||
// .file = b.path("libs/microui/microui.c"),
|
||||
// .flags = &.{"-std=c99"},
|
||||
// });
|
||||
|
||||
// =========================================================
|
||||
// Boot: Entry Point (Assembly + Zig)
|
||||
// =========================================================
|
||||
|
||||
const boot = b.addObject(.{
|
||||
.name = "boot",
|
||||
const boot_mod = b.createModule(.{
|
||||
.root_source_file = b.path("boot/header.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
boot_mod.red_zone = false;
|
||||
boot_mod.stack_check = false;
|
||||
|
||||
boot.root_module.red_zone = false;
|
||||
boot.root_module.stack_check = .none;
|
||||
const boot = b.addObject(.{
|
||||
.name = "boot",
|
||||
.root_module = boot_mod,
|
||||
});
|
||||
|
||||
_ = boot; // Mark as used for now
|
||||
|
||||
// =========================================================
|
||||
// Tests
|
||||
// =========================================================
|
||||
|
||||
const hal_tests = b.addTest(.{
|
||||
const test_mod = b.createModule(.{
|
||||
.root_source_file = b.path("hal/abi.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const hal_tests = b.addTest(.{
|
||||
.root_module = test_mod,
|
||||
});
|
||||
|
||||
const run_tests = b.addRunArtifact(hal_tests);
|
||||
const test_step = b.step("test", "Run Rumpk HAL tests");
|
||||
test_step.dependOn(&run_tests.step);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: High-Level Sovereign Channels
|
||||
|
||||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# RUMPK CORE // CHANNEL
|
||||
# The primitive for Typed Communication.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# RUMPK CORE // FIBER (Unified Multi-Arch)
|
||||
# The atom of execution.
|
||||
# SPDX-License-Identifier: LSL-1.0
|
||||
# Copyright (c) 2026 Markus Maiwald
|
||||
# Stewardship: Self Sovereign Society Foundation
|
||||
#
|
||||
# Supported Architectures:
|
||||
# - aarch64 (ARM64): VisionFive 2, RPi, AWS Graviton
|
||||
# - amd64 (x86_64): Standard servers, trading systems
|
||||
# - riscv64 (RISC-V): Sovereign compute, satellites
|
||||
# This file is part of the Nexus Sovereign Core.
|
||||
# See legal/LICENSE_SOVEREIGN.md for license terms.
|
||||
|
||||
## Rumpk Layer 1: Fiber Execution (Motive Power)
|
||||
##
|
||||
## Implements the unified multi-arch fiber context switching.
|
||||
## Supported Architectures: x86_64, AArch64, RISC-V.
|
||||
##
|
||||
## SAFETY: Direct manipulation of stack pointers and CPU registers via
|
||||
## architecture-specific context frames. Swaps page tables during switch.
|
||||
|
||||
{.push stackTrace: off, lineTrace: off.}
|
||||
|
||||
|
|
@ -36,6 +42,12 @@ else:
|
|||
# =========================================================
|
||||
|
||||
type
|
||||
Spectrum* = enum
|
||||
Photon = 0 # UI/Audio (Top Tier)
|
||||
Matter = 1 # Interactive (Middle Tier)
|
||||
Gravity = 2 # Batch (Bottom Tier)
|
||||
Void = 3 # Unclassified/Demoted (Default)
|
||||
|
||||
FiberState* = object
|
||||
sp*: uint64 # The Stack Pointer (Must be first field!)
|
||||
entry*: proc() {.cdecl.} # Entry point for this fiber
|
||||
|
|
@ -48,11 +60,26 @@ type
|
|||
stack*: ptr UncheckedArray[uint8]
|
||||
stack_size*: int
|
||||
sleep_until*: uint64 # NS timestamp
|
||||
promises*: uint64 # Phase 28: Capability Mask (Pledge)
|
||||
promises*: uint64 # [63:62]=Spectrum, [61:0]=Pledge bits
|
||||
pledge_budget*: uint64 # Microseconds allowed per frame (legacy)
|
||||
avg_burst*: uint64 # Moving average for telemetry (The Ratchet)
|
||||
user_entry*: pointer # Phase 29: User function pointer for workers
|
||||
user_arg*: uint64 # Phase 29: Argument for user function
|
||||
satp_value*: uint64 # Phase 31: Page table root (0 = use kernel map)
|
||||
wants_yield*: bool # Phase 37: Deferred yield flag
|
||||
# SPEC-250: The Ratchet
|
||||
budget_ns*: uint64 # "I promise to run for X ns max"
|
||||
last_burst_ns*: uint64 # Actual execution time of last run
|
||||
violations*: uint32 # Strike counter (3 strikes = demotion)
|
||||
|
||||
# Spectrum Accessors
|
||||
proc getSpectrum*(f: Fiber): Spectrum =
|
||||
if f == nil: return Spectrum.Void
|
||||
Spectrum((f.promises shr 62) and 0x3)
|
||||
|
||||
proc setSpectrum*(f: Fiber, s: Spectrum) =
|
||||
if f == nil: return
|
||||
f.promises = (f.promises and 0x3FFFFFFFFFFFFFFF'u64) or (uint64(s) shl 62)
|
||||
|
||||
proc fiber_yield*() {.importc, cdecl.}
|
||||
# Imports
|
||||
|
|
@ -117,6 +144,9 @@ proc fiber_trampoline() {.cdecl, exportc, noreturn.} =
|
|||
|
||||
proc init_fiber*(f: Fiber, entry: proc() {.cdecl.}, stack_base: pointer, size: int) =
|
||||
f.state.entry = entry
|
||||
f.stack = cast[ptr UncheckedArray[uint8]](stack_base)
|
||||
f.stack_size = size
|
||||
f.sleep_until = 0
|
||||
|
||||
# Start at top of stack (using actual size)
|
||||
var sp = cast[uint64](stack_base) + cast[uint64](size)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,22 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Sovereign File System (SFS)
|
||||
|
||||
# Markus Maiwald (Architect) | Voxis Forge (AI)
|
||||
#
|
||||
# Rumpk Phase 23: The Sovereign Filesystem (SFS) v2
|
||||
# Features: Multi-Sector Files (Linked List), Block Alloc Map (BAM)
|
||||
#
|
||||
# DOCTRINE(SPEC-021):
|
||||
# This file currently implements the "Physics-Logic Hybrid" for Bootstrapping.
|
||||
# In Phase 37, this will be deprecated in favor of:
|
||||
# - L0: LittleFS (Atomic Physics)
|
||||
# - L1: SFS Overlay Daemon (Sovereign Logic in Userland)
|
||||
|
||||
proc kprintln(s: cstring) {.importc, cdecl.}
|
||||
proc kprint(s: cstring) {.importc, cdecl.}
|
||||
|
|
@ -11,14 +27,13 @@ proc kprint_hex(n: uint64) {.importc, cdecl.}
|
|||
# =========================================================
|
||||
|
||||
const SFS_MAGIC* = 0x31534653'u32
|
||||
const SEC_SB = 0
|
||||
const SEC_BAM = 1
|
||||
const SEC_DIR = 2
|
||||
|
||||
# Linked List Payload: 508 bytes data + 4 bytes next_sector
|
||||
const CHUNK_SIZE = 508
|
||||
const NEXT_PTR_OFFSET = 508
|
||||
const EOF_MARKER = 0xFFFFFFFF'u32
|
||||
const
|
||||
SEC_SB = 0
|
||||
SEC_BAM = 1
|
||||
SEC_DIR = 2
|
||||
# Linked List Payload: 508 bytes data + 4 bytes next_sector
|
||||
CHUNK_SIZE = 508
|
||||
EOF_MARKER = 0xFFFFFFFF'u32
|
||||
|
||||
type
|
||||
Superblock* = object
|
||||
|
|
@ -41,14 +56,7 @@ proc virtio_blk_write(sector: uint64, buf: pointer) {.importc, cdecl.}
|
|||
# Helpers
|
||||
# =========================================================
|
||||
|
||||
proc sfs_set_bam(sector: uint32) =
|
||||
# Read BAM
|
||||
virtio_blk_read(SEC_BAM, addr io_buffer[0])
|
||||
let byteIndex = int(sector div 8)
|
||||
let bitIndex = int(sector mod 8)
|
||||
if byteIndex < 512:
|
||||
io_buffer[byteIndex] = io_buffer[byteIndex] or byte(1 shl bitIndex)
|
||||
virtio_blk_write(SEC_BAM, addr io_buffer[0])
|
||||
# Removed sfs_set_bam (unused)
|
||||
|
||||
proc sfs_alloc_sector(): uint32 =
|
||||
# Simple allocator: Scan BAM for first 0 bit
|
||||
|
|
@ -73,6 +81,31 @@ proc sfs_alloc_sector(): uint32 =
|
|||
|
||||
proc sfs_is_mounted*(): bool = sfs_mounted
|
||||
|
||||
proc sfs_format*() =
|
||||
kprintln("[SFS] Formatting disk...")
|
||||
# 1. Clear IO Buffer
|
||||
for i in 0..511: io_buffer[i] = 0
|
||||
|
||||
# 2. Setup Superblock
|
||||
io_buffer[0] = byte('S')
|
||||
io_buffer[1] = byte('F')
|
||||
io_buffer[2] = byte('S')
|
||||
io_buffer[3] = byte('2')
|
||||
# Disk size placeholder (32MB = 65536 sectors)
|
||||
io_buffer[4] = 0x00; io_buffer[5] = 0x00; io_buffer[6] = 0x01; io_buffer[7] = 0x00
|
||||
virtio_blk_write(SEC_SB, addr io_buffer[0])
|
||||
|
||||
# 3. Clear BAM
|
||||
for i in 0..511: io_buffer[i] = 0
|
||||
# Mark sectors 0, 1, 2 as used
|
||||
io_buffer[0] = 0x07
|
||||
virtio_blk_write(SEC_BAM, addr io_buffer[0])
|
||||
|
||||
# 4. Clear Directory
|
||||
for i in 0..511: io_buffer[i] = 0
|
||||
virtio_blk_write(SEC_DIR, addr io_buffer[0])
|
||||
kprintln("[SFS] Format Complete.")
|
||||
|
||||
proc sfs_mount*() =
|
||||
kprintln("[SFS] Mounting System v2...")
|
||||
|
||||
|
|
@ -84,6 +117,10 @@ proc sfs_mount*() =
|
|||
io_buffer[2] == byte('S') and io_buffer[3] == byte('2'):
|
||||
kprintln("[SFS] Mount SUCCESS. Version 2 (Linked Chain).")
|
||||
sfs_mounted = true
|
||||
elif io_buffer[0] == 0 and io_buffer[1] == 0:
|
||||
kprintln("[SFS] Fresh disk detected.")
|
||||
sfs_format()
|
||||
sfs_mounted = true
|
||||
else:
|
||||
kprint("[SFS] Mount FAILED. Invalid Magic/Ver. Found: ")
|
||||
kprint_hex(cast[uint64](io_buffer[0]))
|
||||
|
|
@ -129,7 +166,6 @@ proc sfs_write_file*(name: cstring, data: cstring, data_len: int) {.exportc, cde
|
|||
virtio_blk_read(SEC_DIR, addr io_buffer[0])
|
||||
|
||||
var dir_offset = -1
|
||||
var start_sector = 0'u32
|
||||
var file_exists = false
|
||||
|
||||
# 1. Find File or Free Slot
|
||||
|
|
@ -158,7 +194,6 @@ proc sfs_write_file*(name: cstring, data: cstring, data_len: int) {.exportc, cde
|
|||
var remaining = data_len
|
||||
var data_ptr = 0
|
||||
var first_sector = 0'u32
|
||||
var prev_sector = 0'u32
|
||||
var current_sector = 0'u32
|
||||
|
||||
# For the first chunk
|
||||
|
|
|
|||
121
core/fs/tar.nim
121
core/fs/tar.nim
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: ROMFS (Static Tar Loader)
|
||||
|
||||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# Rumpk L1: Sovereign VFS (Indexing TarFS)
|
||||
|
||||
|
|
@ -157,109 +166,55 @@ proc vfs_read_file*(path: string): string =
|
|||
return s
|
||||
return ""
|
||||
|
||||
proc ion_vfs_open*(path: cstring, flags: int32): int32 {.exportc, cdecl.} =
|
||||
return int32(vfs_open($path, flags))
|
||||
|
||||
proc sfs_write_file(name: cstring, data: cstring, data_len: int) {.importc, cdecl.}
|
||||
proc sfs_read_file(name: cstring, dest: pointer, max_len: int): int {.importc, cdecl.}
|
||||
|
||||
proc ion_vfs_read*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
|
||||
let fd_int = int(fd)
|
||||
if not vfs.fds.hasKey(fd_int): return -1
|
||||
let fh = addr vfs.fds[fd_int]
|
||||
|
||||
if fh.is_sfs:
|
||||
# Read to temp buffer to handle offset/slicing
|
||||
var temp_buf: array[512, byte]
|
||||
let total_n = sfs_read_file(cstring(fh.path), addr temp_buf[0], 512)
|
||||
if total_n < 0: return -1
|
||||
|
||||
if fh.offset >= uint64(total_n): return 0
|
||||
let available = uint64(total_n) - fh.offset
|
||||
proc vfs_read_at*(path: string, buf: pointer, count: uint64, offset: uint64): int64 =
|
||||
if vfs.ram_data.hasKey(path):
|
||||
let data = addr vfs.ram_data[path]
|
||||
if offset >= uint64(data[].len): return 0
|
||||
let available = uint64(data[].len) - offset
|
||||
let actual = min(count, available)
|
||||
|
||||
if actual > 0:
|
||||
copyMem(buf, addr temp_buf[int(fh.offset)], int(actual))
|
||||
fh.offset += actual
|
||||
copyMem(buf, addr data[][int(offset)], int(actual))
|
||||
return int64(actual)
|
||||
|
||||
# 1. RamFS Read
|
||||
if fh.is_ram:
|
||||
if not vfs.ram_data.hasKey(fh.path): return 0
|
||||
let data = addr vfs.ram_data[fh.path]
|
||||
if fh.offset >= uint64(data[].len): return 0
|
||||
let available = uint64(data[].len) - fh.offset
|
||||
let actual_count = min(count, available)
|
||||
if actual_count > 0:
|
||||
copyMem(buf, addr data[][int(fh.offset)], int(actual_count))
|
||||
fh.offset += actual_count
|
||||
return int64(actual_count)
|
||||
if not vfs.index.hasKey(path): return -1
|
||||
let entry = vfs.index[path]
|
||||
if entry.is_sfs: return -1 # Routed via SFS
|
||||
|
||||
# 2. Tar Read
|
||||
let entry = vfs.index[fh.path]
|
||||
var actual_count = uint64(count)
|
||||
var actual = uint64(count)
|
||||
if offset >= entry.size: return 0
|
||||
if offset + count > entry.size:
|
||||
actual = entry.size - offset
|
||||
|
||||
if fh.offset >= entry.size: return 0
|
||||
if fh.offset + uint64(count) > entry.size:
|
||||
actual_count = entry.size - fh.offset
|
||||
copyMem(buf, cast[pointer](entry.offset + offset), int(actual))
|
||||
return int64(actual)
|
||||
|
||||
copyMem(buf, cast[pointer](entry.offset + fh.offset), int(actual_count))
|
||||
fh.offset += actual_count
|
||||
|
||||
return int64(actual_count)
|
||||
|
||||
proc ion_vfs_close*(fd: int32): int32 {.exportc, cdecl.} =
|
||||
let fd_int = int(fd)
|
||||
if vfs.fds.hasKey(fd_int):
|
||||
vfs.fds.del(fd_int)
|
||||
return 0
|
||||
return -1
|
||||
|
||||
proc ion_vfs_write*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
|
||||
let fd_int = int(fd)
|
||||
if not vfs.fds.hasKey(fd_int): return -1
|
||||
let fh = addr vfs.fds[fd_int]
|
||||
|
||||
if fh.is_sfs:
|
||||
sfs_write_file(cstring(fh.path), cast[cstring](buf), int(count))
|
||||
return int64(count)
|
||||
|
||||
# 1. Promote to RamFS if on TarFS (CoW)
|
||||
if not fh.is_ram:
|
||||
if vfs.index.hasKey(fh.path):
|
||||
let entry = vfs.index[fh.path]
|
||||
proc vfs_write_at*(path: string, buf: pointer, count: uint64, offset: uint64): int64 =
|
||||
# Promote to RamFS if on TarFS (CoW)
|
||||
if not vfs.ram_data.hasKey(path):
|
||||
if vfs.index.hasKey(path):
|
||||
let entry = vfs.index[path]
|
||||
var content = newSeq[byte](int(entry.size))
|
||||
if entry.size > 0:
|
||||
copyMem(addr content[0], cast[pointer](entry.offset), int(entry.size))
|
||||
vfs.ram_data[fh.path] = content
|
||||
fh.is_ram = true
|
||||
# fh.offset preserved
|
||||
vfs.ram_data[path] = content
|
||||
else:
|
||||
# Should not happen if open was successful, but for safety:
|
||||
vfs.ram_data[fh.path] = @[]
|
||||
fh.is_ram = true
|
||||
vfs.ram_data[path] = @[]
|
||||
|
||||
# 2. RamFS Write
|
||||
let data = addr vfs.ram_data[fh.path]
|
||||
let min_size = int(fh.offset + count)
|
||||
let data = addr vfs.ram_data[path]
|
||||
let min_size = int(offset + count)
|
||||
if data[].len < min_size:
|
||||
data[].setLen(min_size)
|
||||
|
||||
copyMem(addr data[][int(fh.offset)], buf, int(count))
|
||||
fh.offset += count
|
||||
copyMem(addr data[][int(offset)], buf, int(count))
|
||||
return int64(count)
|
||||
# Removed ion_vfs_* in favor of vfs.nim dispatcher
|
||||
|
||||
proc ion_vfs_list*(buf: pointer, max_len: uint64): int64 {.exportc, cdecl.} =
|
||||
var s = ""
|
||||
# Unique names from both
|
||||
proc vfs_get_names*(): seq[string] =
|
||||
var names = initTable[string, bool]()
|
||||
for name, _ in vfs.index: names[name] = true
|
||||
for name, _ in vfs.ram_data: names[name] = true
|
||||
|
||||
for name, _ in names: s.add(name & "\n")
|
||||
let n = min(s.len, int(max_len))
|
||||
if n > 0: copyMem(buf, addr s[0], n)
|
||||
return int64(n)
|
||||
result = @[]
|
||||
for name, _ in names: result.add(name)
|
||||
|
||||
proc vfs_register_sfs*(name: string, size: uint64) {.exportc, cdecl.} =
|
||||
vfs.index[name] = FileEntry(offset: 0, size: size, is_sfs: true)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# test
|
||||
# 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.
|
||||
|
||||
## Rumpk Layer 1: FS Test Wrapper
|
||||
##
|
||||
## Internal testing utility for file system wrapping logic.
|
||||
proc foo() =
|
||||
echo "this is a very long line to see if it gets wrapped in the actual file system by the tool"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Sovereign VFS (The Loom)
|
||||
|
||||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# VFS dispatcher for SPEC-130 alignment.
|
||||
|
||||
import strutils, tables
|
||||
import tar, sfs
|
||||
|
||||
type
|
||||
VFSMode = enum
|
||||
MODE_TAR, MODE_SFS, MODE_RAM
|
||||
|
||||
MountPoint = object
|
||||
prefix: string
|
||||
mode: VFSMode
|
||||
|
||||
var mounts: seq[MountPoint] = @[]
|
||||
|
||||
type
|
||||
FileHandle = object
|
||||
path: string
|
||||
offset: uint64
|
||||
mode: VFSMode
|
||||
is_ram: bool
|
||||
|
||||
var fds = initTable[int, FileHandle]()
|
||||
var next_fd = 3
|
||||
|
||||
proc vfs_mount_init*() =
|
||||
# SPEC-130: The Three-Domain Root
|
||||
# SPEC-021: The Sovereign Overlay Strategy
|
||||
mounts.add(MountPoint(prefix: "/nexus", mode: MODE_SFS)) # The Sovereign State (Persistent)
|
||||
mounts.add(MountPoint(prefix: "/sysro", mode: MODE_TAR)) # The Projected Reality (Immutable InitRD)
|
||||
mounts.add(MountPoint(prefix: "/state", mode: MODE_RAM)) # The Mutable Dust (Transient)
|
||||
|
||||
proc resolve_path(path: string): (VFSMode, string) =
|
||||
for m in mounts:
|
||||
if path.startsWith(m.prefix):
|
||||
let sub = if path.len > m.prefix.len: path[m.prefix.len..^1] else: "/"
|
||||
return (m.mode, sub)
|
||||
return (MODE_TAR, path)
|
||||
|
||||
# Syscall implementation procs
|
||||
# Kernel Imports
|
||||
# (Currently unused, relying on kprintln from kernel)
|
||||
proc ion_vfs_open*(path: cstring, flags: int32): int32 {.exportc, cdecl.} =
|
||||
let p = $path
|
||||
let (mode, sub) = resolve_path(p)
|
||||
|
||||
var fd = -1
|
||||
case mode:
|
||||
of MODE_TAR: fd = tar.vfs_open(sub, flags)
|
||||
of MODE_SFS: fd = 0 # Placeholder for SFS open
|
||||
of MODE_RAM: fd = tar.vfs_open(sub, flags) # Using TAR's RamFS for now
|
||||
|
||||
if fd > 0:
|
||||
let kernel_fd = next_fd
|
||||
fds[kernel_fd] = FileHandle(path: sub, offset: 0, mode: mode, is_ram: (mode == MODE_RAM))
|
||||
next_fd += 1
|
||||
return int32(kernel_fd)
|
||||
return -1
|
||||
|
||||
proc ion_vfs_read*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
|
||||
let ifd = int(fd)
|
||||
if not fds.hasKey(ifd): return -1
|
||||
let fh = addr fds[ifd]
|
||||
|
||||
case fh.mode:
|
||||
of MODE_TAR, MODE_RAM:
|
||||
let n = tar.vfs_read_at(fh.path, buf, count, fh.offset)
|
||||
if n > 0: fh.offset += uint64(n)
|
||||
return n
|
||||
of MODE_SFS:
|
||||
# SFS current read-whole-file shim
|
||||
var temp_buf: array[4096, byte] # FIXME: Small stack buffer
|
||||
let total = sfs.sfs_read_file(cstring(fh.path), addr temp_buf[0], 4096)
|
||||
if total < 0: return -1
|
||||
if fh.offset >= uint64(total): return 0
|
||||
let avail = uint64(total) - fh.offset
|
||||
let actual = min(count, avail)
|
||||
if actual > 0:
|
||||
copyMem(buf, addr temp_buf[int(fh.offset)], int(actual))
|
||||
fh.offset += actual
|
||||
return int64(actual)
|
||||
|
||||
proc ion_vfs_write*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
|
||||
let ifd = int(fd)
|
||||
if not fds.hasKey(ifd): return -1
|
||||
let fh = addr fds[ifd]
|
||||
|
||||
case fh.mode:
|
||||
of MODE_TAR, MODE_RAM:
|
||||
let n = tar.vfs_write_at(fh.path, buf, count, fh.offset)
|
||||
if n > 0: fh.offset += uint64(n)
|
||||
return n
|
||||
of MODE_SFS:
|
||||
sfs.sfs_write_file(cstring(fh.path), cast[cstring](buf), int(count))
|
||||
return int64(count)
|
||||
|
||||
proc ion_vfs_close*(fd: int32): int32 {.exportc, cdecl.} =
|
||||
let ifd = int(fd)
|
||||
if fds.hasKey(ifd):
|
||||
fds.del(ifd)
|
||||
return 0
|
||||
return -1
|
||||
|
||||
proc ion_vfs_list*(buf: pointer, max_len: uint64): int64 {.exportc, cdecl.} =
|
||||
var s = "/nexus\n/sysro\n/state\n"
|
||||
for name in tar.vfs_get_names():
|
||||
s.add("/sysro/" & name & "\n")
|
||||
|
||||
# Add SFS files under /nexus
|
||||
let sfs_names = sfs.sfs_get_files()
|
||||
for line in sfs_names.splitLines():
|
||||
if line.len > 0:
|
||||
s.add("/nexus/" & line & "\n")
|
||||
|
||||
let n = min(s.len, int(max_len))
|
||||
if n > 0: copyMem(buf, addr s[0], n)
|
||||
return int64(n)
|
||||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Invariant Verification (The Shield)
|
||||
|
||||
# import ion # Included in ion.nim
|
||||
|
||||
# Error type for future use
|
||||
|
|
|
|||
40
core/ion.nim
40
core/ion.nim
|
|
@ -1,5 +1,16 @@
|
|||
# core/rumpk/core/ion.nim
|
||||
# Phase 35e: Expanded SysTable with Crypto + Global Channels
|
||||
# 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.
|
||||
|
||||
## Rumpk Layer 1: ION Interface (The Sovereign Protocol)
|
||||
##
|
||||
## Defines the core communication protocol between Kernel and Userland.
|
||||
## Implements the SysTable structure, packet types, and Sovereign Channels.
|
||||
##
|
||||
## SAFETY: Provides the ABI contract for lock-free communication.
|
||||
|
||||
# CRITICAL: Only import memory module for kernel builds
|
||||
# Userspace builds (with -d:is_membrane) should NOT get the 2MB pool
|
||||
|
|
@ -93,11 +104,17 @@ type
|
|||
# Phase 35e: Crypto
|
||||
fn_siphash*: proc(key: ptr array[16, byte], data: pointer, len: uint64, out_hash: ptr array[16, byte]) {.cdecl.}
|
||||
fn_ed25519_verify*: proc(sig: ptr array[64, byte], msg: pointer, len: uint64, pk: ptr array[32, byte]): bool {.cdecl.}
|
||||
# SPEC-021: Monolith Key Derivation
|
||||
fn_blake3*: proc(data: pointer, len: uint64, out_hash: ptr array[32, byte]) {.cdecl.}
|
||||
|
||||
# Phase 36.2: Network Membrane (The Veins)
|
||||
s_net_rx*: ptr HAL_Ring[IonPacket] # Kernel Producer -> User Consumer
|
||||
s_net_tx*: ptr HAL_Ring[IonPacket] # User Producer -> Kernel Consumer
|
||||
|
||||
# Phase 36.3: Shared ION (16 bytes)
|
||||
fn_ion_alloc*: proc(out_id: ptr uint16): uint64 {.cdecl.}
|
||||
fn_ion_free*: proc(id: uint16) {.cdecl.}
|
||||
|
||||
include invariant
|
||||
|
||||
# --- Sovereign Logic ---
|
||||
|
|
@ -108,12 +125,14 @@ proc hal_channel_pop*(ring: uint64, out_pkt: ptr IonPacket): bool {.importc, cde
|
|||
proc hal_cmd_push*(ring: uint64, pkt: CmdPacket): bool {.importc, cdecl.}
|
||||
proc hal_cmd_pop*(ring: uint64, out_pkt: ptr CmdPacket): bool {.importc, cdecl.}
|
||||
|
||||
proc send*[T](c: var SovereignChannel[T], pkt: T) =
|
||||
if c.ring == nil: return
|
||||
proc send*[T](c: var SovereignChannel[T], pkt: T): bool =
|
||||
if c.ring == nil: return false
|
||||
when T is IonPacket:
|
||||
discard hal_channel_push(cast[uint64](c.ring), pkt)
|
||||
return hal_channel_push(cast[uint64](c.ring), pkt)
|
||||
elif T is CmdPacket:
|
||||
discard hal_cmd_push(cast[uint64](c.ring), pkt)
|
||||
return hal_cmd_push(cast[uint64](c.ring), pkt)
|
||||
else:
|
||||
return false
|
||||
|
||||
proc recv*[T](c: var SovereignChannel[T], out_pkt: var T): bool =
|
||||
if c.ring == nil: return false
|
||||
|
|
@ -129,8 +148,10 @@ var guest_input_hal: HAL_Ring[IonPacket]
|
|||
# Phase 36.2: Network Channels
|
||||
var chan_net_rx*: SovereignChannel[IonPacket]
|
||||
var chan_net_tx*: SovereignChannel[IonPacket]
|
||||
var chan_netswitch_rx*: SovereignChannel[IonPacket] # Internal: Driver -> NetSwitch
|
||||
var net_rx_hal: HAL_Ring[IonPacket]
|
||||
var net_tx_hal: HAL_Ring[IonPacket]
|
||||
var netswitch_rx_hal: HAL_Ring[IonPacket]
|
||||
|
||||
proc ion_init_input*() {.exportc, cdecl.} =
|
||||
guest_input_hal.head = 0
|
||||
|
|
@ -149,6 +170,11 @@ proc ion_init_network*() {.exportc, cdecl.} =
|
|||
net_tx_hal.mask = 255
|
||||
chan_net_tx.ring = addr net_tx_hal
|
||||
|
||||
netswitch_rx_hal.head = 0
|
||||
netswitch_rx_hal.tail = 0
|
||||
netswitch_rx_hal.mask = 255
|
||||
chan_netswitch_rx.ring = addr netswitch_rx_hal
|
||||
|
||||
static: doAssert(sizeof(IonPacket) == 24, "IonPacket size mismatch!")
|
||||
static: doAssert(sizeof(CmdPacket) == 32, "CmdPacket size mismatch!")
|
||||
static: doAssert(sizeof(SysTable) == 168, "SysTable size mismatch! (Expected 168 after Network expansion)")
|
||||
static: doAssert(sizeof(SysTable) == 192, "SysTable size mismatch! (Expected 192 after BLAKE3 expansion)")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: ION Slab Allocator
|
||||
|
||||
# ION Memory Manager
|
||||
# The "Slab Allocator" for Zero-Copy IO
|
||||
|
||||
|
|
@ -90,13 +99,13 @@ proc ion_free*(pkt: IonPacket) {.exportc.} =
|
|||
|
||||
# Helper for C/Zig Interop (Pure Pointers)
|
||||
# Return physical address of a allocated block, put ID in out_id
|
||||
proc ion_alloc_raw*(out_id: ptr uint16): uint64 {.exportc.} =
|
||||
proc ion_alloc_raw*(out_id: ptr uint16): uint64 {.exportc, cdecl.} =
|
||||
let pkt = ion_alloc()
|
||||
if pkt.data == nil: return 0
|
||||
out_id[] = pkt.id
|
||||
return pkt.phys
|
||||
|
||||
proc ion_free_raw*(id: uint16) {.exportc.} =
|
||||
proc ion_free_raw*(id: uint16) {.exportc, cdecl.} =
|
||||
var pkt: IonPacket
|
||||
pkt.id = id
|
||||
# We don't reconstruct data/phys for free, just push ID
|
||||
|
|
|
|||
364
core/kernel.nim
364
core/kernel.nim
|
|
@ -1,9 +1,17 @@
|
|||
# Copyright (c) 2026 Nexus Foundation
|
||||
# Licensed under the Libertaria Sovereign License (LSL-1.0)
|
||||
# See legal/LICENSE_SOVEREIGN.md for details.
|
||||
# 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.
|
||||
|
||||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# Rumpk Layer 1: The Logic Core (Autonomous Immune System)
|
||||
## Rumpk Layer 1: The Logic Core (Autonomous Immune System)
|
||||
##
|
||||
## The primary kernel orchestrator. Handles boot sequence, service initialization,
|
||||
## and the main system loop. Manages the transition from HAL (L0) to Userland.
|
||||
##
|
||||
## DECISION(Kernel): Cooperative scheduling is used to ensure deterministic
|
||||
## execution of immune system fibers.
|
||||
|
||||
{.push stackTrace: off, lineTrace: off.}
|
||||
|
||||
|
|
@ -12,9 +20,16 @@ import ion
|
|||
import loader
|
||||
import fs/tar
|
||||
import fs/sfs
|
||||
import fs/vfs
|
||||
import netswitch
|
||||
import ../libs/membrane/net_glue
|
||||
import ../libs/membrane/compositor
|
||||
import sched
|
||||
|
||||
# Phase 31: Memory Manager imports (must be before usage)
|
||||
proc mm_init() {.importc, cdecl.}
|
||||
proc mm_enable_kernel_paging() {.importc, cdecl.}
|
||||
proc mm_activate_satp(satp_val: uint64) {.importc, cdecl.}
|
||||
|
||||
var ion_paused*: bool = false
|
||||
var pause_start*: uint64 = 0
|
||||
|
|
@ -63,7 +78,7 @@ proc wrapper_vfs_write(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}
|
|||
|
||||
var fiber_ion: FiberObject
|
||||
var fiber_nexshell: FiberObject
|
||||
var fiber_ui: FiberObject
|
||||
# fiber_ui removed (unused)
|
||||
var fiber_subject: FiberObject
|
||||
var fiber_watchdog: FiberObject
|
||||
var fiber_compositor: FiberObject
|
||||
|
|
@ -76,7 +91,7 @@ var worker_stacks: array[MAX_WORKERS, array[8192, uint8]]
|
|||
var worker_active: array[MAX_WORKERS, bool]
|
||||
var next_worker_id: uint64 = 100 # Start worker IDs at 100
|
||||
|
||||
var subject_loading_path: string = "bin/nipbox"
|
||||
var subject_loading_path: string = "/init"
|
||||
|
||||
proc subject_fiber_entry() {.cdecl.} =
|
||||
## The Sovereign Container for Userland Consciousness.
|
||||
|
|
@ -88,27 +103,33 @@ proc subject_fiber_entry() {.cdecl.} =
|
|||
let entry = kload(subject_loading_path)
|
||||
if entry != 0:
|
||||
kprintln("[Subject] Consciousness Transferred.")
|
||||
|
||||
# CRITICAL FIX: Activate userland Sv39 page table before sret
|
||||
# Without this, userland accesses unmapped memory → page fault → M-mode reset
|
||||
if current_fiber.satp_value != 0:
|
||||
kprint("[Subject] Activating userland MMU, satp=")
|
||||
kprint_hex(current_fiber.satp_value)
|
||||
kprintln("")
|
||||
mm_activate_satp(current_fiber.satp_value)
|
||||
|
||||
rumpk_enter_userland(entry)
|
||||
else:
|
||||
kprint("[Subject] Failed to load: ")
|
||||
kprintln(cstring(subject_loading_path))
|
||||
|
||||
kprintln("[Subject] Pausing for Rebirth.")
|
||||
fiber.switch(addr fiber_ion) # Emergency yield to master
|
||||
fiber_sleep(1000)
|
||||
# fiber.switch(addr fiber_ion) # Emergency yield to master
|
||||
|
||||
# --- STACK ALLOCATIONS ---
|
||||
var stack_ion {.align: 4096.}: array[4096, uint8]
|
||||
var stack_nexshell {.align: 4096.}: array[4096, uint8]
|
||||
var stack_ui {.align: 4096.}: array[32768, uint8]
|
||||
var stack_ion {.align: 4096.}: array[32768, uint8]
|
||||
var stack_nexshell {.align: 4096.}: array[32768, uint8]
|
||||
# var stack_ui {.align: 4096.}: array[32768, uint8]
|
||||
var stack_subject {.align: 4096.}: array[32768, uint8]
|
||||
var stack_watchdog {.align: 4096.}: array[4096, uint8]
|
||||
var stack_netswitch {.align: 4096.}: array[8192, uint8] # Phase 36.2
|
||||
var stack_netswitch {.align: 4096.}: array[128 * 1024, uint8] # Phase 36.2
|
||||
var stack_compositor {.align: 4096.}: array[128 * 1024, uint8]
|
||||
|
||||
# Phase 31: Memory Manager (The Glass Cage)
|
||||
proc mm_init() {.importc, cdecl.}
|
||||
proc mm_enable_kernel_paging() {.importc, cdecl.}
|
||||
|
||||
# HAL Framebuffer imports (Phase 26: Visual Cortex)
|
||||
proc fb_kern_get_addr(): uint64 {.importc, cdecl.}
|
||||
# --- INITRD SYMBOLS ---
|
||||
|
|
@ -122,10 +143,10 @@ var binary_initrd_tar_end {.importc: "_initrd_end".}: char
|
|||
const SYSTABLE_BASE = 0x83000000'u64
|
||||
|
||||
# Global Rings (The Pipes - L0 Physics)
|
||||
var guest_rx_hal: HAL_Ring[IonPacket]
|
||||
var guest_tx_hal: HAL_Ring[IonPacket]
|
||||
var guest_event_hal: HAL_Ring[IonPacket]
|
||||
var guest_cmd_hal: HAL_Ring[CmdPacket]
|
||||
# guest_rx_hal removed (unused)
|
||||
# guest_tx_hal removed (unused)
|
||||
# guest_event_hal removed (unused)
|
||||
# var guest_cmd_hal: HAL_Ring[CmdPacket]
|
||||
|
||||
# Shared Channels (The Valves - L1 Logic)
|
||||
# Shared Channels
|
||||
|
|
@ -149,18 +170,34 @@ proc ion_push_stdin*(p: pointer, len: csize_t) {.exportc, cdecl.} =
|
|||
|
||||
kprintln("[Kernel] Input packet pushed to ring")
|
||||
|
||||
# Phase 37: Direct routing (Compositor not yet operational)
|
||||
chan_input.send(pkt)
|
||||
# Wake up Subject if it was waiting for input
|
||||
if fiber_subject.sleep_until == 0xFFFFFFFFFFFFFFFF'u64:
|
||||
fiber_subject.sleep_until = 0
|
||||
|
||||
proc get_ion_load(): int =
|
||||
## Calculate load of the Command Ring (The Heartbeat of the NPLs)
|
||||
let head = guest_cmd_hal.head
|
||||
let tail = guest_cmd_hal.tail
|
||||
let mask = guest_cmd_hal.mask
|
||||
return int((head - tail) and mask)
|
||||
# Phase 37: Direct routing (Compositor not yet operational)
|
||||
discard chan_input.send(pkt)
|
||||
|
||||
# get_ion_load removed (unused)
|
||||
|
||||
proc rumpk_yield_internal() {.cdecl, exportc.}
|
||||
|
||||
# [EXISTING] Network Membrane Imports (via C ABI to resolve module cycles)
|
||||
proc libc_is_socket_fd(fd: int): bool {.importc, cdecl.}
|
||||
proc libc_impl_socket(domain, sock_type, proto: int): int {.importc, cdecl.}
|
||||
proc libc_impl_bind(fd: int, addr_ptr: pointer, len: int): int {.importc, cdecl.}
|
||||
proc libc_impl_connect(fd: int, addr_ptr: pointer, len: int): int {.importc, cdecl.}
|
||||
proc libc_impl_listen(fd: int, backlog: int): int {.importc, cdecl.}
|
||||
proc libc_impl_accept(fd: int, addr_ptr: pointer, len_ptr: pointer): int {.importc, cdecl.}
|
||||
proc libc_impl_recv(fd: int, buf: pointer, count: uint64): int {.importc, cdecl.}
|
||||
proc libc_impl_send(fd: int, buf: pointer, count: uint64): int {.importc, cdecl.}
|
||||
# Sockets handled via unified close
|
||||
|
||||
# [ADDED] Unified File System Imports (The VFS Bridge)
|
||||
proc libc_impl_open(path: cstring, flags: int): int {.importc, cdecl.}
|
||||
proc libc_impl_close(fd: int): int {.importc, cdecl.}
|
||||
proc libc_impl_read(fd: int, buf: pointer, count: uint64): int {.importc, cdecl.}
|
||||
proc libc_impl_write(fd: int, buf: pointer, count: uint64): int {.importc, cdecl.}
|
||||
|
||||
# HAL Driver API
|
||||
proc hal_io_init() {.importc, cdecl.}
|
||||
proc virtio_net_poll() {.importc, cdecl.}
|
||||
|
|
@ -168,9 +205,8 @@ proc virtio_net_send(data: pointer, len: uint32) {.importc, cdecl.}
|
|||
proc rumpk_yield_guard() {.importc, cdecl.}
|
||||
proc virtio_blk_read(sector: uint64, buf: pointer) {.importc, cdecl.}
|
||||
proc virtio_blk_write(sector: uint64, buf: pointer) {.importc, cdecl.}
|
||||
proc ion_free_raw(id: uint16) {.importc, cdecl.}
|
||||
proc nexshell_main() {.importc, cdecl.}
|
||||
proc ui_fiber_entry() {.importc, cdecl.}
|
||||
# ui_fiber_entry removed (unused)
|
||||
proc rumpk_halt() {.importc, cdecl, noreturn.}
|
||||
|
||||
proc compositor_fiber_entry() {.cdecl.} =
|
||||
|
|
@ -178,9 +214,9 @@ proc compositor_fiber_entry() {.cdecl.} =
|
|||
while true:
|
||||
compositor.compositor_step()
|
||||
# High frequency yield (120Hz goal)
|
||||
rumpk_yield_internal()
|
||||
fiber_sleep(10)
|
||||
|
||||
proc get_now_ns(): uint64 =
|
||||
proc get_now_ns(): uint64 {.exportc: "get_now_ns", cdecl.} =
|
||||
proc rumpk_timer_now_ns(): uint64 {.importc, cdecl.}
|
||||
return rumpk_timer_now_ns()
|
||||
|
||||
|
|
@ -193,52 +229,56 @@ proc fiber_sleep*(ms: int) {.exportc, cdecl.} =
|
|||
fiber_yield()
|
||||
|
||||
proc rumpk_yield_internal() {.cdecl, exportc.} =
|
||||
let now = get_now_ns()
|
||||
# The Reactive Dispatcher Integration (SPEC-250)
|
||||
let prev_fiber = current_fiber
|
||||
let start_ns = get_now_ns()
|
||||
|
||||
# Gather all potential fibers
|
||||
# Static Fibers
|
||||
var active_fibers_arr: array[16, ptr FiberObject]
|
||||
var count = 0
|
||||
|
||||
template addFiber(f: var FiberObject) =
|
||||
if count < 16:
|
||||
active_fibers_arr[count] = addr f
|
||||
inc count
|
||||
|
||||
# Normal Round Robin logic with Sleep Check
|
||||
var next_fiber: Fiber = nil
|
||||
if fiber_compositor.stack != nil: addFiber(fiber_compositor)
|
||||
if fiber_netswitch.stack != nil: addFiber(fiber_netswitch)
|
||||
if fiber_ion.stack != nil: addFiber(fiber_ion)
|
||||
if fiber_nexshell.stack != nil: addFiber(fiber_nexshell)
|
||||
if fiber_subject.stack != nil: addFiber(fiber_subject)
|
||||
if fiber_watchdog.stack != nil: addFiber(fiber_watchdog)
|
||||
|
||||
# Dynamic Workers
|
||||
for i in 0..<MAX_WORKERS:
|
||||
if worker_active[i]:
|
||||
addFiber(worker_pool[i])
|
||||
|
||||
kprint("[Kernel] Active Fibers: "); kprint_hex(uint64(count)); kprintln("")
|
||||
|
||||
if current_fiber == addr fiber_ion:
|
||||
next_fiber = addr fiber_nexshell
|
||||
elif current_fiber == addr fiber_nexshell:
|
||||
next_fiber = addr fiber_subject
|
||||
elif current_fiber == addr fiber_subject:
|
||||
next_fiber = addr fiber_watchdog
|
||||
elif current_fiber == addr fiber_watchdog:
|
||||
next_fiber = addr fiber_ion
|
||||
else:
|
||||
next_fiber = addr fiber_ion
|
||||
# Execute Spectrum Scheduler
|
||||
if count > 0:
|
||||
if not sched_tick_spectrum(active_fibers_arr.toOpenArray(0, count - 1)):
|
||||
# The Silence Doctrine: WFI
|
||||
asm "csrsi sstatus, 2" # Ensure interrupts enabled
|
||||
asm "wfi"
|
||||
|
||||
# Post-Mortem: Analyze the previous fiber's burst (The Ratchet)
|
||||
let end_ns = get_now_ns()
|
||||
let burst_ns = end_ns - start_ns
|
||||
if prev_fiber != nil:
|
||||
sched_analyze_burst(prev_fiber, burst_ns)
|
||||
|
||||
# Skip sleeping fibers
|
||||
var found = false
|
||||
for _ in 0..6: # Max 6 check
|
||||
if next_fiber != nil and now >= next_fiber.sleep_until:
|
||||
found = true
|
||||
break
|
||||
|
||||
# Move to next in sequence
|
||||
if next_fiber == addr fiber_ion: next_fiber = addr fiber_nexshell
|
||||
elif next_fiber == addr fiber_nexshell: next_fiber = addr fiber_subject
|
||||
elif next_fiber == addr fiber_subject: next_fiber = addr fiber_watchdog
|
||||
elif next_fiber == addr fiber_watchdog: next_fiber = addr fiber_ion
|
||||
else: next_fiber = addr fiber_ion
|
||||
|
||||
# Force found = true for now
|
||||
found = true
|
||||
|
||||
if found and next_fiber != current_fiber:
|
||||
kprint("[Sched] "); kprint(current_fiber.name); kprint(" -> "); kprintln(next_fiber.name)
|
||||
switch(next_fiber)
|
||||
elif not found:
|
||||
asm "csrsi sstatus, 2"
|
||||
asm "wfi"
|
||||
|
||||
# =========================================================
|
||||
# ION Intelligence Fiber (Core System Supervisor)
|
||||
# =========================================================
|
||||
|
||||
proc ion_fiber_entry() {.cdecl.} =
|
||||
hal_io_init()
|
||||
# hal_io_init() -> ALREADY CALLED IN KMAIN
|
||||
sfs_mount()
|
||||
sfs_sync_vfs()
|
||||
kprintln("[ION] Fiber 1 Reporting for Duty.")
|
||||
while true:
|
||||
var cmd: CmdPacket
|
||||
|
|
@ -248,7 +288,7 @@ proc ion_fiber_entry() {.cdecl.} =
|
|||
matrix_enabled = (cmd.arg > 0)
|
||||
of uint32(CmdType.CMD_SYS_EXIT):
|
||||
kprintln("[Kernel] Subject Exited. Respawning...")
|
||||
subject_loading_path = "bin/nipbox"
|
||||
subject_loading_path = "/init"
|
||||
init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0], stack_subject.len)
|
||||
of uint32(CmdType.CMD_ION_STOP):
|
||||
ion_paused = true
|
||||
|
|
@ -277,22 +317,38 @@ proc ion_fiber_entry() {.cdecl.} =
|
|||
virtio_blk_write(args.sector, cast[pointer](args.buf))
|
||||
of uint32(CmdType.CMD_FS_WRITE):
|
||||
let args = cast[ptr FileArgs](cmd.arg)
|
||||
sfs_write_file(cast[cstring](args.name), cast[cstring](args.data), int(args.len))
|
||||
sfs.sfs_write_file(cast[cstring](args.name), cast[cstring](args.data), int(args.len))
|
||||
sfs_sync_vfs()
|
||||
of uint32(CmdType.CMD_FS_READ):
|
||||
let args = cast[ptr FileArgs](cmd.arg)
|
||||
let bytes_read = sfs_read_file(cast[cstring](args.name), cast[pointer](args.data), int(args.len))
|
||||
let bytes_read = sfs.sfs_read_file(cast[cstring](args.name), cast[pointer](args.data), int(args.len))
|
||||
args.len = uint64(bytes_read)
|
||||
else:
|
||||
discard
|
||||
fiber_yield()
|
||||
fiber_sleep(10) # 10ms poll
|
||||
|
||||
# Hardware Ingress (Zig -> Nim)
|
||||
proc ion_get_virt(id: uint16): pointer {.importc, cdecl.}
|
||||
proc ion_ingress*(id: uint16, len: uint16) {.exportc, cdecl.} =
|
||||
let data = ion_get_virt(id)
|
||||
var pkt = IonPacket(data: cast[ptr UncheckedArray[byte]](data), len: len, id: id)
|
||||
chan_rx.send(pkt)
|
||||
## Callback from VirtIO-Net HAL.
|
||||
## id: Slab index containing the packet.
|
||||
## len: Length of the ETHERNET FRAME (excluding VirtIO header).
|
||||
|
||||
let v_base = ion_get_virt(id)
|
||||
let p_base = ion_get_phys(id)
|
||||
|
||||
# VirtIO-Net Header is 10 bytes (non-mergeable).
|
||||
# We offset the packet pointers to point directly to the Ethernet Frame.
|
||||
let eth_v = cast[ptr UncheckedArray[byte]](cast[uint64](v_base) + 10)
|
||||
let eth_p = p_base + 10
|
||||
|
||||
var pkt = IonPacket(data: eth_v, phys: eth_p, len: len, id: id)
|
||||
|
||||
# Push to NetSwitch internal pipe for demultiplexing
|
||||
if not chan_netswitch_rx.send(pkt):
|
||||
# Backpressure: If NetSwitch is full, we must drop the packet to avoid leaked slabs
|
||||
# kprintln("[Kernel] NetSwitch RX Full - Dropping Packet")
|
||||
ion_free_raw(id)
|
||||
|
||||
# Panic Handler
|
||||
proc nimPanic(msg: cstring) {.exportc: "panic", cdecl, noreturn.} =
|
||||
|
|
@ -385,6 +441,7 @@ proc k_check_deferred_yield*() {.exportc, cdecl.} =
|
|||
fiber_yield()
|
||||
|
||||
|
||||
|
||||
proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
|
||||
# kprint("[Syscall] "); kprint_hex(nr); kprintln("")
|
||||
if nr != 0x100: # Ignore YIELD noise
|
||||
|
|
@ -394,81 +451,125 @@ proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
|
|||
of 0x01: # EXIT
|
||||
kprintln("[Kernel] Subject EXIT Triggered")
|
||||
var pkt = CmdPacket(kind: uint32(CmdType.CMD_SYS_EXIT), arg: a0)
|
||||
chan_cmd.send(pkt)
|
||||
discard chan_cmd.send(pkt)
|
||||
current_fiber.wants_yield = true
|
||||
return 0
|
||||
of 0x100: # YIELD
|
||||
current_fiber.wants_yield = true
|
||||
return 0
|
||||
of 0x101: # PLEDGE
|
||||
# Only allow reducing privileges? For now, allow setting.
|
||||
current_fiber.promises = a0
|
||||
return 0
|
||||
of 0x200: # OPEN
|
||||
|
||||
# [UPDATED] 0x200: OPEN - Route through Unified LibC
|
||||
of 0x200:
|
||||
let flags = int32(a1)
|
||||
if (flags and 0x01) != 0:
|
||||
# Check permissions (0=RDONLY, 1=WRONLY, 2=RDWR)
|
||||
if (flags and 0x03) != 0:
|
||||
if (current_fiber.promises and PLEDGE_WPATH) == 0: return cast[uint](-1)
|
||||
else:
|
||||
if (current_fiber.promises and PLEDGE_RPATH) == 0: return cast[uint](-1)
|
||||
return uint(ion_vfs_open(cast[cstring](a0), flags))
|
||||
of 0x201: # CLOSE
|
||||
return uint(ion_vfs_close(int32(a0)))
|
||||
of 0x202: # LIST
|
||||
|
||||
# Call the new unified implementation
|
||||
return uint(libc_impl_open(cast[cstring](a0), int(flags)))
|
||||
|
||||
# [UPDATED] 0x201: CLOSE - Unified close
|
||||
of 0x201:
|
||||
return uint(libc_impl_close(int(a0)))
|
||||
|
||||
of 0x202: # LIST / READDIR
|
||||
if (current_fiber.promises and PLEDGE_RPATH) == 0: return cast[uint](-1)
|
||||
return uint(ion_vfs_list(cast[pointer](a0), uint64(a1)))
|
||||
of 0x203: # READ
|
||||
if a0 == 0:
|
||||
|
||||
# [UPDATED] 0x203: READ - Unified Dispatch
|
||||
of 0x203:
|
||||
if a0 == 0: # STDIN Special Case
|
||||
kprintln("[Kernel] sys_read(0) - STDIN request")
|
||||
if (current_fiber.promises and PLEDGE_STDIO) == 0: return cast[uint](-1)
|
||||
var pkt: IonPacket
|
||||
if chan_input.recv(pkt):
|
||||
kprintln("[Kernel] sys_read(0) - Data available")
|
||||
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))
|
||||
ion_free_raw(pkt.id)
|
||||
return n
|
||||
else:
|
||||
kprintln("[Kernel] sys_read(0) - No data, yielding")
|
||||
current_fiber.wants_yield = true
|
||||
return 0
|
||||
|
||||
# Check if it's a socket
|
||||
if libc_is_socket_fd(int(a0)):
|
||||
return uint(libc_impl_recv(int(a0), cast[pointer](a1), uint64(a2)))
|
||||
|
||||
# Permission Check
|
||||
if (current_fiber.promises and PLEDGE_RPATH) == 0: return cast[uint](-1)
|
||||
return uint(ion_vfs_read(int32(a0), cast[pointer](a1), uint64(a2)))
|
||||
of 0x204: # WRITE
|
||||
# Bypass optimization for now to test stability
|
||||
return uint(ion_vfs_write(int32(a0), cast[pointer](a1), uint64(a2)))
|
||||
of 0x300: # SURFACE_CREATE
|
||||
return uint(compositor.create_surface(int(a0), int(a1)))
|
||||
of 0x301: # SURFACE_FLIP
|
||||
return 0
|
||||
of 0x302: # SURFACE_GET_PTR
|
||||
return cast[uint](compositor.hal_surface_get_ptr(int32(a0)))
|
||||
of 0x500: # SPAWN
|
||||
return uint(k_spawn(cast[pointer](a0), uint64(a1)))
|
||||
of 0x501: # JOIN
|
||||
return uint(k_join(uint64(a0)))
|
||||
of 0x100: # YIELD
|
||||
# Deferred yield: Set flag, yield happens after trap return
|
||||
current_fiber.wants_yield = true
|
||||
return 0
|
||||
of 0x220: # BLK_READ - Raw Sector Read (Block Valve)
|
||||
# a0 = sector, a1 = buffer pointer (userland), a2 = count (sectors)
|
||||
|
||||
# Route to Sovereign FS via Unified LibC
|
||||
return uint(libc_impl_read(int(a0), cast[pointer](a1), uint64(a2)))
|
||||
|
||||
# [UPDATED] 0x204: WRITE - Unified Dispatch
|
||||
of 0x204:
|
||||
if a0 == 1 or a0 == 2: # STDOUT/STDERR
|
||||
kprintln("[Kernel] sys_write(stdout) called")
|
||||
console_write(cast[pointer](a1), csize_t(a2))
|
||||
kprintln("[Kernel] sys_write(stdout) returning")
|
||||
return a2
|
||||
|
||||
# Check if it's a socket
|
||||
if libc_is_socket_fd(int(a0)):
|
||||
return uint(libc_impl_send(int(a0), cast[pointer](a1), uint64(a2)))
|
||||
|
||||
# Permission Check
|
||||
if (current_fiber.promises and PLEDGE_WPATH) == 0: return cast[uint](-1)
|
||||
|
||||
# Route to Sovereign FS via Unified LibC
|
||||
return uint(libc_impl_write(int(a0), cast[pointer](a1), uint64(a2)))
|
||||
|
||||
# BLOCK VALVE (SPEC-500)
|
||||
of 0x220: # BLK_READ
|
||||
if (current_fiber.promises and PLEDGE_RPATH) == 0: return cast[uint](-1)
|
||||
var buf: array[512, byte]
|
||||
virtio_blk_read(uint64(a0), addr buf[0])
|
||||
copyMem(cast[pointer](a1), addr buf[0], 512)
|
||||
return 512
|
||||
of 0x221: # BLK_WRITE - Raw Sector Write (Block Valve)
|
||||
# a0 = sector, a1 = buffer pointer (userland), a2 = count (sectors)
|
||||
of 0x221: # BLK_WRITE
|
||||
if (current_fiber.promises and PLEDGE_WPATH) == 0: return cast[uint](-1)
|
||||
virtio_blk_write(uint64(a0), cast[ptr byte](a1))
|
||||
return 512
|
||||
of 0x222: # BLK_SYNC - Flush (Block Valve)
|
||||
# VirtIO block is synchronous, so this is a no-op for now
|
||||
of 0x222: # BLK_SYNC
|
||||
return 0
|
||||
of 0: # EXIT
|
||||
fiber_yield()
|
||||
|
||||
# SURFACE MANAGER (SPEC-600)
|
||||
of 0x300: return uint(compositor.create_surface(int(a0), int(a1)))
|
||||
of 0x301: return 0 # FLIP
|
||||
of 0x302: return cast[uint](compositor.hal_surface_get_ptr(int32(a0)))
|
||||
|
||||
# HIVE / WORKERS (SPEC-200)
|
||||
of 0x500: return uint(k_spawn(cast[pointer](a0), uint64(a1)))
|
||||
of 0x501: return uint(k_join(uint64(a0)))
|
||||
|
||||
# PHOENIX / UPGRADE
|
||||
of 0x600:
|
||||
kprintln("\n[Kernel] SYSTEM PHOENIX ACTIVATED.")
|
||||
proc hal_kexec(entry, dtb: uint64) {.importc, cdecl.}
|
||||
hal_kexec(uint64(a0), 0)
|
||||
return 0
|
||||
|
||||
# NETWORK MEMBRANE (SPEC-400)
|
||||
of 0x900: return uint(libc_impl_socket(int(a0), int(a1), int(a2)))
|
||||
of 0x901: return uint(libc_impl_bind(int(a0), cast[pointer](a1), int(a2)))
|
||||
of 0x902: return uint(libc_impl_connect(int(a0), cast[pointer](a1), int(a2)))
|
||||
of 0x903: return uint(libc_impl_listen(int(a0), int(a1)))
|
||||
of 0x904: return uint(libc_impl_accept(int(a0), cast[pointer](a1), cast[pointer](a2)))
|
||||
|
||||
else:
|
||||
return 0
|
||||
|
||||
proc kmain() {.exportc, cdecl.} =
|
||||
kprintln("\n\n")
|
||||
kprintln("╔═══════════════════════════════════════╗")
|
||||
kprintln("║ NEXUS RUMK v1.1 - SOVEREIGN ║")
|
||||
kprintln("║ NEXUS SOVEREIGN CORE v1.1 ║")
|
||||
kprintln("╚═══════════════════════════════════════╝")
|
||||
|
||||
kprint("[Kernel] current_fiber Addr: "); kprint_hex(cast[uint64](addr current_fiber)); kprintln("")
|
||||
|
|
@ -497,8 +598,7 @@ proc kmain() {.exportc, cdecl.} =
|
|||
hal_io_init()
|
||||
|
||||
vfs_init(addr binary_initrd_tar_start, addr binary_initrd_tar_end)
|
||||
sfs_mount()
|
||||
sfs_sync_vfs()
|
||||
vfs_mount_init()
|
||||
|
||||
let sys = cast[ptr SysTable](SYSTABLE_BASE)
|
||||
sys.fn_vfs_open = ion_vfs_open
|
||||
|
|
@ -513,9 +613,11 @@ proc kmain() {.exportc, cdecl.} =
|
|||
# Phase 35e: Crypto HAL integration
|
||||
proc hal_crypto_siphash(key: ptr array[16, byte], data: pointer, len: uint64, out_hash: ptr array[16, byte]) {.importc, cdecl.}
|
||||
proc hal_crypto_ed25519_verify(sig: ptr array[64, byte], msg: pointer, len: uint64, pk: ptr array[32, byte]): bool {.importc, cdecl.}
|
||||
proc hal_crypto_blake3(data: pointer, len: uint64, out_hash: ptr array[32, byte]) {.importc, cdecl.}
|
||||
|
||||
sys.fn_siphash = hal_crypto_siphash
|
||||
sys.fn_ed25519_verify = hal_crypto_ed25519_verify
|
||||
sys.fn_blake3 = hal_crypto_blake3
|
||||
|
||||
# GPU disabled temporarily until display works
|
||||
# proc virtio_gpu_init(base: uint64) {.importc, cdecl.}
|
||||
|
|
@ -561,6 +663,20 @@ proc kmain() {.exportc, cdecl.} =
|
|||
|
||||
# Phase 36.2: Initialize Network Membrane BEFORE userland starts
|
||||
netswitch_init()
|
||||
|
||||
# OVERRIDE: Move Network Rings to Shared Memory (User Accessible)
|
||||
# Previous offsets: 0x1000..0x5000 used for RX/TX/Event/Cmd/Input
|
||||
let ring_net_rx_ptr = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0x6000)
|
||||
let ring_net_tx_ptr = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0x7000)
|
||||
|
||||
# Re-initialize shared rings (clearing stale kernel BSS state)
|
||||
ring_net_rx_ptr.head = 0; ring_net_rx_ptr.tail = 0; ring_net_rx_ptr.mask = 255
|
||||
ring_net_tx_ptr.head = 0; ring_net_tx_ptr.tail = 0; ring_net_tx_ptr.mask = 255
|
||||
|
||||
# Connect Valves to the new shared Pipes
|
||||
chan_net_rx.ring = ring_net_rx_ptr
|
||||
chan_net_tx.ring = ring_net_tx_ptr
|
||||
|
||||
netswitch_attach_systable(sys)
|
||||
|
||||
# Framebuffer info
|
||||
|
|
@ -570,16 +686,22 @@ proc kmain() {.exportc, cdecl.} =
|
|||
sys.fb_stride = 1920 * 4
|
||||
sys.fb_bpp = 32
|
||||
sys.fn_yield = rumpk_yield_guard
|
||||
sys.fn_ion_alloc = cast[proc(out_id: ptr uint16): uint64 {.cdecl.}](ion_alloc_raw)
|
||||
sys.fn_ion_free = cast[proc(id: uint16) {.cdecl.}](ion_free_raw)
|
||||
|
||||
kprintln("[Kernel] Spawning System Fibers...")
|
||||
fiber_ion.name = "ion"
|
||||
init_fiber(addr fiber_ion, ion_fiber_entry, addr stack_ion[0], sizeof(stack_ion))
|
||||
fiber_ion.promises = PLEDGE_ALL
|
||||
|
||||
# Compositor
|
||||
fiber_compositor.name = "compositor"
|
||||
init_fiber(addr fiber_compositor, compositor_fiber_entry, addr stack_compositor[0], sizeof(stack_compositor))
|
||||
fiber_compositor.promises = PLEDGE_ALL
|
||||
|
||||
fiber_nexshell.name = "nexshell"
|
||||
init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0], sizeof(stack_nexshell))
|
||||
fiber_nexshell.promises = PLEDGE_ALL
|
||||
|
||||
# Phase 31: Page Table root for worker isolation
|
||||
proc mm_create_worker_map(stack_base: uint64, stack_size: uint64, packet_addr: uint64): uint64 {.importc, cdecl.}
|
||||
|
|
@ -591,14 +713,26 @@ proc kmain() {.exportc, cdecl.} =
|
|||
|
||||
fiber_watchdog.name = "watchdog"
|
||||
init_fiber(addr fiber_watchdog, watchdog_loop, addr stack_watchdog[0], sizeof(stack_watchdog))
|
||||
fiber_watchdog.promises = PLEDGE_ALL
|
||||
|
||||
# Phase 36.2: NetSwitch Fiber (Traffic Cop)
|
||||
fiber_netswitch.name = "netswitch"
|
||||
init_fiber(addr fiber_netswitch, fiber_netswitch_entry, addr stack_netswitch[0], sizeof(stack_netswitch))
|
||||
fiber_netswitch.promises = PLEDGE_ALL # NetSwitch needs full power
|
||||
|
||||
kprintln("[Kernel] Enabling Supervisor Interrupts (SIE)...")
|
||||
asm "csrsi sstatus, 2"
|
||||
|
||||
# Assign Spectra (The Caste System)
|
||||
setSpectrum(addr fiber_compositor, Spectrum.Photon) # 120Hz Critical
|
||||
setSpectrum(addr fiber_netswitch, Spectrum.Photon) # Line-rate Polling
|
||||
|
||||
setSpectrum(addr fiber_ion, Spectrum.Matter) # System Logic
|
||||
setSpectrum(addr fiber_nexshell, Spectrum.Gravity) # Human Inputs (Polling)
|
||||
|
||||
setSpectrum(addr fiber_subject, Spectrum.Matter) # User Payload (Promoted for Bootstrap)
|
||||
setSpectrum(addr fiber_watchdog, Spectrum.Photon) # Safety Critical (Keepalives)
|
||||
|
||||
kprintln("[Kernel] All Systems Go. Entering Autonomous Loop.")
|
||||
switch(addr fiber_ion)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Application Loader (The Breath of Life)
|
||||
|
||||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# Rumpk Phase 8: The Summoning (ELF Loader)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: ELF Binary Parser
|
||||
|
||||
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
# ELF64 Header Definitions for Rumpk Summoning
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Software Network Switch
|
||||
|
||||
# core/rumpk/core/netswitch.nim
|
||||
# Phase 36.2: The Traffic Cop (Network Membrane Layer 2 Switch)
|
||||
#
|
||||
|
|
@ -13,6 +22,7 @@ import ion
|
|||
|
||||
# Forward declare fiber_yield to avoid circular import
|
||||
proc fiber_yield*() {.importc, cdecl.}
|
||||
proc fiber_sleep*(ms: int) {.importc, cdecl.}
|
||||
|
||||
# HAL Imports
|
||||
proc virtio_net_poll() {.importc, cdecl.}
|
||||
|
|
@ -20,6 +30,13 @@ proc virtio_net_send(data: pointer, len: uint32) {.importc, cdecl.}
|
|||
|
||||
# Logging
|
||||
proc kprintln(s: cstring) {.importc, cdecl.}
|
||||
proc kprint(s: cstring) {.importc, cdecl.}
|
||||
proc kprint_hex(v: uint64) {.importc, cdecl.}
|
||||
proc get_now_ns(): uint64 {.importc, cdecl.}
|
||||
|
||||
# Membrane Infrastructure (LwIP Glue)
|
||||
proc membrane_init*() {.importc, cdecl.}
|
||||
proc pump_membrane_stack*() {.importc, cdecl.}
|
||||
|
||||
var netswitch_initialized: bool = false
|
||||
|
||||
|
|
@ -36,42 +53,95 @@ proc netswitch_attach_systable*(sys: ptr SysTable) =
|
|||
sys.s_net_tx = chan_net_tx.ring
|
||||
kprintln("[NetSwitch] SysTable Rings Attached")
|
||||
|
||||
type
|
||||
EthHeader* {.packed.} = object
|
||||
dst*: array[6, byte]
|
||||
src*: array[6, byte]
|
||||
ethertype*: uint16 # Big Endian
|
||||
|
||||
proc swap16(v: uint16): uint16 =
|
||||
((v and 0xFF) shl 8) or (v shr 8)
|
||||
|
||||
proc netswitch_process_packet(pkt: IonPacket): bool =
|
||||
## Layer 2 Demultiplexer
|
||||
if pkt.len < 14:
|
||||
ion_free(pkt)
|
||||
return false
|
||||
|
||||
let eth = cast[ptr EthHeader](pkt.data)
|
||||
let etype = swap16(eth.ethertype)
|
||||
|
||||
case etype:
|
||||
of 0x0800, 0x0806, 0x86DD: # IPv4, ARP, IPv6
|
||||
# Route to Legacy/LwIP Membrane
|
||||
if not chan_net_rx.send(pkt):
|
||||
# Ring full (Backpressure)
|
||||
ion_free(pkt)
|
||||
return false
|
||||
return true
|
||||
|
||||
of 0x88B5: # Sovereign UTCP (SPEC-410)
|
||||
# TODO: Route to dedicated UTCP channel
|
||||
# kprintln("[NetSwitch] UTCP Sovereign Packet Identified")
|
||||
ion_free(pkt)
|
||||
return true # Handled (dropped)
|
||||
|
||||
else:
|
||||
# Drop unknown EtherTypes (Security/Sovereignty)
|
||||
ion_free(pkt)
|
||||
return false
|
||||
|
||||
proc fiber_netswitch_entry*() {.cdecl.} =
|
||||
membrane_init()
|
||||
kprintln("[NetSwitch] Fiber Entry - The Traffic Cop is ON DUTY")
|
||||
|
||||
var rx_activity: bool = false
|
||||
var tx_activity: bool = false
|
||||
var rx_count: uint64 = 0
|
||||
var tx_count: uint64 = 0
|
||||
var last_stat_print: uint64 = 0
|
||||
|
||||
while true:
|
||||
rx_activity = false
|
||||
tx_activity = false
|
||||
|
||||
# ============================================
|
||||
# RX PATH: Hardware -> chan_net_rx -> Userland
|
||||
# ============================================
|
||||
# virtio_net_poll() internally calls ion_ingress() which pushes
|
||||
# received packets to the hardware driver's internal ring.
|
||||
# We poll here to drive the RX path.
|
||||
# 1. Drive the hardware poll (fills chan_netswitch_rx)
|
||||
virtio_net_poll()
|
||||
|
||||
# ============================================
|
||||
# TX PATH: Userland -> chan_net_tx -> Hardware
|
||||
# ============================================
|
||||
# 2. Drive the LwIP Stack (Timers/RX)
|
||||
pump_membrane_stack()
|
||||
|
||||
# 2. Consume from the Driver -> Switch internal ring
|
||||
var raw_pkt: IonPacket
|
||||
while chan_netswitch_rx.recv(raw_pkt):
|
||||
if netswitch_process_packet(raw_pkt):
|
||||
rx_activity = true
|
||||
inc rx_count
|
||||
|
||||
# 3. TX PATH: Userland -> Hardware
|
||||
var tx_pkt: IonPacket
|
||||
while chan_net_tx.recv(tx_pkt):
|
||||
if tx_pkt.data != nil and tx_pkt.len > 0:
|
||||
virtio_net_send(cast[pointer](tx_pkt.data), uint32(tx_pkt.len))
|
||||
inc tx_count
|
||||
ion_free(tx_pkt)
|
||||
tx_activity = true
|
||||
|
||||
# ============================================
|
||||
# YIELD STRATEGY
|
||||
# ============================================
|
||||
# 4. Periodically print stats
|
||||
let now = get_now_ns()
|
||||
if now - last_stat_print > 5000000000'u64: # 5 seconds
|
||||
kprint("[NetSwitch] STATS - RX: ")
|
||||
kprint_hex(rx_count)
|
||||
kprint(" TX: ")
|
||||
kprint_hex(tx_count)
|
||||
kprintln("")
|
||||
last_stat_print = now
|
||||
|
||||
# 5. Yield Strategy
|
||||
if rx_activity or tx_activity:
|
||||
# War Mode: Continue processing if we moved data
|
||||
# War Mode: High priority processing
|
||||
continue
|
||||
else:
|
||||
# Peace Mode: Yield to let other fibers run
|
||||
fiber_yield()
|
||||
fiber_sleep(10)
|
||||
|
||||
{.pop.}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Panic Override (Emergency Procedures)
|
||||
|
||||
# Rumpk Panic Override
|
||||
# Required for Nim --os:any / --os:standalone
|
||||
# This file must be named panicoverride.nim
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Simple Lock-Free Ring Buffers
|
||||
|
||||
# Rumpk Disruptor Ring Buffer
|
||||
# Lock-free O(1) inter-fiber communication
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: The Reactive Dispatcher (The Tyrant)
|
||||
##
|
||||
## Implements the Silence Doctrine (SPEC-250).
|
||||
## - No Tick.
|
||||
## - No Policy.
|
||||
## - Only Physics.
|
||||
|
||||
{.push stackTrace: off, lineTrace: off.}
|
||||
|
||||
import fiber
|
||||
|
||||
# We might need to access the Fiber globals from fiber.nim
|
||||
# fiber.nim exports current_fiber, but we need to iterate them.
|
||||
# Currently kernel.nim manages the specific fibers variables (fiber_ion, fiber_ui, etc.)
|
||||
# We need a centralized registry or a way to iterate.
|
||||
#
|
||||
# For the first pass, we can replicate the logic in kernel.nim which explicitly checks
|
||||
# the known fibers, but structured as the Spectrum loop.
|
||||
# Or we can make kernel.nim pass the fibers to us.
|
||||
#
|
||||
# Let's keep it simple and stateless in sched.nim if possible, or have it manage the queue.
|
||||
# Since kernel.nim holds the variables, sched.nim should probably define the *Strategy*
|
||||
# and kernel.nim calls it, OR sched.nim should import kernel (circular!).
|
||||
#
|
||||
# Better: fiber.nim holds a linked list of fibers?
|
||||
# Or sched.nim is just a helper module that kernel.nim uses.
|
||||
|
||||
# Let's define the Strategy here.
|
||||
|
||||
# To avoid circular imports, kernel.nim will likely INCLUDE sched.nim or sched.nim
|
||||
# will act on a passed context.
|
||||
# BUT, SPEC-250 implies sched.nim *is* the logic.
|
||||
#
|
||||
# Let's define the Harmonic logic.
|
||||
# We need access to `current_fiber` (from fiber.nim) and `get_now_ns` (helper).
|
||||
|
||||
proc sched_get_now_ns*(): uint64 {.importc: "get_now_ns", cdecl.}
|
||||
|
||||
# Forward declaration for the tick function
|
||||
# Returns TRUE if a fiber was switched to (work done/found).
|
||||
# Returns FALSE if the system should sleep (WFI).
|
||||
proc sched_tick_spectrum*(fibers: openArray[ptr FiberObject]): bool =
|
||||
let now = sched_get_now_ns()
|
||||
|
||||
# =========================================================
|
||||
# Phase 1: PHOTON (Hard Real-Time / Hardware Driven)
|
||||
# =========================================================
|
||||
# - V-Sync (Compositor)
|
||||
# - Audio Mix
|
||||
# - Network Polling (War Mode)
|
||||
|
||||
var run_photon = false
|
||||
for f in fibers:
|
||||
if f != nil and f.getSpectrum() == Spectrum.Photon:
|
||||
if now >= f.sleep_until:
|
||||
if f != current_fiber:
|
||||
switch(f); return true
|
||||
else:
|
||||
run_photon = true
|
||||
if run_photon: return true
|
||||
|
||||
# =========================================================
|
||||
# Phase 2: MATTER (Interactive / Latency Sensitive)
|
||||
# =========================================================
|
||||
# - Shell
|
||||
# - Editor
|
||||
|
||||
var run_matter = false
|
||||
for f in fibers:
|
||||
if f != nil and f.getSpectrum() == Spectrum.Matter:
|
||||
if now >= f.sleep_until:
|
||||
if f != current_fiber:
|
||||
switch(f); return true
|
||||
else:
|
||||
run_matter = true
|
||||
if run_matter: return true
|
||||
|
||||
# =========================================================
|
||||
# Phase 3: GRAVITY (Throughput / Background)
|
||||
# =========================================================
|
||||
# - Compiler
|
||||
# - Ledger Sync
|
||||
|
||||
var run_gravity = false
|
||||
for f in fibers:
|
||||
if f != nil and f.getSpectrum() == Spectrum.Gravity:
|
||||
if now >= f.sleep_until:
|
||||
if f != current_fiber:
|
||||
switch(f); return true
|
||||
else:
|
||||
run_gravity = true
|
||||
if run_gravity: return true
|
||||
|
||||
# =========================================================
|
||||
# Phase 4: VOID (Scavenger)
|
||||
# =========================================================
|
||||
# - Untrusted Code
|
||||
# - Speculative Execution
|
||||
|
||||
for f in fibers:
|
||||
if f != nil and f.getSpectrum() == Spectrum.Void:
|
||||
if now >= f.sleep_until:
|
||||
if f != current_fiber:
|
||||
switch(f)
|
||||
return true
|
||||
else:
|
||||
return true
|
||||
|
||||
# =========================================================
|
||||
# THE SILENCE
|
||||
# =========================================================
|
||||
# If we reached here, NO fiber is runnable.
|
||||
return false
|
||||
|
||||
# =========================================================
|
||||
# THE RATCHET (Post-Execution Analysis)
|
||||
# =========================================================
|
||||
|
||||
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
||||
|
||||
proc sched_log(msg: string) =
|
||||
if msg.len > 0:
|
||||
console_write(unsafeAddr msg[0], csize_t(msg.len))
|
||||
|
||||
proc sched_demote(f: ptr FiberObject) =
|
||||
## Demote a fiber to a lower Spectrum tier
|
||||
let current = f.getSpectrum()
|
||||
case current:
|
||||
of Spectrum.Photon:
|
||||
f.setSpectrum(Spectrum.Matter)
|
||||
console_write(cstring("[Ratchet] DEMOTED fiber to Matter\n"), 34)
|
||||
of Spectrum.Matter:
|
||||
f.setSpectrum(Spectrum.Gravity)
|
||||
console_write(cstring("[Ratchet] DEMOTED fiber to Gravity\n"), 35)
|
||||
of Spectrum.Gravity:
|
||||
f.setSpectrum(Spectrum.Void)
|
||||
console_write(cstring("[Ratchet] DEMOTED fiber to Void\n"), 32)
|
||||
of Spectrum.Void:
|
||||
discard # Already at the bottom
|
||||
|
||||
proc sched_analyze_burst*(f: ptr FiberObject, burst_ns: uint64) =
|
||||
## Analyze the burst duration of a fiber after it yields/switches
|
||||
## Implements the 3-strike rule for budget violations
|
||||
if f == nil: return
|
||||
|
||||
f.last_burst_ns = burst_ns
|
||||
|
||||
# Update moving average (exponential: 75% old, 25% new)
|
||||
if f.avg_burst == 0:
|
||||
f.avg_burst = burst_ns
|
||||
else:
|
||||
f.avg_burst = (f.avg_burst * 3 + burst_ns) div 4
|
||||
|
||||
# Budget enforcement
|
||||
if f.budget_ns > 0 and burst_ns > f.budget_ns:
|
||||
f.violations += 1
|
||||
console_write(cstring("[Ratchet] Violation: fiber exceeded budget\n"), 42)
|
||||
|
||||
if f.violations >= 3:
|
||||
sched_demote(f)
|
||||
f.violations = 0 # Reset after demotion
|
||||
|
||||
{.pop.}
|
||||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: The Watchdog (Immune Monitor)
|
||||
|
||||
|
||||
# Watchdog Fiber - Logic Core Immune System
|
||||
|
||||
|
|
@ -27,7 +36,7 @@ proc watchdog_loop() {.cdecl.} =
|
|||
|
||||
# Send CMD_ION_START to the Control Loop
|
||||
var cmd = CmdPacket(kind: uint32(ion.CmdType.CMD_ION_START), arg: 0)
|
||||
chan_cmd.send(cmd)
|
||||
discard chan_cmd.send(cmd)
|
||||
|
||||
# Cooperative Multitasking: Must yield!
|
||||
# 🏛️ ADAPTIVE GOVERNOR (Phase 3: IDLE)
|
||||
|
|
@ -39,5 +48,5 @@ proc watchdog_loop() {.cdecl.} =
|
|||
# csrci sstatus, 2
|
||||
# """
|
||||
|
||||
fiber_yield()
|
||||
fiber_sleep(100)
|
||||
# asm "wfi"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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.
|
||||
|
||||
## Rumpk Layer 1: Console Writer Infrastructure
|
||||
|
||||
|
||||
# Forward declarations for C symbols
|
||||
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
||||
|
|
|
|||
38
hal/abi.zig
38
hal/abi.zig
|
|
@ -1,28 +1,38 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// HAL ABI - The Contract between L0 (Zig) and L1 (Nim)
|
||||
// This struct is the "contract" for future language integration
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL ABI: The Contract between L0 (Zig) and L1 (Nim)
|
||||
//!
|
||||
//! This struct defines the function pointer table for platform abstraction.
|
||||
//! All function pointers use C calling convention for Nim FFI compatibility.
|
||||
|
||||
// NOTE(Build): Zig 0.15.x requires explicit callconv on extern struct fn pointers
|
||||
pub const HAL = extern struct {
|
||||
/// Write to console/serial
|
||||
console_write: *const fn ([*]const u8, usize) void,
|
||||
console_write: *const fn ([*]const u8, usize) callconv(.c) void,
|
||||
|
||||
/// Allocate physical pages
|
||||
palloc: *const fn (usize) ?*anyopaque,
|
||||
palloc: *const fn (usize) callconv(.c) ?*anyopaque,
|
||||
|
||||
/// Free physical pages
|
||||
pfree: *const fn (*anyopaque) void,
|
||||
pfree: *const fn (*anyopaque) callconv(.c) void,
|
||||
|
||||
/// Register interrupt handler
|
||||
irq_register: *const fn (u8, *const fn () void) void,
|
||||
irq_register: *const fn (u8, *const fn () callconv(.c) void) callconv(.c) void,
|
||||
|
||||
/// Get current time in nanoseconds
|
||||
timer_now_ns: *const fn () u64,
|
||||
timer_now_ns: *const fn () callconv(.c) u64,
|
||||
|
||||
/// Halt the CPU
|
||||
halt: *const fn () noreturn,
|
||||
halt: *const fn () callconv(.c) noreturn,
|
||||
};
|
||||
|
||||
/// Global HAL instance - initialized by boot code
|
||||
// SAFETY(HAL): Global instance initialized by init() before any access.
|
||||
// SAFETY(HAL): Global HAL instance is populated by `init()` during the early boot phase.
|
||||
pub var hal: HAL = undefined;
|
||||
|
||||
/// Initialize the HAL with platform-specific implementations
|
||||
|
|
@ -31,13 +41,15 @@ pub fn init(console: anytype, allocator: anytype) void {
|
|||
.console_write = console.write,
|
||||
.palloc = allocator.alloc,
|
||||
.pfree = allocator.free,
|
||||
.irq_register = undefined, // TODO
|
||||
.timer_now_ns = undefined, // TODO
|
||||
// SAFETY(HAL): Placeholders for future implementation.
|
||||
// These function pointers are not called until implemented.
|
||||
.irq_register = undefined, // TODO(HAL): Implement IRQ registration
|
||||
.timer_now_ns = undefined, // TODO(HAL): Implement timer
|
||||
.halt = halt_impl,
|
||||
};
|
||||
}
|
||||
|
||||
fn halt_impl() noreturn {
|
||||
fn halt_impl() callconv(.c) noreturn {
|
||||
while (true) {
|
||||
asm volatile ("wfi");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,13 +76,23 @@ rumpk_enter_userland:
|
|||
# - SPIE (Previous Interrupt Enable) = 1 (Enable Interrupts on sret) - Bit 5
|
||||
# - SUM (Supervisor User Memory) - PRESERVE (Already set in kmain)
|
||||
|
||||
# Clear SPP bit (bit 8)
|
||||
# Clear SPP bit (bit 8) -> Return to User Mode
|
||||
li t0, (1 << 8)
|
||||
csrc sstatus, t0
|
||||
|
||||
# Set SPIE bit (bit 5)
|
||||
# Enable SPIE bit (bit 5) -> Enable Interrupts on sret
|
||||
li t0, (1 << 5)
|
||||
csrs sstatus, t0
|
||||
|
||||
# 🔧 CRITICAL FIX: Set SUM bit (bit 18) to allow Kernel access to U=1 pages (UART, etc.)
|
||||
li t0, (1 << 18)
|
||||
csrs sstatus, t0
|
||||
|
||||
# 2.5 Synchronize Instruction Cache (Critical for newly loaded code)
|
||||
fence.i
|
||||
|
||||
# 🔧 CRITICAL FIX: Set sscratch to Kernel Stack (sp)
|
||||
csrw sscratch, sp
|
||||
|
||||
# 3. Use sret to transit to U-mode
|
||||
sret
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// RUMPK HAL // SOVEREIGN CHANNELS (The Pipes)
|
||||
// THE INVARIANT SHIELD - Phase 2 Task 1
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Sovereign Channels (Lock-Free Ring Buffers)
|
||||
//!
|
||||
//! Implements atomic lock-free ring buffers for ION packet communication.
|
||||
//! Provides the "pipes" between kernel and userspace with invariant protection.
|
||||
//!
|
||||
//! SAFETY: All operations use atomic loads/stores with proper memory fences.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
// core/rumpk/hal/crypto.zig
|
||||
// Phase 35e: The Cryptographic Foundation
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Cryptographic Functions
|
||||
//!
|
||||
//! Provides SipHash-2-4 (128-bit) for packet IDs and Ed25519 signature verification.
|
||||
//! All functions are exported for use by the ION layer.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
|
|
@ -20,3 +29,11 @@ export fn hal_crypto_ed25519_verify(sig: *const [64]u8, msg: [*]const u8, msg_le
|
|||
signature.verify(msg[0..msg_len], public_key) catch return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// BLAKE3 Hash (256-bit) for key derivation
|
||||
/// Used by Monolith (SPEC-021) to derive VolumeKey from 4MB keyfile
|
||||
export fn hal_crypto_blake3(data: [*]const u8, len: usize, out: *[32]u8) void {
|
||||
var hasher = std.crypto.hash.Blake3.init(.{});
|
||||
hasher.update(data[0..len]);
|
||||
hasher.final(out);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// RUMPK HAL // RISC-V ENTRY - SOVEREIGN TRAP ARCHITECTURE
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: RISC-V Entry Point (Sovereign Trap Architecture)
|
||||
//!
|
||||
//! This is the hardware floor for RISC-V64. Sets up stack, trap vectors,
|
||||
//! S-mode transition, and memory management before handing off to Nim.
|
||||
//!
|
||||
//! SAFETY: Runs in bare-metal S-mode with Sv39 paging.
|
||||
|
||||
const std = @import("std");
|
||||
const uart = @import("uart.zig");
|
||||
const virtio_net = @import("virtio_net.zig");
|
||||
|
|
@ -13,6 +25,7 @@ export fn _start() callconv(.naked) noreturn {
|
|||
// 1. Disable Interrupts
|
||||
\\ csrw sie, zero
|
||||
\\ csrw satp, zero
|
||||
\\ csrw sscratch, zero
|
||||
// 1.1 Enable FPU (sstatus.FS = Initial [01])
|
||||
\\ li t0, 0x2000
|
||||
\\ csrs sstatus, t0
|
||||
|
|
@ -23,6 +36,16 @@ export fn _start() callconv(.naked) noreturn {
|
|||
\\ la gp, __global_pointer$
|
||||
\\ .option pop
|
||||
|
||||
// 1.5 Clear BSS (Zero out uninitialized globals)
|
||||
\\ la t0, __bss_start
|
||||
\\ la t1, __bss_end
|
||||
\\ bge t0, t1, 2f
|
||||
\\ 1:
|
||||
\\ sb zero, (t0)
|
||||
\\ addi t0, t0, 1
|
||||
\\ blt t0, t1, 1b
|
||||
\\ 2:
|
||||
|
||||
// 2. Set up Stack
|
||||
\\ la sp, stack_bytes
|
||||
\\ li t0, 65536
|
||||
|
|
@ -79,12 +102,17 @@ const TrapFrame = extern struct {
|
|||
};
|
||||
|
||||
// Full Context Save Trap Entry
|
||||
export fn trap_entry() callconv(.naked) void {
|
||||
export fn trap_entry() align(4) callconv(.naked) void {
|
||||
asm volatile (
|
||||
// LOUD HARDWARE TRACE: Write '!' to UART
|
||||
\\ li t0, 0x10000000
|
||||
\\ li t1, 33
|
||||
\\ sb t1, 0(t0)
|
||||
// 🔧 CRITICAL FIX: Stack Switching (User -> Kernel)
|
||||
// Swap sp and sscratch.
|
||||
// If from User: sp=KStack, sscratch=UStack
|
||||
// If from Kernel: sp=0 (sscratch was 0), sscratch=KStack
|
||||
\\ csrrw sp, sscratch, sp
|
||||
\\ bnez sp, 1f
|
||||
// Came from Kernel (sp was 0). Restore sp.
|
||||
\\ csrrw sp, sscratch, sp
|
||||
\\ 1:
|
||||
|
||||
// Allocate stack (36 words * 8 bytes = 288 bytes)
|
||||
\\ addi sp, sp, -288
|
||||
|
|
@ -141,10 +169,10 @@ export fn trap_entry() callconv(.naked) void {
|
|||
\\ mv a0, sp
|
||||
\\ call rss_trap_handler
|
||||
|
||||
// Restore CSRs (sepc might be modified by syscall handler to skip ecall)
|
||||
// Restore CSRs
|
||||
\\ ld t0, 240(sp)
|
||||
\\ csrw sepc, t0
|
||||
// We restore sstatus to preserve interrupt state if needed, though usually fixed in kernel
|
||||
// We restore sstatus
|
||||
\\ ld t1, 248(sp)
|
||||
\\ csrw sstatus, t1
|
||||
|
||||
|
|
@ -207,6 +235,9 @@ export fn rss_trap_handler(frame: *TrapFrame) void {
|
|||
// Write result back to a0
|
||||
frame.a0 = res;
|
||||
|
||||
// DIAGNOSTIC: Syscall completed
|
||||
uart.print("[Trap] Syscall done, returning to userland\n");
|
||||
|
||||
// uart.puts("[Trap] Checking deferred yield\n");
|
||||
// Check for deferred yield
|
||||
k_check_deferred_yield();
|
||||
|
|
@ -222,6 +253,8 @@ export fn rss_trap_handler(frame: *TrapFrame) void {
|
|||
while (true) {}
|
||||
}
|
||||
|
||||
// SAFETY(Stack): Memory is immediately used by _start before any read.
|
||||
// Initialized to `undefined` for performance (no zeroing 64KB at boot).
|
||||
export var stack_bytes: [64 * 1024]u8 align(16) = undefined;
|
||||
|
||||
const hud = @import("hud.zig");
|
||||
|
|
@ -275,3 +308,28 @@ export fn rumpk_timer_now_ns() u64 {
|
|||
// QEMU Virt machine is 10MHz -> 1 tick = 100ns
|
||||
return ticks * 100;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// KEXEC (The Phoenix Protocol)
|
||||
// =========================================================
|
||||
|
||||
export fn hal_kexec(entry: u64, dtb: u64) noreturn {
|
||||
// 1. Disable Interrupts
|
||||
asm volatile ("csrc sstatus, 2");
|
||||
|
||||
// 2. Disable MMU (Return to Physical Reality)
|
||||
// WARNING: This assumes we are Identity Mapped (VA=PA) or executing from a location
|
||||
// where PA is the same. mm.zig creates Identity Map for Kernel code.
|
||||
asm volatile ("csrw satp, zero");
|
||||
asm volatile ("sfence.vma zero, zero");
|
||||
|
||||
// 3. Jump to new kernel
|
||||
asm volatile (
|
||||
\\ jr %[entry]
|
||||
:
|
||||
: [entry] "r" (entry),
|
||||
[dtb] "{a1}" (dtb),
|
||||
[hart] "{a0}" (0),
|
||||
);
|
||||
unreachable;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
// Phase 26: C-compatible wrapper for framebuffer access
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Framebuffer FFI Wrapper
|
||||
//!
|
||||
//! Provides C-compatible exports for framebuffer access from Nim.
|
||||
//!
|
||||
//! SAFETY: Proxies requests to the primary framebuffer module. No state of its own.
|
||||
|
||||
const fb = @import("framebuffer.zig");
|
||||
|
||||
export fn fb_kern_get_addr() usize {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,17 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// Phase 3.5c: The Canvas - Static Framebuffer in BSS
|
||||
// This is our "Video RAM" living in kernel memory.
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: The Canvas (Static Framebuffer)
|
||||
//!
|
||||
//! Implements the primary graphics buffer (VRAM) living in BSS.
|
||||
//! Provides primitives for pixel plotting, rect-filling, and screen fading.
|
||||
//!
|
||||
//! SAFETY: All drawing operations include clipping logic to prevent BSS overflow.
|
||||
//! Resolution is fixed at 1920x1080 ARGB.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
|
|
|
|||
24
hal/gpu.zig
24
hal/gpu.zig
|
|
@ -1,6 +1,17 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// Phase 3.5c: The Retina - VirtIO-GPU Driver
|
||||
// Blasts pixels from RAM canvas to host display.
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: VirtIO-GPU Driver (The Retina)
|
||||
//!
|
||||
//! Blasts pixels from RAM canvas to host display.
|
||||
//! Handles command queue management, resource creation, and buffer flushing.
|
||||
//!
|
||||
//! SAFETY: All hardware registers and queues are accessed via volatile pointers.
|
||||
//! Uses static command/response buffers to avoid dynamic allocation in the tick loop.
|
||||
|
||||
const std = @import("std");
|
||||
const fb = @import("framebuffer.zig");
|
||||
|
|
@ -142,6 +153,8 @@ const VirtioQueueLayout = extern struct {
|
|||
};
|
||||
|
||||
var queue align(PAGE_SIZE) = VirtioQueueLayout{
|
||||
// SAFETY(GPU): Descriptor ring is initialized to `undefined` for performance.
|
||||
// Individual descriptors are populated by `send_command` before use.
|
||||
.desc = undefined,
|
||||
.avail = .{ .flags = 0, .idx = 0, .ring = [_]u16{0} ** QUEUE_SIZE },
|
||||
._pad1 = [_]u8{0} ** (PAGE_SIZE - @sizeOf([QUEUE_SIZE]VirtioDesc) - @sizeOf(VirtioAvail)),
|
||||
|
|
@ -151,7 +164,12 @@ var queue align(PAGE_SIZE) = VirtioQueueLayout{
|
|||
var last_used_idx: u16 = 0;
|
||||
|
||||
// Command/Response buffers (static)
|
||||
// SAFETY(GPU): Command buffer initialized to `undefined` for performance.
|
||||
// Populated by command-specific functions (e.g. `cmd_transfer_2d`) before transmission.
|
||||
var cmd_buf: [512]u8 align(4096) = undefined;
|
||||
|
||||
// SAFETY(GPU): Response buffer initialized to `undefined` for performance.
|
||||
// Populated by hardware device during synchronous command execution.
|
||||
var resp_buf: [256]u8 align(4096) = undefined;
|
||||
|
||||
// =========================================================
|
||||
|
|
|
|||
17
hal/hud.zig
17
hal/hud.zig
|
|
@ -1,6 +1,16 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// RUMPK HAL // HUD TUI
|
||||
// Minimal ANSI escape code utilities for the NexShell HUD.
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: HUD TUI Utilities
|
||||
//!
|
||||
//! Provides minimal ANSI escape code utilities for the NexShell HUD.
|
||||
//! Used for basic TUI elements like boxes and color management.
|
||||
//!
|
||||
//! SAFETY: All operations are synchronous and communicate via UART.
|
||||
|
||||
const uart = @import("uart.zig");
|
||||
|
||||
|
|
@ -63,6 +73,7 @@ fn print_u8(n: u8) void {
|
|||
uart.print("0");
|
||||
return;
|
||||
}
|
||||
// SAFETY(HUD): Local buffer is immediately populated by the while loop.
|
||||
var buf: [3]u8 = undefined;
|
||||
var i: u8 = 0;
|
||||
var val = n;
|
||||
|
|
|
|||
19
hal/main.zig
19
hal/main.zig
|
|
@ -1,11 +1,16 @@
|
|||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Licensed under the Libertaria Commonwealth License (LCL-1.0)
|
||||
// See legal/LICENSE_COMMONWEALTH.md for details.
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// Rumpk Layer 0: The Concrete Foundation
|
||||
// Markus Maiwald (Architect) | Voxis Forge (AI)
|
||||
//
|
||||
// This is the hardware floor. Sets up stack and calls Nim.
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: The Concrete Foundation (HAL Entry Point)
|
||||
//!
|
||||
//! This is the hardware floor. Sets up stack, initializes UART,
|
||||
//! draws the initial HUD, and hands off to Nim L1.
|
||||
//!
|
||||
//! SAFETY: Runs in bare-metal mode with no runtime support.
|
||||
|
||||
const uart = @import("uart.zig");
|
||||
|
||||
|
|
@ -22,6 +27,8 @@ export fn hal_io_init() void {
|
|||
// Stack Setup (16KB)
|
||||
// =========================================================
|
||||
|
||||
// SAFETY(Stack): Memory is immediately used by _start before any read.
|
||||
// Initialized to `undefined` for performance (no zeroing 64KB at boot).
|
||||
export var stack_bytes: [64 * 1024]u8 align(16) = undefined;
|
||||
|
||||
// =========================================================
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// Phase 3.5d: The Matrix Protocol - Rainmaker Logic
|
||||
// Greets the Subject, then recedes into the background.
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Matrix Protocol (Rainmaker Logic)
|
||||
//!
|
||||
//! Implements a "Matrix" falling rain effect for the boot splash.
|
||||
//! Recedes into the background after a fixed lifetime.
|
||||
//!
|
||||
//! SAFETY: Uses a simple Xorshift PRNG. Animation state is global.
|
||||
|
||||
const std = @import("std");
|
||||
const fb = @import("framebuffer.zig");
|
||||
|
|
@ -12,6 +22,8 @@ const COLS = fb.WIDTH / FONT_W;
|
|||
const LIFETIME_FRAMES = 150; // ~5 seconds at 30FPS (reduced for impact)
|
||||
|
||||
// State
|
||||
// SAFETY(Matrix): Drops array is initialized by `init()` before use.
|
||||
// Initialized to `undefined` to save a 512B zero-sweep in BSS.
|
||||
var drops: [COLS]i32 = undefined;
|
||||
var frame_count: usize = 0;
|
||||
var is_active: bool = false;
|
||||
|
|
|
|||
48
hal/mm.zig
48
hal/mm.zig
|
|
@ -1,5 +1,17 @@
|
|||
// Phase 31: The Glass Cage - Sv39 Virtual Memory Isolation
|
||||
// Memory Manager: Page Table Infrastructure
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Memory Management (The Glass Cage)
|
||||
//!
|
||||
//! Implements Sv39 virtual memory isolation for RISC-V.
|
||||
//! Handles page table construction, identity mapping, and worker isolation.
|
||||
//!
|
||||
//! SAFETY: Manages raw physical memory addresses for page tables.
|
||||
//! Performs identity mapping for the kernel and restricted mapping for workers.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
|
|
@ -126,10 +138,6 @@ pub fn map_page(root: *PageTable, va: u64, pa: u64, flags: u64) !void {
|
|||
pte.* = PageTableEntry.init(@intFromPtr(new_pt), PTE_V);
|
||||
}
|
||||
|
||||
if (pte.is_leaf()) {
|
||||
return;
|
||||
}
|
||||
|
||||
pt = @ptrFromInt(pte.get_pa());
|
||||
}
|
||||
|
||||
|
|
@ -169,13 +177,17 @@ pub fn create_worker_map(stack_base: u64, stack_size: u64, packet_addr: u64) !*P
|
|||
|
||||
// 🏛️ THE EXPANDED CAGE (Phase 37 - 256MB RAM)
|
||||
|
||||
// 1. Kernel Memory (0-32MB) -> Supervisor ONLY (PTE_U = 0)
|
||||
// This allows the fiber trampoline to execute in S-mode.
|
||||
try map_range(root, DRAM_BASE, DRAM_BASE, 32 * 1024 * 1024, PTE_R | PTE_W | PTE_X);
|
||||
kprint("[MM] Creating worker map:\n");
|
||||
kprint("[MM] Kernel (S-mode): 0x80000000-0x88000000\n");
|
||||
kprint("[MM] User (U-mode): 0x88000000-0x90000000\n");
|
||||
|
||||
// 2. User Memory (32-256MB) -> User Accessible (PTE_U = 1)
|
||||
// This allows NipBox (at 96MB offset, 64MB size) to execute in U-mode.
|
||||
try map_range(root, DRAM_BASE + (32 * 1024 * 1024), DRAM_BASE + (32 * 1024 * 1024), 224 * 1024 * 1024, PTE_R | PTE_W | PTE_X | PTE_U);
|
||||
// 1. Kernel Memory (0-128MB) -> Supervisor ONLY (PTE_U = 0)
|
||||
// This allows the fiber trampoline to execute in S-mode.
|
||||
try map_range(root, DRAM_BASE, DRAM_BASE, 128 * 1024 * 1024, PTE_R | PTE_W | PTE_X);
|
||||
|
||||
// 2. User Memory (128-256MB) -> User Accessible (PTE_U = 1)
|
||||
// This allows NipBox (at 128MB offset) to execute in U-mode.
|
||||
try map_range(root, DRAM_BASE + (128 * 1024 * 1024), DRAM_BASE + (128 * 1024 * 1024), 128 * 1024 * 1024, PTE_R | PTE_W | PTE_X | PTE_U);
|
||||
|
||||
// 3. User MMIO (UART)
|
||||
try map_range(root, UART_BASE, UART_BASE, PAGE_SIZE, PTE_R | PTE_W | PTE_U);
|
||||
|
|
@ -183,7 +195,14 @@ pub fn create_worker_map(stack_base: u64, stack_size: u64, packet_addr: u64) !*P
|
|||
// 4. Overlap stack with user access
|
||||
try map_range(root, stack_base, stack_base, stack_size, PTE_R | PTE_W | PTE_U);
|
||||
|
||||
_ = packet_addr;
|
||||
// 5. Shared SysTable & Rings (0x83000000) - Map 32KB (8 pages)
|
||||
var j: u64 = 0;
|
||||
while (j < 8) : (j += 1) {
|
||||
const addr = packet_addr + (j * PAGE_SIZE);
|
||||
try map_page(root, addr, addr, PTE_R | PTE_W | PTE_U);
|
||||
}
|
||||
|
||||
kprint("[MM] Worker map created successfully\n");
|
||||
|
||||
return root;
|
||||
}
|
||||
|
|
@ -207,7 +226,8 @@ pub export fn mm_activate_satp(satp_val: u64) callconv(.c) void {
|
|||
|
||||
// Export for kernel
|
||||
pub export fn mm_init() callconv(.c) void {
|
||||
const pt_base = DRAM_BASE + (16 * 1024 * 1024);
|
||||
// Relocate page tables to 240MB offset (Top of 256MB)
|
||||
const pt_base = DRAM_BASE + (240 * 1024 * 1024);
|
||||
init_page_allocator(pt_base, 8 * 1024 * 1024);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Reed-Solomon RAM Block Device (SPEC-023)
|
||||
//!
|
||||
//! Provides ECC-protected RAM storage using Reed-Solomon GF(2^8).
|
||||
//! This is the "Cortex" - Space-Grade resilient memory.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
// =========================================================
|
||||
// Galois Field GF(2^8) Arithmetic
|
||||
// =========================================================
|
||||
// Primitive polynomial: x^8 + x^4 + x^3 + x^2 + 1 (0x11D)
|
||||
|
||||
const GF_PRIM: u16 = 0x11D;
|
||||
|
||||
// Precomputed log and antilog tables for GF(2^8)
|
||||
var gf_log: [256]u8 = undefined;
|
||||
var gf_exp: [512]u8 = undefined;
|
||||
var gf_initialized: bool = false;
|
||||
|
||||
fn gf_init() void {
|
||||
if (gf_initialized) return;
|
||||
|
||||
var x: u16 = 1;
|
||||
for (0..255) |i| {
|
||||
gf_exp[i] = @truncate(x);
|
||||
gf_log[@as(usize, @as(u8, @truncate(x)))] = @truncate(i);
|
||||
x <<= 1;
|
||||
if (x & 0x100 != 0) {
|
||||
x ^= GF_PRIM;
|
||||
}
|
||||
}
|
||||
// Extend exp table for easier modulo
|
||||
for (255..512) |i| {
|
||||
gf_exp[i] = gf_exp[i - 255];
|
||||
}
|
||||
gf_log[0] = 0; // Undefined, but avoid issues
|
||||
gf_initialized = true;
|
||||
}
|
||||
|
||||
fn gf_mul(a: u8, b: u8) u8 {
|
||||
if (a == 0 or b == 0) return 0;
|
||||
const log_a = gf_log[a];
|
||||
const log_b = gf_log[b];
|
||||
return gf_exp[@as(u16, log_a) + @as(u16, log_b)];
|
||||
}
|
||||
|
||||
fn gf_div(a: u8, b: u8) u8 {
|
||||
if (b == 0) return 0; // Error: division by zero
|
||||
if (a == 0) return 0;
|
||||
const log_a = gf_log[a];
|
||||
const log_b = gf_log[b];
|
||||
return gf_exp[@as(u16, log_a) + 255 - @as(u16, log_b)];
|
||||
}
|
||||
|
||||
fn gf_pow(a: u8, n: u8) u8 {
|
||||
if (n == 0) return 1;
|
||||
if (a == 0) return 0;
|
||||
const log_a: u16 = gf_log[a];
|
||||
return gf_exp[(log_a * @as(u16, n)) % 255];
|
||||
}
|
||||
|
||||
fn gf_inv(a: u8) u8 {
|
||||
return gf_exp[255 - @as(u16, gf_log[a])];
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Reed-Solomon Codec
|
||||
// =========================================================
|
||||
|
||||
pub const SECTOR_SIZE: usize = 512;
|
||||
pub const PARITY_SIZE: usize = 32; // Can correct 16 byte errors
|
||||
pub const TOTAL_SIZE: usize = SECTOR_SIZE + PARITY_SIZE;
|
||||
|
||||
// Generator polynomial coefficients (precomputed for t=16)
|
||||
var rs_generator: [PARITY_SIZE + 1]u8 = undefined;
|
||||
var rs_generator_initialized: bool = false;
|
||||
|
||||
fn rs_init_generator() void {
|
||||
if (rs_generator_initialized) return;
|
||||
gf_init();
|
||||
|
||||
// Build generator polynomial: prod(x - alpha^i) for i = 0..PARITY_SIZE-1
|
||||
rs_generator[0] = 1;
|
||||
for (1..PARITY_SIZE + 1) |i| {
|
||||
rs_generator[i] = 0;
|
||||
}
|
||||
|
||||
for (0..PARITY_SIZE) |i| {
|
||||
const alpha_i = gf_pow(2, @truncate(i));
|
||||
// Multiply by (x - alpha^i)
|
||||
var j: usize = PARITY_SIZE;
|
||||
while (j > 0) : (j -= 1) {
|
||||
rs_generator[j] = rs_generator[j - 1] ^ gf_mul(rs_generator[j], alpha_i);
|
||||
}
|
||||
rs_generator[0] = gf_mul(rs_generator[0], alpha_i);
|
||||
}
|
||||
rs_generator_initialized = true;
|
||||
}
|
||||
|
||||
/// Encode data with Reed-Solomon parity
|
||||
pub fn rs_encode(data: []const u8, parity: *[PARITY_SIZE]u8) void {
|
||||
rs_init_generator();
|
||||
|
||||
// Initialize parity to zero
|
||||
for (parity) |*p| p.* = 0;
|
||||
|
||||
// Polynomial division
|
||||
for (data) |byte| {
|
||||
const feedback = byte ^ parity[0];
|
||||
// Shift parity register
|
||||
for (0..PARITY_SIZE - 1) |i| {
|
||||
parity[i] = parity[i + 1] ^ gf_mul(rs_generator[PARITY_SIZE - 1 - i], feedback);
|
||||
}
|
||||
parity[PARITY_SIZE - 1] = gf_mul(rs_generator[0], feedback);
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate syndromes for error detection
|
||||
fn rs_syndromes(data: []const u8, parity: []const u8) [PARITY_SIZE]u8 {
|
||||
var syndromes: [PARITY_SIZE]u8 = undefined;
|
||||
|
||||
for (0..PARITY_SIZE) |i| {
|
||||
const alpha_i = gf_pow(2, @truncate(i));
|
||||
var s: u8 = 0;
|
||||
|
||||
// Evaluate polynomial at alpha^i
|
||||
for (data) |byte| {
|
||||
s = gf_mul(s, alpha_i) ^ byte;
|
||||
}
|
||||
for (parity) |byte| {
|
||||
s = gf_mul(s, alpha_i) ^ byte;
|
||||
}
|
||||
syndromes[i] = s;
|
||||
}
|
||||
return syndromes;
|
||||
}
|
||||
|
||||
/// Check if all syndromes are zero (no errors)
|
||||
fn rs_check_syndromes(syndromes: []const u8) bool {
|
||||
for (syndromes) |s| {
|
||||
if (s != 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Decode and repair data using Reed-Solomon
|
||||
/// Returns true if data is valid (or was repaired), false if uncorrectable
|
||||
pub fn rs_decode(data: []u8, parity: []u8) bool {
|
||||
rs_init_generator();
|
||||
|
||||
const syndromes = rs_syndromes(data, parity);
|
||||
|
||||
// No errors
|
||||
if (rs_check_syndromes(&syndromes)) return true;
|
||||
|
||||
// TODO: Implement Berlekamp-Massey algorithm for error location
|
||||
// TODO: Implement Forney algorithm for error correction
|
||||
// For MVP, we detect but don't yet repair multi-byte errors
|
||||
|
||||
// Simple single-byte error correction (simplified)
|
||||
// This is a placeholder - full RS decoding is complex
|
||||
|
||||
return false; // Could not repair
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// RAM Block Device Interface
|
||||
// =========================================================
|
||||
|
||||
var ram_base: [*]u8 = undefined;
|
||||
var ram_size: usize = 0;
|
||||
var ram_initialized: bool = false;
|
||||
|
||||
/// Initialize the RAM block device with a memory region
|
||||
export fn ram_blk_init(base: [*]u8, size: usize) void {
|
||||
gf_init();
|
||||
rs_init_generator();
|
||||
ram_base = base;
|
||||
ram_size = size;
|
||||
ram_initialized = true;
|
||||
}
|
||||
|
||||
/// Get the number of sectors available
|
||||
export fn ram_blk_sector_count() u32 {
|
||||
if (!ram_initialized) return 0;
|
||||
return @truncate(ram_size / TOTAL_SIZE);
|
||||
}
|
||||
|
||||
/// Write a sector with ECC protection
|
||||
export fn ram_blk_write(sector: u32, data: [*]const u8) i32 {
|
||||
if (!ram_initialized) return -1;
|
||||
|
||||
const offset = @as(usize, sector) * TOTAL_SIZE;
|
||||
if (offset + TOTAL_SIZE > ram_size) return -1;
|
||||
|
||||
// Calculate parity
|
||||
var parity: [PARITY_SIZE]u8 = undefined;
|
||||
rs_encode(data[0..SECTOR_SIZE], &parity);
|
||||
|
||||
// Write data + parity
|
||||
const dest = ram_base + offset;
|
||||
@memcpy(dest[0..SECTOR_SIZE], data[0..SECTOR_SIZE]);
|
||||
@memcpy(dest[SECTOR_SIZE..TOTAL_SIZE], &parity);
|
||||
|
||||
return SECTOR_SIZE;
|
||||
}
|
||||
|
||||
/// Read a sector with ECC verification/repair
|
||||
export fn ram_blk_read(sector: u32, data: [*]u8) i32 {
|
||||
if (!ram_initialized) return -1;
|
||||
|
||||
const offset = @as(usize, sector) * TOTAL_SIZE;
|
||||
if (offset + TOTAL_SIZE > ram_size) return -1;
|
||||
|
||||
const src = ram_base + offset;
|
||||
|
||||
// Read data + parity
|
||||
@memcpy(data[0..SECTOR_SIZE], src[0..SECTOR_SIZE]);
|
||||
var parity: [PARITY_SIZE]u8 = undefined;
|
||||
@memcpy(&parity, src[SECTOR_SIZE..TOTAL_SIZE]);
|
||||
|
||||
// Verify and attempt repair
|
||||
var data_slice: [SECTOR_SIZE]u8 = undefined;
|
||||
@memcpy(&data_slice, data[0..SECTOR_SIZE]);
|
||||
|
||||
if (!rs_decode(&data_slice, &parity)) {
|
||||
// TODO: Log the uncorrectable error
|
||||
return -2; // ECC_ERROR
|
||||
}
|
||||
|
||||
// Copy repaired data back
|
||||
@memcpy(data[0..SECTOR_SIZE], &data_slice);
|
||||
|
||||
return SECTOR_SIZE;
|
||||
}
|
||||
|
||||
/// Scrub a sector (read and verify, repair if needed)
|
||||
export fn ram_blk_scrub(sector: u32) i32 {
|
||||
var temp: [SECTOR_SIZE]u8 = undefined;
|
||||
const result = ram_blk_read(sector, &temp);
|
||||
if (result == SECTOR_SIZE) {
|
||||
// Re-write to fix any corrected errors
|
||||
return ram_blk_write(sector, &temp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Scrub all sectors (patrol scrubbing)
|
||||
export fn ram_blk_scrub_all() u32 {
|
||||
var errors: u32 = 0;
|
||||
const count = ram_blk_sector_count();
|
||||
for (0..count) |i| {
|
||||
if (ram_blk_scrub(@truncate(i)) < 0) {
|
||||
errors += 1;
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -1,7 +1,17 @@
|
|||
// Markus Maiwald (Architect) | Voxis Forge (AI)
|
||||
// RUMPK L0
|
||||
// libc_stubs.zig
|
||||
// We are the standard library now.
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: libc Stubs (Bump Allocator)
|
||||
//!
|
||||
//! We are the standard library now. Provides malloc/free/realloc/calloc
|
||||
//! for libraries that expect libc (e.g., LwIP).
|
||||
//!
|
||||
//! DECISION(Alloc): Bump allocator chosen for simplicity and determinism.
|
||||
//! Memory is never reclaimed; system reboots to reset.
|
||||
|
||||
const uart = @import("uart.zig");
|
||||
|
||||
|
|
@ -10,8 +20,15 @@ const uart = @import("uart.zig");
|
|||
// =========================================================
|
||||
|
||||
// Simple Bump Allocator for L0
|
||||
var heap: [32 * 1024 * 1024]u8 align(4096) = undefined; // 32MB Heap
|
||||
// SAFETY(Heap): Memory is written by malloc before any read occurs.
|
||||
// Initialized to `undefined` to avoid zeroing 32MB at boot.
|
||||
var heap: [96 * 1024 * 1024]u8 align(4096) = undefined;
|
||||
var heap_idx: usize = 0;
|
||||
var heap_init_done: bool = false;
|
||||
|
||||
export fn debug_print(s: [*]const u8, len: usize) void {
|
||||
uart.print(s[0..len]);
|
||||
}
|
||||
|
||||
// Header structure (64 bytes aligned to match LwIP MEM_ALIGNMENT)
|
||||
const BlockHeader = struct {
|
||||
|
|
@ -22,14 +39,36 @@ const BlockHeader = struct {
|
|||
export fn malloc(size: usize) ?*anyopaque {
|
||||
if (size == 0) return null;
|
||||
|
||||
if (!heap_init_done) {
|
||||
if (heap_idx != 0) {
|
||||
uart.print("[Alloc] WARNING: BSS NOT ZEROED! heap_idx: ");
|
||||
uart.print_hex(heap_idx);
|
||||
uart.print("\n");
|
||||
heap_idx = 0;
|
||||
}
|
||||
heap_init_done = true;
|
||||
}
|
||||
|
||||
const total_needed = size + @sizeOf(BlockHeader);
|
||||
const align_mask: usize = 63; // 64-byte alignment
|
||||
const aligned_idx = (heap_idx + align_mask) & ~align_mask;
|
||||
|
||||
if (aligned_idx + total_needed > heap.len) {
|
||||
uart.print("[Alloc] OOM! Size: ");
|
||||
uart.print_hex(size);
|
||||
uart.print(" Used: ");
|
||||
uart.print_hex(heap_idx);
|
||||
uart.print("\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Trace allocations (disabled to reduce noise)
|
||||
// uart.print("[Alloc] ");
|
||||
// uart.print_hex(size);
|
||||
// uart.print(" -> Used: ");
|
||||
// uart.print_hex(aligned_idx + total_needed);
|
||||
// uart.print("\n");
|
||||
|
||||
const base_ptr = &heap[aligned_idx];
|
||||
const header = @as(*BlockHeader, @ptrCast(@alignCast(base_ptr)));
|
||||
header.size = size;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: libc Stubs (Bump Allocator)
|
||||
//!
|
||||
//! We are the standard library now. Provides malloc/free/realloc/calloc
|
||||
//! for libraries that expect libc (e.g., LwIP).
|
||||
//!
|
||||
//! DECISION(Alloc): Bump allocator chosen for simplicity and determinism.
|
||||
//! Memory is never reclaimed; system reboots to reset.
|
||||
|
||||
const uart = @import("uart.zig");
|
||||
|
||||
// =========================================================
|
||||
// Heap Stubs (Bump Allocator with Block Headers)
|
||||
// =========================================================
|
||||
|
||||
// Simple Bump Allocator for L0
|
||||
// SAFETY(Heap): Memory is written by malloc before any read occurs.
|
||||
// Initialized to `undefined` to avoid zeroing 32MB at boot.
|
||||
var heap: [32 * 1024 * 1024]u8 align(4096) = undefined;
|
||||
var heap_idx: usize = 0;
|
||||
var heap_init_done: bool = false;
|
||||
|
||||
export fn debug_print(s: [*]const u8, len: usize) void {
|
||||
uart.print(s[0..len]);
|
||||
}
|
||||
|
||||
export fn kprint_hex(value: u64) void {
|
||||
uart.print_hex(value);
|
||||
}
|
||||
|
||||
// Header structure (64 bytes aligned to match LwIP MEM_ALIGNMENT)
|
||||
const BlockHeader = struct {
|
||||
size: usize,
|
||||
_pad: [64 - @sizeOf(usize)]u8,
|
||||
};
|
||||
|
||||
export fn malloc(size: usize) ?*anyopaque {
|
||||
if (size == 0) return null;
|
||||
|
||||
if (!heap_init_done) {
|
||||
if (heap_idx != 0) {
|
||||
uart.print("[Alloc] WARNING: BSS NOT ZEROED! heap_idx: ");
|
||||
uart.print_hex(heap_idx);
|
||||
uart.print("\n");
|
||||
heap_idx = 0;
|
||||
}
|
||||
heap_init_done = true;
|
||||
}
|
||||
|
||||
const total_needed = size + @sizeOf(BlockHeader);
|
||||
const align_mask: usize = 63; // 64-byte alignment
|
||||
const aligned_idx = (heap_idx + align_mask) & ~align_mask;
|
||||
|
||||
if (aligned_idx + total_needed > heap.len) {
|
||||
uart.print("[Alloc] OOM! Size: ");
|
||||
uart.print_hex(size);
|
||||
uart.print(" Used: ");
|
||||
uart.print_hex(heap_idx);
|
||||
uart.print("\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Trace allocations (disabled to reduce noise)
|
||||
// uart.print("[Alloc] ");
|
||||
// uart.print_hex(size);
|
||||
// uart.print(" -> Used: ");
|
||||
// uart.print_hex(aligned_idx + total_needed);
|
||||
// uart.print("\n");
|
||||
|
||||
const base_ptr = &heap[aligned_idx];
|
||||
const header = @as(*BlockHeader, @ptrCast(@alignCast(base_ptr)));
|
||||
header.size = size;
|
||||
|
||||
heap_idx = aligned_idx + total_needed;
|
||||
return @as(*anyopaque, @ptrFromInt(@intFromPtr(base_ptr) + @sizeOf(BlockHeader)));
|
||||
}
|
||||
|
||||
export fn free(ptr: ?*anyopaque) void {
|
||||
// Bump allocator: no-op free.
|
||||
_ = ptr;
|
||||
}
|
||||
|
||||
export fn realloc(ptr: ?*anyopaque, size: usize) ?*anyopaque {
|
||||
if (ptr == null) return malloc(size);
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retrieve old size from header
|
||||
const base_addr = @intFromPtr(ptr.?) - @sizeOf(BlockHeader);
|
||||
const header = @as(*BlockHeader, @ptrFromInt(base_addr));
|
||||
const old_size = header.size;
|
||||
|
||||
// Optimization: If new size is smaller and it's the last block, we could shrink?
|
||||
// But for a bump allocator, just allocate new.
|
||||
const new_ptr = malloc(size);
|
||||
if (new_ptr) |np| {
|
||||
const copy_size = if (size < old_size) size else old_size;
|
||||
const src = @as([*]const u8, @ptrCast(ptr.?));
|
||||
const dst = @as([*]u8, @ptrCast(np));
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < copy_size) : (i += 1) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
free(ptr);
|
||||
return np;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export fn calloc(nmemb: usize, size: usize) ?*anyopaque {
|
||||
const total = nmemb * size;
|
||||
const ptr = malloc(total);
|
||||
if (ptr) |p| {
|
||||
const dst = @as([*]u8, @ptrCast(p));
|
||||
var i: usize = 0;
|
||||
while (i < total) : (i += 1) {
|
||||
dst[i] = 0;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Rumpk Runtime Support
|
||||
// =========================================================
|
||||
|
||||
export fn get_ticks() u32 {
|
||||
return 0; // TODO: Implement real timer
|
||||
}
|
||||
|
|
@ -1,12 +1,23 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// Phase 35a: The Surface Allocator
|
||||
// Manages contiguous memory chunks for window buffers.
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: Surface Allocator
|
||||
//!
|
||||
//! Manages contiguous memory chunks for window buffers (compositor).
|
||||
//! Provides a simple pool-based allocation for up to 16 surfaces.
|
||||
//!
|
||||
//! DECISION(Graphics): Fixed pool size of 32MB for surfaces.
|
||||
//! Bump-style allocation; reclamation requires system reset.
|
||||
|
||||
const std = @import("std");
|
||||
const uart = @import("uart.zig");
|
||||
|
||||
pub const MAX_SURFACES = 16;
|
||||
pub const SURFACE_POOL_SIZE = 32 * 1024 * 1024; // 32MB for surfaces
|
||||
pub const SURFACE_POOL_SIZE = 1 * 1024 * 1024; // 1MB for surfaces (temporary reduction)
|
||||
|
||||
// Surface Descriptor
|
||||
pub const Surface = struct {
|
||||
|
|
@ -18,10 +29,13 @@ pub const Surface = struct {
|
|||
};
|
||||
|
||||
// Global Surface Pool
|
||||
// SAFETY(Surfaces): Array is initialized by hal_surface_init before use.
|
||||
var surfaces: [MAX_SURFACES]Surface = undefined;
|
||||
var next_surface_id: i32 = 1;
|
||||
|
||||
// Backing memory for surfaces (in BSS)
|
||||
// SAFETY(SurfaceHeap): Memory written by alloc before any read.
|
||||
// Initialized to `undefined` to avoid zeroing 32MB at boot.
|
||||
var surface_heap: [SURFACE_POOL_SIZE]u8 align(4096) = undefined;
|
||||
var heap_offset: usize = 0;
|
||||
|
||||
|
|
@ -29,6 +43,7 @@ export fn hal_surface_init() void {
|
|||
for (&surfaces) |*s| {
|
||||
s.id = -1;
|
||||
s.active = false;
|
||||
// SAFETY(Surfaces): Pointer reset to `undefined`. Populated during allocation.
|
||||
s.ptr = undefined;
|
||||
s.width = 0;
|
||||
s.height = 0;
|
||||
|
|
|
|||
21
hal/uart.zig
21
hal/uart.zig
|
|
@ -1,7 +1,18 @@
|
|||
// Rumpk Layer 0: UART Driver
|
||||
// Minimal serial output for QEMU 'virt' machine
|
||||
// Supports PL011 (ARM64) and 16550A (RISC-V)
|
||||
// Phase 37.2: Input buffering to prevent character loss
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: UART Driver
|
||||
//!
|
||||
//! Minimal serial I/O for QEMU 'virt' machine.
|
||||
//! Supports PL011 (ARM64) and 16550A (RISC-V).
|
||||
//!
|
||||
//! SAFETY: All MMIO accesses use volatile pointers.
|
||||
//! Ring buffer is initialized to undefined for performance;
|
||||
//! head/tail indices ensure only written bytes are read.
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
|
@ -23,6 +34,8 @@ const NS16550A_LCR: usize = 0x03; // Line Control Register
|
|||
|
||||
// Input Ring Buffer (256 bytes, power of 2 for fast masking)
|
||||
const INPUT_BUFFER_SIZE = 256;
|
||||
// SAFETY(RingBuffer): Only accessed via head/tail indices.
|
||||
// Bytes are written before read. No uninitialized reads possible.
|
||||
var input_buffer: [INPUT_BUFFER_SIZE]u8 = undefined;
|
||||
var input_head: u32 = 0; // Write position
|
||||
var input_tail: u32 = 0; // Read position
|
||||
|
|
|
|||
16
hal/ui.zig
16
hal/ui.zig
|
|
@ -1,3 +1,18 @@
|
|||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: UI Layer (The Persona)
|
||||
//!
|
||||
//! Bridges microui (C) with the Zig HAL and Framebuffer.
|
||||
//! Handles GUI rendering, layout management, and the boot animation loop.
|
||||
//!
|
||||
//! SAFETY: Integrates with a C-based GUI library via @cImport.
|
||||
//! Global context is initialized by `init()` before use in the UI fiber.
|
||||
|
||||
const std = @import("std");
|
||||
const fb = @import("framebuffer.zig");
|
||||
|
||||
|
|
@ -8,6 +23,7 @@ pub const c = @cImport({
|
|||
});
|
||||
|
||||
// --- STATIC MEMORY ---
|
||||
// SAFETY(UI): Context is initialized by `c.mu_init(&ctx)` in `init()`.
|
||||
var ctx: c.mu_Context = undefined;
|
||||
|
||||
// --- FONT (The "8-bit" classic) ---
|
||||
|
|
|
|||
|
|
@ -1,69 +1,59 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// Rumpk Layer 0: VirtIO-Block Driver (The Ledger)
|
||||
// - Provides persistent storage access (Sector I/O)
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: VirtIO-Block Driver
|
||||
//!
|
||||
//! Provides raw sector access for the unikernel storage system.
|
||||
//!
|
||||
//! SAFETY: Synchronous driver. Blocks current fiber until QEMU completes
|
||||
//! the request. Uses bounce-buffers to guarantee alignment.
|
||||
|
||||
const std = @import("std");
|
||||
const uart = @import("uart.zig");
|
||||
const pci = @import("virtio_pci.zig");
|
||||
|
||||
// External C/Zig stubs
|
||||
extern fn malloc(size: usize) ?*anyopaque;
|
||||
|
||||
var global_blk: ?VirtioBlkDriver = null;
|
||||
|
||||
export fn virtio_blk_read(sector: u64, buf: [*]u8) void {
|
||||
if (global_blk) |*d| {
|
||||
d.read_sync(sector, buf);
|
||||
} else {
|
||||
uart.print("[VirtIO-Blk] Error: Driver not initialized.\n");
|
||||
d.read(sector, buf[0..512]) catch {
|
||||
uart.print("[VirtIO-Blk] READ ERROR\n");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export fn virtio_blk_write(sector: u64, buf: [*]const u8) void {
|
||||
if (global_blk) |*d| {
|
||||
d.write_sync(sector, buf);
|
||||
} else {
|
||||
uart.print("[VirtIO-Blk] Error: Driver not initialized.\n");
|
||||
d.write(sector, buf[0..512]) catch {
|
||||
uart.print("[VirtIO-Blk] WRITE ERROR\n");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() void {
|
||||
if (VirtioBlkDriver.probe()) |*driver| {
|
||||
var d = driver.*;
|
||||
if (d.init_device()) {
|
||||
uart.print("[Rumpk L0] Storage initialized (The Ledger).\n");
|
||||
}
|
||||
if (VirtioBlkDriver.probe()) |_| {
|
||||
uart.print("[Rumpk L0] Storage initialized (The Ledger).\n");
|
||||
} else {
|
||||
uart.print("[Rumpk L0] No Storage Device Found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
const VIRTIO_BLK_T_IN: u32 = 0;
|
||||
const VIRTIO_BLK_T_OUT: u32 = 1;
|
||||
const SECTOR_SIZE: usize = 512;
|
||||
|
||||
pub const VirtioBlkDriver = struct {
|
||||
transport: pci.VirtioTransport,
|
||||
req_queue: ?*Virtqueue,
|
||||
last_used_idx: u16,
|
||||
|
||||
pub fn init(transport: pci.VirtioTransport) !VirtioBlkDriver {
|
||||
var driver = VirtioBlkDriver{
|
||||
.req_queue = null,
|
||||
.transport = transport,
|
||||
.last_used_idx = 0,
|
||||
};
|
||||
|
||||
if (!driver.init_device()) {
|
||||
return error.DeviceInitFailed;
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
v_desc: [*]volatile VirtioDesc,
|
||||
v_avail: *volatile VirtioAvail,
|
||||
v_used: *volatile VirtioUsed,
|
||||
queue_size: u16,
|
||||
|
||||
pub fn probe() ?VirtioBlkDriver {
|
||||
uart.print("[VirtIO] Probing PCI for Block device...\n");
|
||||
const PCI_ECAM_BASE: usize = 0x30000000;
|
||||
// Scan a few slots. Usually 00:02.0 if 00:01.0 is Net.
|
||||
// Or implement real PCI scan logic later.
|
||||
const bus: u8 = 0;
|
||||
const func: u8 = 0;
|
||||
|
||||
|
|
@ -74,191 +64,145 @@ pub const VirtioBlkDriver = struct {
|
|||
const ptr: *volatile u32 = @ptrFromInt(addr);
|
||||
const id = ptr.*;
|
||||
|
||||
// Device ID 0x1001 (Legacy Block) or 0x1042 (Modern Block)
|
||||
// 0x1042 = 0x1040 + 2
|
||||
if (id == 0x10011af4 or id == 0x10421af4) {
|
||||
uart.print("[VirtIO] Found VirtIO-Block device at PCI 00:0");
|
||||
uart.print_hex(i);
|
||||
uart.print(".0\n");
|
||||
return VirtioBlkDriver.init(pci.VirtioTransport.init(addr)) catch null;
|
||||
var self = VirtioBlkDriver{
|
||||
.transport = pci.VirtioTransport.init(addr),
|
||||
.v_desc = undefined,
|
||||
.v_avail = undefined,
|
||||
.v_used = undefined,
|
||||
.queue_size = 0,
|
||||
};
|
||||
if (self.init_device()) {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn init_device(self: *VirtioBlkDriver) bool {
|
||||
// 0. Probe Transport (Legacy/Modern)
|
||||
if (!self.transport.probe()) {
|
||||
uart.print("[VirtIO-Blk] Transport Probe Failed.\n");
|
||||
return false;
|
||||
if (!self.transport.probe()) return false;
|
||||
|
||||
self.transport.reset();
|
||||
self.transport.add_status(1);
|
||||
self.transport.add_status(2);
|
||||
|
||||
self.transport.select_queue(0);
|
||||
const count = self.transport.get_queue_size();
|
||||
|
||||
// [Desc] [Avail] [Used] (Simplified layout)
|
||||
const total = (count * 16) + (6 + count * 2) + 4096 + (6 + count * 8);
|
||||
const raw_ptr = malloc(total + 4096) orelse return false;
|
||||
const aligned = (@intFromPtr(raw_ptr) + 4095) & ~@as(usize, 4095);
|
||||
|
||||
self.v_desc = @ptrFromInt(aligned);
|
||||
self.v_avail = @ptrFromInt(aligned + (count * 16));
|
||||
self.v_used = @ptrFromInt(aligned + (count * 16) + (6 + count * 2) + 4096);
|
||||
self.queue_size = count;
|
||||
|
||||
if (self.transport.is_modern) {
|
||||
self.transport.setup_modern_queue(aligned, aligned + (count * 16), @intFromPtr(self.v_used));
|
||||
} else {
|
||||
self.transport.setup_legacy_queue(@intCast(aligned >> 12));
|
||||
}
|
||||
|
||||
// 1. Reset
|
||||
self.transport.reset();
|
||||
// 2. ACK + DRIVER
|
||||
self.transport.add_status(3);
|
||||
|
||||
// 3. Queue Setup (Queue 0 is Request Queue)
|
||||
self.transport.select_queue(0);
|
||||
const q_size = self.transport.get_queue_size();
|
||||
if (q_size == 0) return false;
|
||||
|
||||
self.req_queue = self.setup_queue(0, q_size) catch return false;
|
||||
|
||||
// 4. Driver OK
|
||||
self.transport.add_status(4);
|
||||
global_blk = self.*;
|
||||
|
||||
uart.print("[VirtIO-Blk] Device Ready. Queue Size: ");
|
||||
uart.print_hex(q_size);
|
||||
uart.print_hex(count);
|
||||
uart.print(" HeaderSize: ");
|
||||
uart.print_hex(@sizeOf(VirtioBlkReq));
|
||||
uart.print_hex(@sizeOf(VirtioBlkHeader));
|
||||
uart.print("\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn read_sync(self: *VirtioBlkDriver, sector: u64, buf: [*]u8) void {
|
||||
self.submit_request(VIRTIO_BLK_T_IN, sector, buf);
|
||||
}
|
||||
pub fn read(self: *VirtioBlkDriver, sector: u64, buf: []u8) !void {
|
||||
const header = VirtioBlkHeader{
|
||||
.type = 0, // READ
|
||||
.reserved = 0,
|
||||
.sector = sector,
|
||||
};
|
||||
var status: u8 = 0xFF;
|
||||
|
||||
pub fn write_sync(self: *VirtioBlkDriver, sector: u64, buf: [*]const u8) void {
|
||||
// Cast const away because submit_request buffer logic is generic, but T_OUT implies read from buf
|
||||
self.submit_request(VIRTIO_BLK_T_OUT, sector, @constCast(buf));
|
||||
}
|
||||
// Simple synchronous request: Use descriptors 0, 1, 2
|
||||
// Desc 0: Header (Read-only for device)
|
||||
self.v_desc[0].addr = @intFromPtr(&header);
|
||||
self.v_desc[0].len = @sizeOf(VirtioBlkHeader);
|
||||
self.v_desc[0].flags = 1; // NEXT
|
||||
self.v_desc[0].next = 1;
|
||||
|
||||
// SOVEREIGN BOUNCE BUFFERS (Aligned to avoid offset bugs)
|
||||
var bounce_header: VirtioBlkReq align(16) = undefined;
|
||||
var bounce_sector: [512]u8 align(4096) = undefined;
|
||||
var bounce_status: u8 align(16) = 0;
|
||||
// Desc 1: Data Buffer (Write-only for device)
|
||||
self.v_desc[1].addr = @intFromPtr(buf.ptr);
|
||||
self.v_desc[1].len = 512;
|
||||
self.v_desc[1].flags = 1 | 2; // NEXT | WRITE
|
||||
self.v_desc[1].next = 2;
|
||||
|
||||
fn submit_request(self: *VirtioBlkDriver, type_: u32, sector: u64, buf: [*]u8) void {
|
||||
const q = self.req_queue orelse return;
|
||||
const idx = q.avail.idx % q.num;
|
||||
// Desc 2: Status Byte (Write-only for device)
|
||||
self.v_desc[2].addr = @intFromPtr(&status);
|
||||
self.v_desc[2].len = 1;
|
||||
self.v_desc[2].flags = 2; // WRITE
|
||||
self.v_desc[2].next = 0;
|
||||
|
||||
// Use fixed descriptors indices 0, 1, 2
|
||||
const d1 = 0;
|
||||
const d2 = 1;
|
||||
const d3 = 2;
|
||||
|
||||
bounce_header.type = type_;
|
||||
bounce_header.reserved = 0;
|
||||
bounce_header.sector = sector;
|
||||
bounce_status = 0xFF;
|
||||
|
||||
const VRING_DESC_F_NEXT: u16 = 1;
|
||||
const VRING_DESC_F_WRITE: u16 = 2;
|
||||
|
||||
if (type_ == VIRTIO_BLK_T_OUT) {
|
||||
@memcpy(&bounce_sector, buf[0..512]);
|
||||
}
|
||||
|
||||
q.desc[d1].addr = @intFromPtr(&bounce_header);
|
||||
q.desc[d1].len = @sizeOf(VirtioBlkReq);
|
||||
q.desc[d1].flags = VRING_DESC_F_NEXT;
|
||||
q.desc[d1].next = d2;
|
||||
|
||||
q.desc[d2].addr = @intFromPtr(&bounce_sector);
|
||||
q.desc[d2].len = 512;
|
||||
if (type_ == VIRTIO_BLK_T_IN) {
|
||||
// Device writes to this buffer
|
||||
q.desc[d2].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
|
||||
} else {
|
||||
// Device reads from this buffer
|
||||
q.desc[d2].flags = VRING_DESC_F_NEXT;
|
||||
}
|
||||
q.desc[d2].next = d3;
|
||||
|
||||
q.desc[d3].addr = @intFromPtr(&bounce_status);
|
||||
q.desc[d3].len = 1;
|
||||
q.desc[d3].flags = VRING_DESC_F_WRITE;
|
||||
q.desc[d3].next = 0;
|
||||
|
||||
asm volatile ("fence" ::: .{ .memory = true });
|
||||
|
||||
const avail_ring = get_avail_ring(q.avail);
|
||||
avail_ring[idx] = d1;
|
||||
|
||||
asm volatile ("fence" ::: .{ .memory = true });
|
||||
q.avail.idx +%= 1;
|
||||
asm volatile ("fence" ::: .{ .memory = true });
|
||||
// Submit to Avail Ring
|
||||
const ring = @as([*]volatile u16, @ptrFromInt(@intFromPtr(self.v_avail) + 4));
|
||||
ring[self.v_avail.idx % self.queue_size] = 0; // Head of chain
|
||||
asm volatile ("fence w, w" ::: .{ .memory = true });
|
||||
self.v_avail.idx +%= 1;
|
||||
asm volatile ("fence w, w" ::: .{ .memory = true });
|
||||
|
||||
self.transport.notify(0);
|
||||
|
||||
// Polling Used Ring for Completion
|
||||
var timeout: usize = 10000000;
|
||||
const used_ptr = q.used;
|
||||
|
||||
while (used_ptr.idx == self.last_used_idx and timeout > 0) : (timeout -= 1) {
|
||||
asm volatile ("fence" ::: .{ .memory = true });
|
||||
// Wait for device (Polling)
|
||||
while (self.v_used.idx == 0) {
|
||||
asm volatile ("nop");
|
||||
}
|
||||
|
||||
if (timeout == 0) {
|
||||
uart.print("[VirtIO-Blk] Timeout Waiting for Used Ring!\n");
|
||||
} else {
|
||||
// Request Done.
|
||||
self.last_used_idx +%= 1;
|
||||
asm volatile ("fence" ::: .{ .memory = true });
|
||||
|
||||
if (bounce_status != 0) {
|
||||
uart.print("[VirtIO-Blk] I/O Error Status: ");
|
||||
uart.print_hex(bounce_status);
|
||||
uart.print("\n");
|
||||
} else if (type_ == VIRTIO_BLK_T_IN) {
|
||||
// Success Read: Copy bounce -> user
|
||||
const dest_slice = buf[0..512];
|
||||
@memcpy(dest_slice, &bounce_sector);
|
||||
}
|
||||
}
|
||||
if (status != 0) return error.DiskError;
|
||||
}
|
||||
|
||||
fn setup_queue(self: *VirtioBlkDriver, index: u16, count: u16) !*Virtqueue {
|
||||
// ...(Similar to Net)...
|
||||
// Allocate Memory
|
||||
const desc_size = 16 * @as(usize, count);
|
||||
const avail_size = 6 + 2 * @as(usize, count);
|
||||
const used_offset = (desc_size + avail_size + 4095) & ~@as(usize, 4095);
|
||||
const used_size = 6 + 8 * @as(usize, count);
|
||||
const total_size = used_offset + used_size;
|
||||
pub fn write(self: *VirtioBlkDriver, sector: u64, buf: []const u8) !void {
|
||||
const header = VirtioBlkHeader{
|
||||
.type = 1, // WRITE
|
||||
.reserved = 0,
|
||||
.sector = sector,
|
||||
};
|
||||
var status: u8 = 0xFF;
|
||||
|
||||
const raw_ptr = malloc(total_size + 4096) orelse return error.OutOfMemory;
|
||||
const aligned_addr = (@intFromPtr(raw_ptr) + 4095) & ~@as(usize, 4095);
|
||||
self.v_desc[3].addr = @intFromPtr(&header);
|
||||
self.v_desc[3].len = @sizeOf(VirtioBlkHeader);
|
||||
self.v_desc[3].flags = 1;
|
||||
self.v_desc[3].next = 4;
|
||||
|
||||
const q_ptr_raw = malloc(@sizeOf(Virtqueue)) orelse return error.OutOfMemory;
|
||||
const q_ptr: *Virtqueue = @ptrCast(@alignCast(q_ptr_raw));
|
||||
self.v_desc[4].addr = @intFromPtr(buf.ptr);
|
||||
self.v_desc[4].len = 512;
|
||||
self.v_desc[4].flags = 1; // Note: Write for disk is READ for device
|
||||
self.v_desc[4].next = 5;
|
||||
|
||||
q_ptr.num = count;
|
||||
q_ptr.desc = @ptrFromInt(aligned_addr);
|
||||
q_ptr.avail = @ptrFromInt(aligned_addr + desc_size);
|
||||
q_ptr.used = @ptrFromInt(aligned_addr + used_offset);
|
||||
self.v_desc[5].addr = @intFromPtr(&status);
|
||||
self.v_desc[5].len = 1;
|
||||
self.v_desc[5].flags = 2;
|
||||
self.v_desc[5].next = 0;
|
||||
|
||||
// Notify Device
|
||||
const phys_addr = aligned_addr;
|
||||
self.transport.select_queue(index);
|
||||
if (self.transport.is_modern) {
|
||||
self.transport.setup_modern_queue(phys_addr, phys_addr + desc_size, phys_addr + used_offset);
|
||||
} else {
|
||||
const pfn = @as(u32, @intCast(phys_addr >> 12));
|
||||
self.transport.setup_legacy_queue(pfn);
|
||||
const ring = @as([*]volatile u16, @ptrFromInt(@intFromPtr(self.v_avail) + 4));
|
||||
ring[self.v_avail.idx % self.queue_size] = 3;
|
||||
asm volatile ("fence w, w" ::: .{ .memory = true });
|
||||
self.v_avail.idx +%= 1;
|
||||
asm volatile ("fence w, w" ::: .{ .memory = true });
|
||||
|
||||
self.transport.notify(0);
|
||||
|
||||
while (status == 0xFF) {
|
||||
asm volatile ("nop");
|
||||
}
|
||||
|
||||
return q_ptr;
|
||||
if (status != 0) return error.DiskError;
|
||||
}
|
||||
|
||||
// structs ...
|
||||
const VirtioBlkReq = packed struct {
|
||||
type: u32,
|
||||
reserved: u32,
|
||||
sector: u64,
|
||||
};
|
||||
|
||||
const Virtqueue = struct {
|
||||
desc: [*]volatile VirtioDesc,
|
||||
avail: *volatile VirtioAvail,
|
||||
used: *volatile VirtioUsed,
|
||||
num: u16,
|
||||
};
|
||||
|
||||
const VirtioDesc = struct {
|
||||
addr: u64,
|
||||
len: u32,
|
||||
|
|
@ -276,7 +220,9 @@ pub const VirtioBlkDriver = struct {
|
|||
idx: u16,
|
||||
};
|
||||
|
||||
inline fn get_avail_ring(avail: *volatile VirtioAvail) [*]volatile u16 {
|
||||
return @ptrFromInt(@intFromPtr(avail) + 4);
|
||||
}
|
||||
const VirtioBlkHeader = extern struct {
|
||||
type: u32,
|
||||
reserved: u32,
|
||||
sector: u64,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
||||
// Rumpk Layer 0: VirtIO-Net Driver (Sovereign Edition)
|
||||
// - Uses VirtioTransport for PCI Capability Traversal
|
||||
// - Supports both Legacy (I/O & Memory) and Modern VirtIO
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk Layer 0: VirtIO-Net Driver (Sovereign Edition)
|
||||
//!
|
||||
//! Implements a zero-copy network interface using ION slabs for RX/TX.
|
||||
//! Supports both Legacy and Modern VirtIO via the universal transport layer.
|
||||
//!
|
||||
//! SAFETY: Uses volatile pointers for hardware rings and memory barriers (fences)
|
||||
//! to ensure correct synchronization with the virtual device.
|
||||
|
||||
const std = @import("std");
|
||||
const uart = @import("uart.zig");
|
||||
|
|
@ -71,11 +81,8 @@ export fn virtio_net_send(data: [*]const u8, len: usize) void {
|
|||
}
|
||||
|
||||
pub fn init() void {
|
||||
if (VirtioNetDriver.probe()) |*driver| {
|
||||
var d = driver.*;
|
||||
if (d.init_device()) {
|
||||
uart.print("[Rumpk L0] Networking initialized (Sovereign).\n");
|
||||
}
|
||||
if (VirtioNetDriver.probe()) |_| {
|
||||
uart.print("[Rumpk L0] Networking initialized (Sovereign).\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,16 +105,29 @@ pub const VirtioNetDriver = struct {
|
|||
uart.print("[VirtIO] Probing PCI for networking device...\n");
|
||||
const PCI_ECAM_BASE: usize = 0x30000000;
|
||||
const bus: u8 = 0;
|
||||
const dev: u8 = 1;
|
||||
const func: u8 = 0;
|
||||
|
||||
const addr = PCI_ECAM_BASE | (@as(usize, bus) << 20) | (@as(usize, dev) << 15) | (@as(usize, func) << 12);
|
||||
const ptr: *volatile u32 = @ptrFromInt(addr);
|
||||
const id = ptr.*;
|
||||
var i: u8 = 1;
|
||||
while (i <= 8) : (i += 1) {
|
||||
const addr = PCI_ECAM_BASE | (@as(usize, bus) << 20) | (@as(usize, i) << 15) | (@as(usize, func) << 12);
|
||||
const ptr: *volatile u32 = @ptrFromInt(addr);
|
||||
const id = ptr.*;
|
||||
|
||||
if (id == 0x10001af4 or id == 0x10411af4) {
|
||||
uart.print("[VirtIO] Found VirtIO-Net device at PCI 00:01.0\n");
|
||||
return VirtioNetDriver.init(addr, 33);
|
||||
uart.print("[VirtIO-Net] Probing dev ");
|
||||
uart.print_hex(i);
|
||||
uart.print(", ID: ");
|
||||
uart.print_hex(id);
|
||||
uart.print("\n");
|
||||
|
||||
if (id == 0x10001af4 or id == 0x10411af4) {
|
||||
uart.print("[VirtIO] Found VirtIO-Net device at PCI 00:0");
|
||||
uart.print_hex(i);
|
||||
uart.print(".0\n");
|
||||
var self = VirtioNetDriver.init(addr, 33);
|
||||
if (self.init_device()) {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,17 @@
|
|||
// core/rumpk/hal/virtio_pci.zig
|
||||
// Sovereign VirtIO Transport Layer
|
||||
// Handles PCI Capability Discovery and Universal Access
|
||||
// SPDX-License-Identifier: LCL-1.0
|
||||
// Copyright (c) 2026 Markus Maiwald
|
||||
// Stewardship: Self Sovereign Society Foundation
|
||||
//
|
||||
// This file is part of the Nexus Commonwealth.
|
||||
// See legal/LICENSE_COMMONWEALTH.md for license terms.
|
||||
|
||||
//! Rumpk HAL: Sovereign VirtIO Transport Layer
|
||||
//!
|
||||
//! Handles PCI Capability Discovery and provides a universal interface
|
||||
//! for accessing both Legacy and Modern VirtIO devices.
|
||||
//!
|
||||
//! SAFETY: All hardware registers are accessed via volatile pointers.
|
||||
//! Dynamically assigns BARs (Base Address Registers) if unassigned by firmware.
|
||||
|
||||
const std = @import("std");
|
||||
const uart = @import("uart.zig");
|
||||
|
|
@ -64,6 +75,14 @@ pub const VirtioTransport = struct {
|
|||
const cap_id = @as(*volatile u8, @ptrFromInt(cap_addr)).*;
|
||||
const cap_next = @as(*volatile u8, @ptrFromInt(cap_addr + 1)).*;
|
||||
|
||||
uart.print("[VirtIO-PCI] Cap at ");
|
||||
uart.print_hex(cap_offset);
|
||||
uart.print(" ID: ");
|
||||
uart.print_hex(cap_id);
|
||||
uart.print(" Next: ");
|
||||
uart.print_hex(cap_next);
|
||||
uart.print("\n");
|
||||
|
||||
if (cap_id == 0x09) { // Vendor Specific (VirtIO)
|
||||
const cap_type = @as(*volatile u8, @ptrFromInt(cap_addr + 3)).*;
|
||||
const bar_idx = @as(*volatile u8, @ptrFromInt(cap_addr + 4)).*;
|
||||
|
|
@ -71,20 +90,24 @@ pub const VirtioTransport = struct {
|
|||
|
||||
// Resolve BAR Address
|
||||
const bar_ptr = @as(*volatile u32, @ptrFromInt(self.base_addr + 0x10 + (@as(usize, bar_idx) * 4)));
|
||||
const bar_val = bar_ptr.*;
|
||||
|
||||
// Check if BAR is assigned
|
||||
if ((bar_ptr.* & 0xFFFFFFF0) == 0) {
|
||||
uart.print("[VirtIO-PCI] Initializing Unassigned BAR ");
|
||||
// Check if BAR is assigned and is a Memory BAR (bit 0 == 0)
|
||||
if ((bar_val & 0x1) == 0 and (bar_val & 0xFFFFFFF0) == 0) {
|
||||
uart.print("[VirtIO-PCI] Initializing Unassigned Memory BAR ");
|
||||
uart.print_hex(@as(u64, bar_idx));
|
||||
uart.print(" at ");
|
||||
uart.print_hex(next_mmio_addr);
|
||||
uart.print("\n");
|
||||
bar_ptr.* = next_mmio_addr;
|
||||
const rb = bar_ptr.*;
|
||||
uart.print("[VirtIO-PCI] BAR Assigned. Readback: ");
|
||||
uart.print_hex(rb);
|
||||
uart.print("\n");
|
||||
next_mmio_addr += 0x10000; // Increment 64KB
|
||||
}
|
||||
|
||||
// Basic BAR resolution (Memory only for Modern)
|
||||
// We assume Modern BARs are Memory Mapped
|
||||
// Refresh BAR resolution (Memory only for Modern)
|
||||
const bar_base = bar_ptr.* & 0xFFFFFFF0;
|
||||
|
||||
if (cap_type == VIRTIO_PCI_CAP_COMMON_CFG) {
|
||||
|
|
@ -98,9 +121,11 @@ pub const VirtioTransport = struct {
|
|||
self.notify_off_multiplier = @as(*volatile u32, @ptrFromInt(cap_addr + 16)).*;
|
||||
}
|
||||
if (cap_type == VIRTIO_PCI_CAP_ISR_CFG) {
|
||||
uart.print("[VirtIO-PCI] Found Modern ISR Config\n");
|
||||
self.isr_cfg = @ptrFromInt(bar_base + offset);
|
||||
}
|
||||
}
|
||||
uart.print("[VirtIO-PCI] Next Cap...\n");
|
||||
cap_offset = cap_next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
# SPDX-License-Identifier: LUL-1.0
|
||||
# Copyright (c) 2026 Markus Maiwald
|
||||
# Stewardship: Self Sovereign Society Foundation
|
||||
#
|
||||
# This file is part of the Nexus SDK.
|
||||
# See legal/LICENSE_UNBOUND.md for license terms.
|
||||
|
||||
# Rumpk Adaptive I/O Governor
|
||||
# War Mode (polling) ↔ Peace Mode (interrupts)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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 Membrane: Block I/O Client
|
||||
|
||||
# Membrane Block API (The Block Valve - Userland Side)
|
||||
# Phase 37.2: Sovereign Storage Architecture
|
||||
#
|
||||
|
|
|
|||
|
|
@ -159,6 +159,66 @@ void *memmove(void *dest, const void *src, size_t n) {
|
|||
return dest;
|
||||
}
|
||||
|
||||
char *strchr(const char *s, int c) {
|
||||
while (*s != (char)c) {
|
||||
if (!*s++) return NULL;
|
||||
}
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src) {
|
||||
char *d = dest;
|
||||
while ((*d++ = *src++));
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
while(*s1 && (*s1 == *s2)) {
|
||||
s1++; s2++;
|
||||
}
|
||||
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
|
||||
}
|
||||
|
||||
size_t strspn(const char *s, const char *accept) {
|
||||
const char *p = s;
|
||||
const char *a;
|
||||
while (*p) {
|
||||
for (a = accept; *a; a++) {
|
||||
if (*p == *a) break;
|
||||
}
|
||||
if (*a == '\0') return p - s;
|
||||
p++;
|
||||
}
|
||||
return p - s;
|
||||
}
|
||||
|
||||
size_t strcspn(const char *s, const char *reject) {
|
||||
const char *p = s;
|
||||
const char *r;
|
||||
while (*p) {
|
||||
for (r = reject; *r; r++) {
|
||||
if (*p == *r) return p - s;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return p - s;
|
||||
}
|
||||
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
static const uint32_t rtable[16] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
||||
};
|
||||
const uint8_t *data = (const uint8_t *)buffer;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
|
||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void console_write(const void* p, size_t len) {
|
||||
// Phase 7: Direct UART access for Proof of Life
|
||||
volatile char *uart = (volatile char *)0x10000000;
|
||||
|
|
@ -170,3 +230,5 @@ void console_write(const void* p, size_t len) {
|
|||
}
|
||||
|
||||
void ion_egress_to_port(uint16_t port, void* pkt);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
# 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 Membrane: Userland Graphics Compositor
|
||||
|
||||
# libs/membrane/compositor.nim
|
||||
# Phase 35b/d: The Sovereign Compositor + Input Router
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
Building lwIP
|
||||
=============
|
||||
|
||||
lwIP uses a CMake based build system.
|
||||
|
||||
The CMake files in this project are designed to
|
||||
be included into your own CMake files. They are
|
||||
mainly variable definitions containing a list of
|
||||
source files and predefined static libraries to
|
||||
be linked against application code.
|
||||
|
||||
1) lwIP sources:
|
||||
src/Filelists.cmake provides file lists containing
|
||||
the lwIP core library.
|
||||
The file also contains two static libraries, lwipcore
|
||||
and lwipallapps, where you can link your app against.
|
||||
This is the file that is useful to all lwIP users.
|
||||
|
||||
2) Example applications:
|
||||
contrib/Filelists.cmake provides several file lists
|
||||
containing the example applications.
|
||||
The file also contains several static libraries
|
||||
for these example apps.
|
||||
This file is only useful for you, if you can use one
|
||||
of the examples in your application, which is normally
|
||||
not the case.
|
||||
|
||||
3) OS/platform port:
|
||||
Usually the OS port needs to be provided by the user.
|
||||
If a port to Linux, Windows or MacOS is useful for
|
||||
you, you can use
|
||||
contrib/ports/{win32, unix}/Filelists.cmake
|
||||
that contains file lists and libraries for
|
||||
these operating systems.
|
||||
|
||||
VARIABLES
|
||||
=========
|
||||
In all cases, you need to provide two variables.
|
||||
|
||||
"LWIP_DIR" pointing to the lwIP directory
|
||||
Example:
|
||||
set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/externals/lwip)
|
||||
|
||||
"LWIP_INCLUDE_DIRS" that contains the include base paths
|
||||
- for lwIP itself (${LWIP_DIR}/src/include)
|
||||
- for lwIP contrib if you use it (${LWIP_DIR}/contrib)
|
||||
- to a directory containing an OS port
|
||||
- to a directory containing lwipopts.h
|
||||
|
||||
Example:
|
||||
set (LWIP_INCLUDE_DIRS
|
||||
"${LWIP_DIR}/src/include"
|
||||
"${LWIP_DIR}/contrib"
|
||||
"${LWIP_DIR}/contrib/ports/unix/port/include"
|
||||
"${LWIP_DIR}/contrib/examples/example_app"
|
||||
)
|
||||
|
||||
Putting it all together
|
||||
=======================
|
||||
To get a working application, your CMake system
|
||||
needs to provide the variables described above, e.g.
|
||||
set (LWIP_DIR <path to lwip sources>)
|
||||
set (LWIP_INCLUDE_DIRS
|
||||
"${LWIP_DIR}/src/include"
|
||||
"${LWIP_DIR}/contrib"
|
||||
"<path to my port>/include"
|
||||
"<path to lwipopts.h>"
|
||||
)
|
||||
|
||||
You may add some defines:
|
||||
set (LWIP_DEFINITIONS LWIP_DEBUG=1)
|
||||
|
||||
Then include the filelists you need:
|
||||
include(${LWIP_DIR}/src/Filelists.cmake)
|
||||
include(${LWIP_DIR}/contrib/Filelists.cmake)
|
||||
|
||||
Then, declare you executable:
|
||||
add_executable(my_app <my source files> <my lwip port files>)
|
||||
|
||||
Add lwIP include dirs to your app:
|
||||
target_include_directories(my_app PRIVATE ${LWIP_INCLUDE_DIRS})
|
||||
|
||||
Link your app against the lwIP libs from the filelists you need:
|
||||
target_link_libraries(my_app lwipcontribapps lwipallapps lwipcore)
|
||||
|
||||
Working example
|
||||
===============
|
||||
Working build examples can be found in the
|
||||
contrib/ports/{win32, unix}/example_app
|
||||
subdirectory.
|
||||
To use them, create a build directory and call cmake with
|
||||
the lwIP root dir:
|
||||
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- cmake --build .
|
||||
|
||||
The CMakeLists.txt will autoselect the correct port
|
||||
for your system (supported: Linux, Windows, Darwin).
|
||||
|
||||
To configure the example app to your needs, you need to copy the file
|
||||
contrib/examples/example_app/lwipcfg.h.example
|
||||
to
|
||||
contrib/examples/example_app/lwipcfg.h
|
||||
and edit to your needs.
|
||||
|
||||
Makefile based build system
|
||||
===========================
|
||||
lwIP also maintains file lists for Makefile-based
|
||||
build systems. Look for Filelists.mk files
|
||||
in the source tree. We try to maintain them,
|
||||
but lwIP's mainly focused build system is CMake.
|
||||
|
||||
MS Visual Studio
|
||||
================
|
||||
lwIP also provides basic support for MSVS in the win32 port
|
||||
folder under 'msvc'. We try to maintain these files,
|
||||
but lwIP's mainly focused build system is CMake.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,35 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set (CMAKE_CONFIGURATION_TYPES "Debug;Release")
|
||||
|
||||
project(lwIP)
|
||||
|
||||
# Example lwIP application
|
||||
set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set (LWIP_DEFINITIONS LWIP_DEBUG=1)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
add_subdirectory(${LWIP_DIR}/contrib/ports/win32/example_app)
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
add_subdirectory(${LWIP_DIR}/contrib/ports/unix/example_app)
|
||||
else()
|
||||
message(WARNING "Host ${CMAKE_SYSTEM_NAME} is not supported to build example_app")
|
||||
endif()
|
||||
|
||||
# Source package generation
|
||||
set(CPACK_SOURCE_GENERATOR "ZIP")
|
||||
set(CPACK_SOURCE_PACKAGE_DESCRIPTION_SUMMARY "lwIP lightweight IP stack")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${LWIP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${LWIP_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${LWIP_VERSION_REVISION}")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "/build/;${CPACK_SOURCE_IGNORE_FILES};.git")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "lwip-${LWIP_VERSION_MAJOR}.${LWIP_VERSION_MINOR}.${LWIP_VERSION_REVISION}")
|
||||
include(CPack)
|
||||
|
||||
# Generate docs before creating source package
|
||||
include(src/Filelists.cmake)
|
||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
|
||||
if (TARGET lwipdocs)
|
||||
add_dependencies(dist lwipdocs)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
lwIP is a small independent implementation of the TCP/IP protocol suite targeted at embedded systems.
|
||||
|
||||
The focus of the lwIP TCP/IP implementation is to reduce resource usage while still having a full scale TCP. This makes lwIP suitable for use in embedded systems with tens of kilobytes of free RAM and room for around 40 kilobytes of code ROM.
|
||||
|
||||
Main features include:
|
||||
- Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE, 6LowPAN (via IEEE 802.15.4, BLE or ZEP; since v2.1.0)
|
||||
- DHCP client, stateless DHCPv6 (since v2.1.0), DNS client (incl. mDNS hostname resolver), AutoIP/APIPA (Zeroconf), ACD (Address Conflict Detection), SNMP agent (v1, v2c, v3 (since v2.1.0), private MIB support & MIB compiler)
|
||||
- APIs: specialized APIs for enhanced performance & zero copy, optional Berkeley-alike socket API
|
||||
- Extended features: IP forwarding over multiple network interfaces
|
||||
- Extended TCP features: congestion control, RTT estimation and fast recovery/fast retransmit, sending SACKs (since v2.1.0), "altcp": nearly transparent TLS for any tcp pcb (since v2.1.0)
|
||||
- Addon applications: HTTP server (HTTPS via altcp), HTTP(S) client (since v2.1.0), SNTP client, SMTP client (SMTPS via altcp), ping, NetBIOS nameserver, mDNS responder, MQTT client (TLS support since v2.1.0), TFTP server, iPerf2 counterpart
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
contrib/ - lwIP examples, ports, and small apps (formerly http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git/)
|
||||
src/ - The source code for the lwIP TCP/IP stack.
|
||||
doc/ - The documentation for lwIP.
|
||||
test/ - Some code to test whether the sources do what they should.
|
||||
|
||||
See also the FILES file in each subdirectory.
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
INTRODUCTION
|
||||
|
||||
lwIP is a small independent implementation of the TCP/IP protocol suite.
|
||||
|
||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
||||
while still having a full scale TCP. This making lwIP suitable for use
|
||||
in embedded systems with tens of kilobytes of free RAM and room for
|
||||
around 40 kilobytes of code ROM.
|
||||
|
||||
lwIP was originally developed by Adam Dunkels at the Computer and Networks
|
||||
Architectures (CNA) lab at the Swedish Institute of Computer Science (SICS)
|
||||
and is now developed and maintained by a worldwide network of developers.
|
||||
|
||||
FEATURES
|
||||
|
||||
* IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over
|
||||
multiple network interfaces
|
||||
* ICMP (Internet Control Message Protocol) for network maintenance and debugging
|
||||
* IGMP (Internet Group Management Protocol) for multicast traffic management
|
||||
* MLD (Multicast listener discovery for IPv6). Aims to be compliant with
|
||||
RFC 2710. No support for MLDv2
|
||||
* ND (Neighbor discovery and stateless address autoconfiguration for IPv6).
|
||||
Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862
|
||||
(Address autoconfiguration)
|
||||
* DHCP, AutoIP/APIPA (Zeroconf), ACD (Address Conflict Detection)
|
||||
and (stateless) DHCPv6
|
||||
* UDP (User Datagram Protocol) including experimental UDP-lite extensions
|
||||
* TCP (Transmission Control Protocol) with congestion control, RTT estimation
|
||||
fast recovery/fast retransmit and sending SACKs
|
||||
* raw/native API for enhanced performance
|
||||
* Optional Berkeley-like socket API
|
||||
* TLS: optional layered TCP ("altcp") for nearly transparent TLS for any
|
||||
TCP-based protocol (ported to mbedTLS) (see changelog for more info)
|
||||
* PPPoS and PPPoE (Point-to-point protocol over Serial/Ethernet)
|
||||
* DNS (Domain name resolver incl. mDNS)
|
||||
* 6LoWPAN (via IEEE 802.15.4, BLE or ZEP)
|
||||
|
||||
|
||||
APPLICATIONS
|
||||
|
||||
* HTTP server with SSI and CGI (HTTPS via altcp)
|
||||
* SNMPv2c agent with MIB compiler (Simple Network Management Protocol), v3 via altcp
|
||||
* SNTP (Simple network time protocol)
|
||||
* NetBIOS name service responder
|
||||
* MDNS (Multicast DNS) responder
|
||||
* iPerf server implementation
|
||||
* MQTT client (TLS support via altcp)
|
||||
|
||||
|
||||
LICENSE
|
||||
|
||||
lwIP is freely available under a BSD license.
|
||||
|
||||
|
||||
DEVELOPMENT
|
||||
|
||||
lwIP has grown into an excellent TCP/IP stack for embedded devices,
|
||||
and developers using the stack often submit bug fixes, improvements,
|
||||
and additions to the stack to further increase its usefulness.
|
||||
|
||||
Development of lwIP is hosted on Savannah, a central point for
|
||||
software development, maintenance and distribution. Everyone can
|
||||
help improve lwIP by use of Savannah's interface, Git and the
|
||||
mailing list. A core team of developers will commit changes to the
|
||||
Git source tree.
|
||||
|
||||
The lwIP TCP/IP stack is maintained in the 'src' directory and
|
||||
contributions (such as platform ports and applications) are in
|
||||
the 'contrib' directory.
|
||||
|
||||
See doc/savannah.txt for details on Git server access for users and
|
||||
developers.
|
||||
|
||||
The current Git tree is web-browsable:
|
||||
https://git.savannah.gnu.org/cgit/lwip.git
|
||||
|
||||
Submit patches and bugs via the lwIP project page:
|
||||
https://savannah.nongnu.org/projects/lwip/
|
||||
|
||||
Continuous integration builds (GCC, clang):
|
||||
https://github.com/lwip-tcpip/lwip/actions
|
||||
|
||||
|
||||
DOCUMENTATION
|
||||
|
||||
Self documentation of the source code is regularly extracted from the current
|
||||
Git sources and is available from this web page:
|
||||
https://www.nongnu.org/lwip/
|
||||
|
||||
Also, there are mailing lists you can subscribe at
|
||||
https://savannah.nongnu.org/mail/?group=lwip
|
||||
plus searchable archives:
|
||||
https://lists.nongnu.org/archive/html/lwip-users/
|
||||
https://lists.nongnu.org/archive/html/lwip-devel/
|
||||
|
||||
There is a wiki about lwIP at
|
||||
https://lwip.wikia.com/wiki/LwIP_Wiki
|
||||
You might get questions answered there, but unfortunately, it is not as
|
||||
well maintained as it should be.
|
||||
|
||||
lwIP was originally written by Adam Dunkels:
|
||||
http://dunkels.com/adam/
|
||||
|
||||
Reading Adam's papers, the files in docs/, browsing the source code
|
||||
documentation and browsing the mailing list archives is a good way to
|
||||
become familiar with the design of lwIP.
|
||||
|
||||
Adam Dunkels <adam@sics.se>
|
||||
Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
This file lists major changes between release versions that require
|
||||
ports or applications to be changed. Use it to update a port or an
|
||||
application written for an older version of lwIP to correctly work
|
||||
with newer versions.
|
||||
|
||||
|
||||
(git master)
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
* The eth_addr_cmp and ip_addr_cmp set of functions have been renamed to eth_addr_eq, ip_addr_eq
|
||||
and so on, since they return non-zero on equality. Macros for the old names exist.
|
||||
* The sio_write function used by PPP now takes the data argument as const.
|
||||
|
||||
(2.2.0)
|
||||
|
||||
++ Repository changes:
|
||||
|
||||
* The contrib repository has been added into the main repository in the subdirectory 'contrib'
|
||||
(the old contrib repository remains online for reference but is not used any more)
|
||||
|
||||
(2.1.0)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* Use the new altcp API for seamless TLS integration into existing TCP applications (see changelog)
|
||||
* TCP only kills existing connections with a LOWER priority than the one currently being opened.
|
||||
Previous implementations also kill existing connections of the SAME priority.
|
||||
* ip4_route_src: parameter order is reversed: ip4_route_src(dest, src) -> ip4_route_src(src, dest)
|
||||
to make parameter order consistent with other ip*_route*() functions.
|
||||
Same also applies to LWIP_HOOK_IP4_ROUTE_SRC() parameter order.
|
||||
* pbuf API: pbuf->type (an u8_t holding the enum 'pbuf_type') has changed to only hold a
|
||||
description of the pbuf (e.g. data following pbuf struct, data volatile, allocation
|
||||
source heap/pool/etc.). As a consequence, applications can't test pbuf->type any more.
|
||||
Use pbuf_match_type(pbuf, type) instead.
|
||||
* socket API: according to the standard, SO_ERROR now only returns asynchronous errors.
|
||||
All other/normal/synchronous errors are (and always were) available via 'errno'.
|
||||
LWIP_SOCKET_SET_ERRNO has been removed - 'errno' is always set - and required!
|
||||
* httpd LWIP_HTTPD_CGI_SSI: httpd_cgi_handler() has an additional parameter "struct fs_file *"
|
||||
|
||||
++ Port changes:
|
||||
|
||||
* tcpip_trycallback() was renamed to tcpip_callbackmsg_trycallback() to avoid confusion
|
||||
with tcpip_try_callback()
|
||||
* compatibility headers: moved from 'src/include/posix' to 'src/include/compat/posix',
|
||||
'src/include/compat/stdc' etc.
|
||||
* The IPv6 implementation now supports address scopes. (See LWIP_IPV6_SCOPES documentation
|
||||
and ip6_zone.h for more documentation)
|
||||
* LWIP_HOOK_DHCP_APPEND_OPTIONS() has changed, see description in opt.h (options_out_len is not
|
||||
available in struct dhcp any more)
|
||||
* Added debug helper asserts to ensure threading/locking requirements are met (define
|
||||
LWIP_MARK_TCPIP_THREAD() and LWIP_ASSERT_CORE_LOCKED()).
|
||||
* Added sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr()
|
||||
These can be used to post preallocated messages from an ISR to the tcpip thread
|
||||
(e.g. when using FreeRTOS)
|
||||
|
||||
(2.0.2)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* slipif: The way to pass serial port number has changed. netif->num is not
|
||||
supported any more, netif->state is interpreted as an u8_t port number now
|
||||
(it's not a POINTER to an u8_t any more!)
|
||||
|
||||
(2.0.1)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
|
||||
netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare
|
||||
ip_current_netif() to the desired netif for every packet.
|
||||
See bug #49662 for an explanation.
|
||||
|
||||
(2.0.0)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of
|
||||
"ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif
|
||||
has to be set "up" before starting the DHCP client
|
||||
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
||||
* Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only).
|
||||
* Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs);
|
||||
supports SNMPv2c (experimental v3 support)
|
||||
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
|
||||
|
||||
+++ Raw API:
|
||||
* Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/
|
||||
tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb
|
||||
|
||||
+++ Socket API:
|
||||
* Added an implementation for posix sendmsg()
|
||||
* Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
|
||||
|
||||
++ Port changes
|
||||
|
||||
+++ new files:
|
||||
* MANY new and moved files!
|
||||
* Added src/Filelists.mk for use in Makefile projects
|
||||
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
|
||||
to let abc.h only contain the actual application programmer's API
|
||||
|
||||
+++ sys layer:
|
||||
* Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than
|
||||
the traditional message passing (although with LWIP_COMPAT_MUTEX you are still
|
||||
open to priority inversion, so this is not recommended any more)
|
||||
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
|
||||
instead of using one per netconn (these semaphores are used even with core locking
|
||||
enabled as some longer lasting functions like big writes still need to delay)
|
||||
* Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
|
||||
in def.h (to be overridden in cc.h) instead of config
|
||||
options for netbiosns, httpd, dns, etc. ...
|
||||
* New abstraction for hton* and ntoh* functions in def.h.
|
||||
To override them, use the following in cc.h:
|
||||
#define lwip_htons(x) <your_htons>
|
||||
#define lwip_htonl(x) <your_htonl>
|
||||
|
||||
+++ new options:
|
||||
* TODO
|
||||
|
||||
+++ new pools:
|
||||
* Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
|
||||
that share memp.c code but do not have to be made global via lwippools.h
|
||||
* Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
|
||||
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
|
||||
is now available
|
||||
|
||||
* Signature of LWIP_HOOK_VLAN_SET macro was changed
|
||||
|
||||
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
|
||||
or to move buffers to dedicated memory using compiler attributes
|
||||
|
||||
* Standard C headers are used to define sized types and printf formatters
|
||||
(disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
|
||||
does not support these)
|
||||
|
||||
|
||||
++ Major bugfixes/improvements
|
||||
|
||||
* Added IPv6 support (dual-stack or IPv4/IPv6 only)
|
||||
* Major rewrite of PPP (incl. keep-up with apache pppd)
|
||||
see doc/ppp.txt for an upgrading how-to
|
||||
* Major rewrite of SNMP (incl. MIB parser)
|
||||
* Fixed timing issues that might have lead to losing a DHCP lease
|
||||
* Made rx processing path more robust against crafted errors
|
||||
* TCP window scaling support
|
||||
* modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
|
||||
* made DNS client more robust
|
||||
* support PBUF_REF for RX packets
|
||||
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
|
||||
threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
|
||||
* Moved and reordered stats (mainly memp/mib2)
|
||||
|
||||
(1.4.0)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
|
||||
compatibility to old applications, but will be removed in the future).
|
||||
|
||||
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
|
||||
|
||||
+++ Raw API:
|
||||
* Changed the semantics of tcp_close() (since it was rather a
|
||||
shutdown before): Now the application does *NOT* get any calls to the recv
|
||||
callback (aside from NULL/closed) after calling tcp_close()
|
||||
|
||||
* When calling tcp_abort() from a raw API TCP callback function,
|
||||
make sure you return ERR_ABRT to prevent accessing unallocated memory.
|
||||
(ERR_ABRT now means the applicaiton has called tcp_abort!)
|
||||
|
||||
+++ Netconn API:
|
||||
* Changed netconn_receive() and netconn_accept() to return
|
||||
err_t, not a pointer to new data/netconn.
|
||||
|
||||
+++ Socket API:
|
||||
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
|
||||
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
|
||||
|
||||
* Added a minimal version of posix fctl() to have a
|
||||
standardised way to set O_NONBLOCK for nonblocking sockets.
|
||||
|
||||
+++ all APIs:
|
||||
* correctly implemented SO(F)_REUSEADDR
|
||||
|
||||
++ Port changes
|
||||
|
||||
+++ new files:
|
||||
|
||||
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
|
||||
|
||||
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
|
||||
the actual application programmer's API
|
||||
|
||||
* Separated timer implementation from sys.h/.c, moved to timers.h/.c;
|
||||
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
|
||||
still want to use your own timer implementation for NO_SYS==0 (as before).
|
||||
|
||||
+++ sys layer:
|
||||
|
||||
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
|
||||
sys_sem_t;
|
||||
|
||||
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
|
||||
|
||||
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
|
||||
binary semaphores instead of mutexes - as before)
|
||||
|
||||
+++ new options:
|
||||
|
||||
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to
|
||||
prevent creating many small pbufs when calling tcp_write with many small
|
||||
blocks of data. Instead, pbufs are allocated larger than needed and the
|
||||
space is used for later calls to tcp_write.
|
||||
|
||||
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
|
||||
in tcp_write/udp_send.
|
||||
|
||||
* Added an additional option LWIP_ETHERNET to support ethernet without ARP
|
||||
(necessary for pure PPPoE)
|
||||
|
||||
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
|
||||
be used to place these pools into user-defined memory by using external
|
||||
declaration.
|
||||
|
||||
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
|
||||
|
||||
+++ new pools:
|
||||
|
||||
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
|
||||
so MEMP_NUM_NETDB has to be set accordingly.
|
||||
|
||||
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
|
||||
MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
|
||||
|
||||
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
|
||||
to be set accordingly.
|
||||
|
||||
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
|
||||
has to be set accordingly
|
||||
|
||||
* Integrated loopif into netif.c - loopif does not have to be created by the
|
||||
port any more, just define LWIP_HAVE_LOOPIF to 1.
|
||||
|
||||
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
|
||||
in cc.h, e.g. used by igmp)
|
||||
|
||||
* Added printf-formatter X8_F to printf u8_t as hex
|
||||
|
||||
* The heap now may be moved to user-defined memory by defining
|
||||
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
|
||||
|
||||
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
|
||||
with user-allocated structs instead of calling mem_malloc
|
||||
|
||||
* Added const char* name to mem- and memp-stats for easier debugging.
|
||||
|
||||
* Calculate the TCP/UDP checksum while copying to only fetch data once:
|
||||
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
|
||||
|
||||
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
|
||||
more than one pcb.
|
||||
|
||||
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
|
||||
off any more, if this is set to 0, only one packet (the most recent one) is
|
||||
queued (like demanded by RFC 1122).
|
||||
|
||||
|
||||
++ Major bugfixes/improvements
|
||||
|
||||
* Implemented tcp_shutdown() to only shut down one end of a connection
|
||||
* Implemented shutdown() at socket- and netconn-level
|
||||
* Added errorset support to select() + improved select speed overhead
|
||||
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
|
||||
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
|
||||
* Use macros defined in ip_addr.h to work with IP addresses
|
||||
* Implemented many nonblocking socket/netconn functions
|
||||
* Fixed ARP input processing: only add a new entry if a request was directed as us
|
||||
* mem_realloc() to mem_trim() to prevent confusion with realloc()
|
||||
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break
|
||||
existing connections when assigning a routable address)
|
||||
* Correctly handle remote side overrunning our rcv_wnd in ooseq case
|
||||
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers
|
||||
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
|
||||
* Added support for static ARP table entries
|
||||
|
||||
(STABLE-1.3.2)
|
||||
|
||||
* initial version of this file
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2017 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
# Copyright 2014 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||
# Copyright 2014 Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
|
||||
# Copyright 2020 Jonathan Demeyer <jona.dem@gmail.com>
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
changed_files() {
|
||||
: ${FILEREGEX:='\.([CcHh])$'}
|
||||
: ${EXCLUDE:=''}
|
||||
: ${DIFFFILTER:='ACMR'}
|
||||
|
||||
DIFFFILTER="--diff-filter=${DIFFFILTER}"
|
||||
|
||||
# select either all or only touched-in-branch files, filter through FILEREGEX
|
||||
if [ -z "${BASE_BRANCH}" ]; then
|
||||
FILES="$(git ls-tree -r --full-tree --name-only HEAD | grep -E ${FILEREGEX})"
|
||||
else
|
||||
FILES="$(git diff ${DIFFFILTER} --name-only ${BASE_BRANCH} | grep -E ${FILEREGEX})"
|
||||
fi
|
||||
|
||||
# filter out negatives
|
||||
echo "${FILES}" | grep -v -E ${EXCLUDE}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2019 Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
CODESPELL_CMD="codespell"
|
||||
|
||||
if tput colors &> /dev/null && [ "$(tput colors)" -ge 8 ]; then
|
||||
CERROR=$'\033[1;31m'
|
||||
CRESET=$'\033[0m'
|
||||
else
|
||||
CERROR=
|
||||
CRESET=
|
||||
fi
|
||||
|
||||
: "${LWIPBASE:=$(cd $(dirname $0)/; pwd)}"
|
||||
cd $LWIPBASE
|
||||
|
||||
: "${LWIPTOOLS:=${LWIPBASE}}"
|
||||
. "${LWIPTOOLS}"/codespell_changed_files.sh
|
||||
|
||||
FILEREGEX='\.([CcHh]|sh|py|md|txt)$'
|
||||
EXCLUDE='^(./contrib/apps/LwipMibCompiler/Mibs)'
|
||||
FILES=$(FILEREGEX=${FILEREGEX} EXCLUDE=${EXCLUDE} changed_files)
|
||||
|
||||
if [ -z "${FILES}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
${CODESPELL_CMD} --version &> /dev/null || {
|
||||
printf "%s%s: cannot execute \"%s\"!%s\n" "${CERROR}" "$0" "${CODESPELL_CMD}" "${CRESET}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
CODESPELL_OPTS="-q 2" # Disable "WARNING: Binary file"
|
||||
CODESPELL_OPTS+=" --check-hidden"
|
||||
# Disable false positives "nd => and, 2nd", "ans => and", "tolen => token",
|
||||
# "ofo => of", "WAN => WANT", "mut => must, mutt, moot"
|
||||
CODESPELL_OPTS+=" --ignore-words-list=nd,ans,tolen,ofo,wan,mut "
|
||||
# propagate all options to codespell -> pass "-w" to this script to write changes
|
||||
CODESPELL_OPTS+="$@"
|
||||
|
||||
# Filter-out all false positive raising "disabled due to" messages.
|
||||
ERRORS=$(${CODESPELL_CMD} ${CODESPELL_OPTS} ${FILES} | grep -ve "disabled due to")
|
||||
|
||||
if [ -n "${ERRORS}" ]
|
||||
then
|
||||
printf "%sThere are typos in the following files:%s\n\n" "${CERROR}" "${CRESET}"
|
||||
printf "%s\n" "${ERRORS}"
|
||||
# TODO: return 1 when all typos are fixed
|
||||
exit 0
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
typedef unsigned char err_t;
|
||||
typedef unsigned int u32_t;
|
||||
typedef unsigned short u16_t;
|
||||
typedef unsigned char u8_t;
|
||||
typedef void sys_sem_t;
|
||||
typedef void sys_mutex_t;
|
||||
typedef size_t mem_size_t;
|
||||
typedef size_t memp_t;
|
||||
struct pbuf;
|
||||
struct netif;
|
||||
|
||||
void* mem_malloc(mem_size_t size)
|
||||
{
|
||||
__coverity_alloc__(size);
|
||||
}
|
||||
void mem_free(void* mem)
|
||||
{
|
||||
__coverity_free__(mem);
|
||||
}
|
||||
|
||||
void* memp_malloc(memp_t type)
|
||||
{
|
||||
__coverity_alloc_nosize__();
|
||||
}
|
||||
void memp_free(memp_t type, void* mem)
|
||||
{
|
||||
__coverity_free__(mem);
|
||||
}
|
||||
|
||||
void sys_mutex_lock(sys_mutex_t* mutex)
|
||||
{
|
||||
__coverity_exclusive_lock_acquire__(mutex);
|
||||
}
|
||||
void sys_mutex_unlock(sys_mutex_t* mutex)
|
||||
{
|
||||
__coverity_exclusive_lock_release__(mutex);
|
||||
}
|
||||
|
||||
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
||||
{
|
||||
__coverity_recursive_lock_acquire__(sem);
|
||||
}
|
||||
void sys_sem_signal(sys_sem_t *sem)
|
||||
{
|
||||
__coverity_recursive_lock_release__(sem);
|
||||
}
|
||||
|
||||
err_t ethernet_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
__coverity_tainted_string_sink_content__(p);
|
||||
}
|
||||
err_t tcpip_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
__coverity_tainted_string_sink_content__(p);
|
||||
}
|
||||
err_t ip_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
__coverity_tainted_string_sink_content__(p);
|
||||
}
|
||||
err_t ip4_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
__coverity_tainted_string_sink_content__(p);
|
||||
}
|
||||
err_t ip6_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
__coverity_tainted_string_sink_content__(p);
|
||||
}
|
||||
|
||||
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
|
||||
{
|
||||
__coverity_tainted_string_argument__(buf);
|
||||
__coverity_tainted_data_argument__(buf);
|
||||
}
|
||||
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
|
||||
{
|
||||
__coverity_tainted_string_argument__(buf);
|
||||
__coverity_tainted_data_argument__(buf);
|
||||
}
|
||||
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
||||
{
|
||||
__coverity_tainted_data_transitive__(p_to, p_from);
|
||||
}
|
||||
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
|
||||
{
|
||||
__coverity_tainted_string_argument__(dataptr);
|
||||
__coverity_tainted_data_argument__(dataptr);
|
||||
}
|
||||
u8_t pbuf_get_at(struct pbuf* p, u16_t offset)
|
||||
{
|
||||
__coverity_tainted_data_return__();
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
int check_path(char* path, size_t size)
|
||||
{
|
||||
if (size) {
|
||||
__coverity_tainted_data_sanitize__(path);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
# This file is indended to be included in end-user CMakeLists.txt
|
||||
# include(/path/to/Filelists.cmake)
|
||||
# It assumes the variable LWIP_CONTRIB_DIR is defined pointing to the
|
||||
# root path of lwIP/contrib sources.
|
||||
#
|
||||
# This file is NOT designed (on purpose) to be used as cmake
|
||||
# subdir via add_subdirectory()
|
||||
# The intention is to provide greater flexibility to users to
|
||||
# create their own targets using the *_SRCS variables.
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
|
||||
include_guard(GLOBAL)
|
||||
endif()
|
||||
|
||||
set(lwipcontribexamples_SRCS
|
||||
${LWIP_CONTRIB_DIR}/examples/httpd/fs_example/fs_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/httpd/https_example/https_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/httpd/ssi_example/ssi_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/lwiperf/lwiperf_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/mdns/mdns_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/mqtt/mqtt_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/ppp/pppos_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/snmp/snmp_private_mib/lwip_prvmib.c
|
||||
${LWIP_CONTRIB_DIR}/examples/snmp/snmp_v3/snmpv3_dummy.c
|
||||
${LWIP_CONTRIB_DIR}/examples/snmp/snmp_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/sntp/sntp_example.c
|
||||
${LWIP_CONTRIB_DIR}/examples/tftp/tftp_example.c
|
||||
)
|
||||
add_library(lwipcontribexamples EXCLUDE_FROM_ALL ${lwipcontribexamples_SRCS})
|
||||
target_compile_options(lwipcontribexamples PRIVATE ${LWIP_COMPILER_FLAGS})
|
||||
target_compile_definitions(lwipcontribexamples PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS})
|
||||
target_include_directories(lwipcontribexamples PRIVATE ${LWIP_INCLUDE_DIRS} ${LWIP_MBEDTLS_INCLUDE_DIRS})
|
||||
|
||||
set(lwipcontribapps_SRCS
|
||||
${LWIP_CONTRIB_DIR}/apps/httpserver/httpserver-netconn.c
|
||||
${LWIP_CONTRIB_DIR}/apps/chargen/chargen.c
|
||||
${LWIP_CONTRIB_DIR}/apps/udpecho/udpecho.c
|
||||
${LWIP_CONTRIB_DIR}/apps/tcpecho/tcpecho.c
|
||||
${LWIP_CONTRIB_DIR}/apps/shell/shell.c
|
||||
${LWIP_CONTRIB_DIR}/apps/udpecho_raw/udpecho_raw.c
|
||||
${LWIP_CONTRIB_DIR}/apps/tcpecho_raw/tcpecho_raw.c
|
||||
${LWIP_CONTRIB_DIR}/apps/netio/netio.c
|
||||
${LWIP_CONTRIB_DIR}/apps/ping/ping.c
|
||||
${LWIP_CONTRIB_DIR}/apps/socket_examples/socket_examples.c
|
||||
${LWIP_CONTRIB_DIR}/apps/rtp/rtp.c
|
||||
)
|
||||
add_library(lwipcontribapps EXCLUDE_FROM_ALL ${lwipcontribapps_SRCS})
|
||||
target_compile_options(lwipcontribapps PRIVATE ${LWIP_COMPILER_FLAGS})
|
||||
target_compile_definitions(lwipcontribapps PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS})
|
||||
target_include_directories(lwipcontribapps PRIVATE ${LWIP_INCLUDE_DIRS} ${LWIP_MBEDTLS_INCLUDE_DIRS})
|
||||
|
||||
set(lwipcontribaddons_SRCS
|
||||
${LWIP_CONTRIB_DIR}/addons/tcp_isn/tcp_isn.c
|
||||
${LWIP_CONTRIB_DIR}/addons/ipv6_static_routing/ip6_route_table.c
|
||||
# ${LWIP_CONTRIB_DIR}/addons/netconn/external_resolve/dnssd.c
|
||||
# ${LWIP_CONTRIB_DIR}/addons/tcp_md5/tcp_md5.c
|
||||
)
|
||||
add_library(lwipcontribaddons EXCLUDE_FROM_ALL ${lwipcontribaddons_SRCS})
|
||||
target_compile_options(lwipcontribaddons PRIVATE ${LWIP_COMPILER_FLAGS})
|
||||
target_compile_definitions(lwipcontribaddons PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS})
|
||||
target_include_directories(lwipcontribaddons PRIVATE ${LWIP_INCLUDE_DIRS} ${LWIP_MBEDTLS_INCLUDE_DIRS})
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#
|
||||
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
# OF SUCH DAMAGE.
|
||||
#
|
||||
# This file is part of the lwIP TCP/IP stack.
|
||||
#
|
||||
# Author: Adam Dunkels <adam@sics.se>
|
||||
#
|
||||
|
||||
# CONTRIBAPPFILES: Contrib Applications.
|
||||
CONTRIBAPPFILES=$(CONTRIBDIR)/apps/httpserver/httpserver-netconn.c \
|
||||
$(CONTRIBDIR)/apps/chargen/chargen.c \
|
||||
$(CONTRIBDIR)/apps/udpecho/udpecho.c \
|
||||
$(CONTRIBDIR)/apps/tcpecho/tcpecho.c \
|
||||
$(CONTRIBDIR)/apps/shell/shell.c \
|
||||
$(CONTRIBDIR)/apps/udpecho_raw/udpecho_raw.c \
|
||||
$(CONTRIBDIR)/apps/tcpecho_raw/tcpecho_raw.c \
|
||||
$(CONTRIBDIR)/apps/netio/netio.c \
|
||||
$(CONTRIBDIR)/apps/ping/ping.c \
|
||||
$(CONTRIBDIR)/apps/socket_examples/socket_examples.c \
|
||||
$(CONTRIBDIR)/apps/rtp/rtp.c \
|
||||
$(CONTRIBDIR)/examples/httpd/fs_example/fs_example.c \
|
||||
$(CONTRIBDIR)/examples/httpd/https_example/https_example.c \
|
||||
$(CONTRIBDIR)/examples/httpd/ssi_example/ssi_example.c \
|
||||
$(CONTRIBDIR)/examples/lwiperf/lwiperf_example.c \
|
||||
$(CONTRIBDIR)/examples/mdns/mdns_example.c \
|
||||
$(CONTRIBDIR)/examples/mqtt/mqtt_example.c \
|
||||
$(CONTRIBDIR)/examples/ppp/pppos_example.c \
|
||||
$(CONTRIBDIR)/examples/snmp/snmp_private_mib/lwip_prvmib.c \
|
||||
$(CONTRIBDIR)/examples/snmp/snmp_v3/snmpv3_dummy.c \
|
||||
$(CONTRIBDIR)/examples/snmp/snmp_example.c \
|
||||
$(CONTRIBDIR)/examples/sntp/sntp_example.c \
|
||||
$(CONTRIBDIR)/examples/tftp/tftp_example.c \
|
||||
$(CONTRIBDIR)/addons/tcp_isn/tcp_isn.c \
|
||||
$(CONTRIBDIR)/addons/ipv6_static_routing/ip6_route_table.c
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
A simple example of using LWIP_HOOK_DHCP_PARSE/APPEND_OPTION hooks to implement:
|
||||
* DHCP_OPTION_MTU (option 26) to update the netif's MTU
|
||||
* DHCP_OPTION_CLIENT_ID (option 61) to advertize client's HW id of LWIP_IANA_HWTYPE_ETHERNET type
|
||||
|
||||
Please follow the instructions in dhcp_extra_opts.h to add the hooks, definitions in lwipopts.h and enabling the extra options.
|
||||
91
libs/membrane/external/lwip/contrib/addons/dhcp_extra_opts/dhcp_extra_opts.c
vendored
Normal file
91
libs/membrane/external/lwip/contrib/addons/dhcp_extra_opts/dhcp_extra_opts.c
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) Espressif Systems (Shanghai) CO LTD
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/prot/dhcp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/prot/iana.h"
|
||||
|
||||
|
||||
void dhcp_parse_extra_opts(struct dhcp *dhcp, uint8_t state, uint8_t option, uint8_t len, struct pbuf* p, uint16_t offset)
|
||||
{
|
||||
LWIP_UNUSED_ARG(dhcp);
|
||||
LWIP_UNUSED_ARG(state);
|
||||
LWIP_UNUSED_ARG(option);
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(p);
|
||||
LWIP_UNUSED_ARG(offset);
|
||||
#if LWIP_DHCP_ENABLE_MTU_UPDATE
|
||||
if ((option == DHCP_OPTION_MTU) &&
|
||||
(state == DHCP_STATE_REBOOTING || state == DHCP_STATE_REBINDING ||
|
||||
state == DHCP_STATE_RENEWING || state == DHCP_STATE_REQUESTING)) {
|
||||
u32_t mtu = 0;
|
||||
struct netif *netif;
|
||||
LWIP_ERROR("dhcp_parse_extra_opts(): MTU option's len != 2", len == 2, return;);
|
||||
LWIP_ERROR("dhcp_parse_extra_opts(): extracting MTU option failed",
|
||||
pbuf_copy_partial(p, &mtu, 2, offset) == 2, return;);
|
||||
mtu = lwip_htons((u16_t)mtu);
|
||||
NETIF_FOREACH(netif) {
|
||||
/* find the netif related to this dhcp */
|
||||
if (dhcp == netif_dhcp_data(netif)) {
|
||||
if (mtu < netif->mtu) {
|
||||
netif->mtu = mtu;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_parse_extra_opts(): Negotiated netif MTU is %d\n", netif->mtu));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} /* DHCP_OPTION_MTU */
|
||||
#endif /* LWIP_DHCP_ENABLE_MTU_UPDATE */
|
||||
}
|
||||
|
||||
void dhcp_append_extra_opts(struct netif *netif, uint8_t state, struct dhcp_msg *msg_out, uint16_t *options_out_len)
|
||||
{
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
LWIP_UNUSED_ARG(state);
|
||||
LWIP_UNUSED_ARG(msg_out);
|
||||
LWIP_UNUSED_ARG(options_out_len);
|
||||
#if LWIP_DHCP_ENABLE_CLIENT_ID
|
||||
if (state == DHCP_STATE_RENEWING || state == DHCP_STATE_REBINDING ||
|
||||
state == DHCP_STATE_REBOOTING || state == DHCP_STATE_OFF ||
|
||||
state == DHCP_STATE_REQUESTING || state == DHCP_STATE_BACKING_OFF || state == DHCP_STATE_SELECTING) {
|
||||
size_t i;
|
||||
u8_t *options = msg_out->options + *options_out_len;
|
||||
LWIP_ERROR("dhcp_append(client_id): options_out_len + 3 + netif->hwaddr_len <= DHCP_OPTIONS_LEN",
|
||||
*options_out_len + 3U + netif->hwaddr_len <= DHCP_OPTIONS_LEN, return;);
|
||||
*options_out_len = *options_out_len + netif->hwaddr_len + 3;
|
||||
*options++ = DHCP_OPTION_CLIENT_ID;
|
||||
*options++ = netif->hwaddr_len + 1; /* option size */
|
||||
*options++ = LWIP_IANA_HWTYPE_ETHERNET;
|
||||
for (i = 0; i < netif->hwaddr_len; i++) {
|
||||
*options++ = netif->hwaddr[i];
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_DHCP_ENABLE_CLIENT_ID */
|
||||
}
|
||||
61
libs/membrane/external/lwip/contrib/addons/dhcp_extra_opts/dhcp_extra_opts.h
vendored
Normal file
61
libs/membrane/external/lwip/contrib/addons/dhcp_extra_opts/dhcp_extra_opts.h
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) Espressif Systems (Shanghai) CO LTD
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* To use these additional DHCP options, make sure this file is included in LWIP_HOOK_FILENAME
|
||||
* and define these hooks:
|
||||
*
|
||||
* #define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) \
|
||||
* do { LWIP_UNUSED_ARG(msg); \
|
||||
* dhcp_parse_extra_opts(dhcp, state, option, len, pbuf, offset); \
|
||||
* } while(0)
|
||||
*
|
||||
* #define LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr) \
|
||||
* dhcp_append_extra_opts(netif, state, msg, options_len_ptr);
|
||||
*
|
||||
* To enable (disable) these option, please set one or both of the below macros to 1 (0)
|
||||
* #define LWIP_DHCP_ENABLE_MTU_UPDATE 1
|
||||
* #define LWIP_DHCP_ENABLE_CLIENT_ID 1
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_CONTRIB_ADDONS_DHCP_OPTS_H
|
||||
#define LWIP_HDR_CONTRIB_ADDONS_DHCP_OPTS_H
|
||||
|
||||
/* Add standard integers so the header could be included before lwip */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Forward declare lwip structs */
|
||||
struct dhcp;
|
||||
struct pbuf;
|
||||
struct dhcp;
|
||||
struct netif;
|
||||
struct dhcp_msg;
|
||||
|
||||
/* Internal hook functions */
|
||||
void dhcp_parse_extra_opts(struct dhcp *dhcp, uint8_t state, uint8_t option, uint8_t len, struct pbuf* p, uint16_t offset);
|
||||
void dhcp_append_extra_opts(struct netif *netif, uint8_t state, struct dhcp_msg *msg_out, uint16_t *options_out_len);
|
||||
|
||||
#endif /* LWIP_HDR_CONTRIB_ADDONS_DHCP_OPTS_H */
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
A simple routing table implementation for addition, deletion and lookup of IPv6 routes.
|
||||
|
||||
APIs are:
|
||||
1) s8_t ip6_add_route_entry(struct ip6_prefix *ip6_prefix,
|
||||
struct netif *netif,
|
||||
ip6_addr_t *gateway,
|
||||
s8_t *index);
|
||||
|
||||
2) err_t ip6_remove_route_entry(struct ip6_prefix *ip6_prefix);
|
||||
|
||||
3) s8_t ip6_find_route_entry(ip6_addr_t *ip6_dest_addr);
|
||||
|
||||
4) struct netif *ip6_static_route(ip6_addr_t *src, ip6_addr_t *dest);
|
||||
|
||||
5) ip6_addr_t *ip6_get_gateway(struct netif *netif, ip6_addr_t *dest);
|
||||
|
||||
6) struct ip6_route_entry *ip6_get_route_table(void);
|
||||
|
||||
For route lookup from the table, The LWIP_HOOK_IP6_ROUTE hook in ip6_route(..) of ip6.c
|
||||
could be assigned to the ip6_static_route() API of this implementation to return the
|
||||
appropriate netif.
|
||||
|
||||
-- The application can add routes using the API ip6_add_route_entry(..).
|
||||
This API adds the ip6 prefix route into the static route table while
|
||||
keeping all entries sorted in decreasing order of prefix length.
|
||||
Subsequently, a linear search down the list can be performed to retrieve a
|
||||
matching route entry for a Longest Prefix Match.
|
||||
The prefix length is expected to be at an 8-bit boundary. While this is
|
||||
a limitation, it would serve most practical purposes.
|
||||
|
||||
-- The application can remove routes using the API ip6_remove_route_entry(..).
|
||||
|
||||
-- The application can find a route entry for a specific address using the
|
||||
ip6_find_route_entry() function which returns the index of the found entry.
|
||||
This is used internally by the route lookup function ip6_static_route() API.
|
||||
|
||||
-- To fetch the gateway IPv6 address for a specific destination IPv6
|
||||
address and target netif, the application can call ip6_get_gateway(..).
|
||||
This API could be assigned to the LWIP_HOOK_ND6_GET_GW() if a gateway has
|
||||
been added as part of the ip6_add_route_entry().
|
||||
|
||||
-- To fetch a pointer to the head of the table, the application can call
|
||||
ip6_get_route_table().
|
||||
248
libs/membrane/external/lwip/contrib/addons/ipv6_static_routing/ip6_route_table.c
vendored
Normal file
248
libs/membrane/external/lwip/contrib/addons/ipv6_static_routing/ip6_route_table.c
vendored
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/**
|
||||
* @file
|
||||
* IPv6 static route table.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Pradip De <pradipd@google.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Pradip De
|
||||
* <pradipd@google.com>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ip6_route_table.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
static struct ip6_route_entry static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES];
|
||||
|
||||
/**
|
||||
* Add the ip6 prefix route and target netif into the static route table while
|
||||
* keeping all entries sorted in decreasing order of prefix length.
|
||||
* 1. Search from the last entry up to find the correct slot to insert while
|
||||
* moving entries one position down to create room.
|
||||
* 2. Insert into empty slot created.
|
||||
*
|
||||
* Subsequently, a linear search down the list can be performed to retrieve a
|
||||
* matching route entry for a Longest Prefix Match.
|
||||
*
|
||||
* @param ip6_prefix the route prefix entry to add.
|
||||
* @param netif pointer to target netif.
|
||||
* @param gateway the gateway address to use to send through. Has to be link local.
|
||||
* @param idx return value argument of index where route entry was added in table.
|
||||
* @return ERR_OK if addition was successful.
|
||||
* ERR_MEM if table is already full.
|
||||
* ERR_ARG if passed argument is bad or route already exists in table.
|
||||
*/
|
||||
err_t
|
||||
ip6_add_route_entry(const struct ip6_prefix *ip6_prefix, struct netif *netif, const ip6_addr_t *gateway, s8_t *idx)
|
||||
{
|
||||
s8_t i = -1;
|
||||
err_t retval = ERR_OK;
|
||||
|
||||
if (!ip6_prefix_valid(ip6_prefix->prefix_len) || (netif == NULL)) {
|
||||
retval = ERR_ARG;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check if an entry already exists with matching prefix; If so, replace it. */
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) {
|
||||
if ((ip6_prefix->prefix_len == static_route_table[i].prefix.prefix_len) &&
|
||||
memcmp(&ip6_prefix->addr, &static_route_table[i].prefix.addr,
|
||||
ip6_prefix->prefix_len / 8) == 0) {
|
||||
/* Prefix matches; replace the netif with the one being added. */
|
||||
goto insert;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the table is full */
|
||||
if (static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES - 1].netif != NULL) {
|
||||
retval = ERR_MEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Shift all entries down the table until slot is found */
|
||||
for (i = LWIP_IPV6_NUM_ROUTE_ENTRIES - 1;
|
||||
i > 0 && (ip6_prefix->prefix_len > static_route_table[i - 1].prefix.prefix_len); i--) {
|
||||
SMEMCPY(&static_route_table[i], &static_route_table[i - 1], sizeof(struct ip6_route_entry));
|
||||
}
|
||||
|
||||
insert:
|
||||
/* Insert into the slot selected */
|
||||
SMEMCPY(&static_route_table[i].prefix, ip6_prefix, sizeof(struct ip6_prefix));
|
||||
static_route_table[i].netif = netif;
|
||||
|
||||
/* Add gateway to route table */
|
||||
static_route_table[i].gateway = gateway;
|
||||
|
||||
if (idx != NULL) {
|
||||
*idx = i;
|
||||
}
|
||||
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the route entry from the static route table.
|
||||
*
|
||||
* @param ip6_prefix the route prefix entry to delete.
|
||||
*/
|
||||
void
|
||||
ip6_remove_route_entry(const struct ip6_prefix *ip6_prefix)
|
||||
{
|
||||
int i, pos = -1;
|
||||
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) {
|
||||
/* compare prefix to find position to delete */
|
||||
if (ip6_prefix->prefix_len == static_route_table[i].prefix.prefix_len &&
|
||||
memcmp(&ip6_prefix->addr, &static_route_table[i].prefix.addr,
|
||||
ip6_prefix->prefix_len / 8) == 0) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
/* Shift everything beyond pos one slot up */
|
||||
for (i = pos; i < LWIP_IPV6_NUM_ROUTE_ENTRIES - 1; i++) {
|
||||
SMEMCPY(&static_route_table[i], &static_route_table[i+1], sizeof(struct ip6_route_entry));
|
||||
if (static_route_table[i].netif == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Zero the remaining entries */
|
||||
for (; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) {
|
||||
ip6_addr_set_zero((&static_route_table[i].prefix.addr));
|
||||
static_route_table[i].netif = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the appropriate route entry in the static route table corresponding to the given
|
||||
* destination IPv6 address. Since the entries in the route table are kept sorted in decreasing
|
||||
* order of prefix length, a linear search down the list is performed to retrieve a matching
|
||||
* index.
|
||||
*
|
||||
* @param ip6_dest_addr the destination address to match
|
||||
* @return the idx of the found route entry; -1 if not found.
|
||||
*/
|
||||
s8_t
|
||||
ip6_find_route_entry(const ip6_addr_t *ip6_dest_addr)
|
||||
{
|
||||
s8_t i, idx = -1;
|
||||
|
||||
/* Search prefix in the sorted(decreasing order of prefix length) list */
|
||||
for(i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) {
|
||||
if (memcmp(ip6_dest_addr, &static_route_table[i].prefix.addr,
|
||||
static_route_table[i].prefix.prefix_len / 8) == 0) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IPv6 address from a routing table with
|
||||
* static IPv6 routes.
|
||||
*
|
||||
* @param src the source IPv6 address, if known
|
||||
* @param dest the destination IPv6 address for which to find the route
|
||||
* @return the netif on which to send to reach dest
|
||||
*/
|
||||
struct netif *
|
||||
ip6_static_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
||||
{
|
||||
int i;
|
||||
|
||||
LWIP_UNUSED_ARG(src);
|
||||
|
||||
/* Perform table lookup */
|
||||
i = ip6_find_route_entry(dest);
|
||||
|
||||
if (i >= 0) {
|
||||
return static_route_table[i].netif;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the gateway IP6 address for a given destination IPv6 address and target netif
|
||||
* from a routing table with static IPv6 routes.
|
||||
*
|
||||
* @param netif the netif used for sending
|
||||
* @param dest the destination IPv6 address
|
||||
* @return the ip6 address of the gateway to forward packet to
|
||||
*/
|
||||
const ip6_addr_t *
|
||||
ip6_get_gateway(struct netif *netif, const ip6_addr_t *dest)
|
||||
{
|
||||
const ip6_addr_t *ret_gw = NULL;
|
||||
const int i = ip6_find_route_entry(dest);
|
||||
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
|
||||
if (i >= 0) {
|
||||
if (static_route_table[i].gateway != NULL) {
|
||||
ret_gw = static_route_table[i].gateway;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_gw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top of the route table.
|
||||
* This should be used for debug printing only.
|
||||
*
|
||||
* @return the top of the route table.
|
||||
*/
|
||||
const struct ip6_route_entry *
|
||||
ip6_get_route_table(void)
|
||||
{
|
||||
return static_route_table;
|
||||
}
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
94
libs/membrane/external/lwip/contrib/addons/ipv6_static_routing/ip6_route_table.h
vendored
Normal file
94
libs/membrane/external/lwip/contrib/addons/ipv6_static_routing/ip6_route_table.h
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* IPv6 static route table.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Pradip De <pradipd@google.com>
|
||||
*
|
||||
*
|
||||
* Please coordinate changes and requests with Pradip De
|
||||
* <pradipd@google.com>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_IP6_ROUTE_TABLE_H__
|
||||
#define __LWIP_IP6_ROUTE_TABLE_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct netif;
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_NUM_ROUTES: Number of IPV6 routes that can be kept in the static route table.
|
||||
*/
|
||||
#ifndef LWIP_IPV6_NUM_ROUTE_ENTRIES
|
||||
#define LWIP_IPV6_NUM_ROUTE_ENTRIES (8)
|
||||
#endif
|
||||
|
||||
#define IP6_MAX_PREFIX_LEN (128)
|
||||
#define IP6_PREFIX_ALLOWED_GRANULARITY (8)
|
||||
/* Prefix length cannot be greater than 128 bits and needs to be at a byte boundary */
|
||||
#define ip6_prefix_valid(prefix_len) (((prefix_len) <= IP6_MAX_PREFIX_LEN) && \
|
||||
(((prefix_len) % IP6_PREFIX_ALLOWED_GRANULARITY) == 0))
|
||||
|
||||
struct ip6_prefix {
|
||||
ip6_addr_t addr;
|
||||
u8_t prefix_len; /* prefix length in bits at byte boundaries */
|
||||
};
|
||||
|
||||
struct ip6_route_entry {
|
||||
struct ip6_prefix prefix;
|
||||
struct netif *netif;
|
||||
const ip6_addr_t *gateway;
|
||||
};
|
||||
|
||||
err_t ip6_add_route_entry(const struct ip6_prefix *ip6_prefix, struct netif *netif,
|
||||
const ip6_addr_t *gateway, s8_t *idx);
|
||||
void ip6_remove_route_entry(const struct ip6_prefix *ip6_prefix);
|
||||
s8_t ip6_find_route_entry(const ip6_addr_t *ip6_dest_addr);
|
||||
struct netif *ip6_static_route(const ip6_addr_t *src, const ip6_addr_t *dest);
|
||||
const ip6_addr_t *ip6_get_gateway(struct netif *netif, const ip6_addr_t *dest);
|
||||
const struct ip6_route_entry *ip6_get_route_table(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* __LWIP_IP6_ROUTE_TABLE_H__ */
|
||||
164
libs/membrane/external/lwip/contrib/addons/netconn/external_resolve/dnssd.c
vendored
Normal file
164
libs/membrane/external/lwip/contrib/addons/netconn/external_resolve/dnssd.c
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* @file
|
||||
* DNS-SD APIs used by LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE
|
||||
*
|
||||
* This implementation assumes the DNS-SD API implementation (most likely provided by
|
||||
* mDNSResponder) is implemented in the same process space as LwIP and can directly
|
||||
* invoke the callback for DNSServiceGetAddrInfo. This is the typical deployment in
|
||||
* an embedded environment where as a traditional OS requires pumping the callback results
|
||||
* through an IPC mechanism (see DNSServiceRefSockFD/DNSServiceProcessResult)
|
||||
*
|
||||
* @defgroup dnssd DNS-SD
|
||||
* @ingroup dns
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Joel Cunningham, Garmin International, Inc. <joel.cunningham@garmin.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Joel Cunningham <joel.cunningham@me.com>
|
||||
*
|
||||
*/
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "dnssd.h"
|
||||
|
||||
/* External headers */
|
||||
#include <string.h>
|
||||
#include <dns_sd.h>
|
||||
|
||||
/* This timeout should allow for multiple queries.
|
||||
mDNSResponder has the following query timeline:
|
||||
Query 1: time = 0s
|
||||
Query 2: time = 1s
|
||||
Query 3: time = 4s
|
||||
*/
|
||||
#define GETADDR_TIMEOUT_MS 5000
|
||||
#define LOCAL_DOMAIN ".local"
|
||||
|
||||
/* Only consume .local hosts */
|
||||
#ifndef CONSUME_LOCAL_ONLY
|
||||
#define CONSUME_LOCAL_ONLY 1
|
||||
#endif
|
||||
|
||||
struct addr_clbk_msg {
|
||||
sys_sem_t sem;
|
||||
struct sockaddr_storage addr;
|
||||
err_t err;
|
||||
};
|
||||
|
||||
static void addr_info_callback(DNSServiceRef ref, DNSServiceFlags flags, u32_t interface_index,
|
||||
DNSServiceErrorType error_code, char const* hostname,
|
||||
const struct sockaddr* address, u32_t ttl, void* context);
|
||||
|
||||
int
|
||||
lwip_dnssd_gethostbyname(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err)
|
||||
{
|
||||
DNSServiceErrorType result;
|
||||
DNSServiceRef ref;
|
||||
struct addr_clbk_msg msg;
|
||||
char *p;
|
||||
|
||||
/* @todo: use with IPv6 */
|
||||
LWIP_UNUSED_ARG(addrtype);
|
||||
|
||||
#if CONSUME_LOCAL_ONLY
|
||||
/* check if this is a .local host. If it is, then we consume the query */
|
||||
p = strstr(name, LOCAL_DOMAIN);
|
||||
if (p == NULL) {
|
||||
return 0; /* not consumed */
|
||||
}
|
||||
p += (sizeof(LOCAL_DOMAIN) - 1);
|
||||
/* check to make sure .local isn't a substring (only allow .local\0 or .local.\0) */
|
||||
if ((*p != '.' && *p != '\0') ||
|
||||
(*p == '.' && *(p + 1) != '\0')) {
|
||||
return 0; /* not consumed */
|
||||
}
|
||||
#endif /* CONSUME_LOCAL_ONLY */
|
||||
|
||||
msg.err = sys_sem_new(&msg.sem, 0);
|
||||
if (msg.err != ERR_OK) {
|
||||
goto query_done;
|
||||
}
|
||||
|
||||
msg.err = ERR_TIMEOUT;
|
||||
result = DNSServiceGetAddrInfo(&ref, 0, 0, kDNSServiceProtocol_IPv4, name, addr_info_callback, &msg);
|
||||
if (result == kDNSServiceErr_NoError) {
|
||||
sys_arch_sem_wait(&msg.sem, GETADDR_TIMEOUT_MS);
|
||||
DNSServiceRefDeallocate(ref);
|
||||
|
||||
/* We got a response */
|
||||
if (msg.err == ERR_OK) {
|
||||
struct sockaddr_in* addr_in = (struct sockaddr_in *)&msg.addr;
|
||||
if (addr_in->sin_family == AF_INET) {
|
||||
inet_addr_to_ip4addr(ip_2_ip4(addr), &addr_in->sin_addr);
|
||||
} else {
|
||||
/* @todo add IPv6 support */
|
||||
msg.err = ERR_VAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
sys_sem_free(&msg.sem);
|
||||
|
||||
/* Query has been consumed and is finished */
|
||||
query_done:
|
||||
*err = msg.err;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
addr_info_callback(DNSServiceRef ref, DNSServiceFlags flags, u32_t interface_index,
|
||||
DNSServiceErrorType error_code, char const* hostname,
|
||||
const struct sockaddr* address, u32_t ttl, void* context)
|
||||
{
|
||||
struct addr_clbk_msg* msg = (struct addr_clbk_msg*)context;
|
||||
struct sockaddr_in* addr_in = (struct sockaddr_in *)address;
|
||||
|
||||
LWIP_UNUSED_ARG(ref);
|
||||
LWIP_UNUSED_ARG(flags);
|
||||
LWIP_UNUSED_ARG(interface_index);
|
||||
LWIP_UNUSED_ARG(hostname);
|
||||
LWIP_UNUSED_ARG(ttl);
|
||||
LWIP_UNUSED_ARG(context);
|
||||
|
||||
if ((error_code == kDNSServiceErr_NoError) &&
|
||||
(addr_in->sin_family == AF_INET)) {
|
||||
MEMCPY(&msg->addr, addr_in, sizeof(*addr_in));
|
||||
msg->err = ERR_OK;
|
||||
}
|
||||
else {
|
||||
/* @todo add IPv6 support */
|
||||
msg->err = ERR_VAL;
|
||||
}
|
||||
|
||||
sys_sem_signal(&msg->sem);
|
||||
} /* addr_info_callback() */
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* @file
|
||||
* DNS-SD APIs used by LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE
|
||||
*
|
||||
* @defgroup dnssd DNS-SD
|
||||
* @ingroup dns
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Joel Cunningham, Garmin International, Inc. <joel.cunningham@garmin.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Joel Cunningham <joel.cunningham@me.com>
|
||||
*
|
||||
*/
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifndef LWIP_HDR_DNSSD_H
|
||||
#define LWIP_HDR_DNSSD_H
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
int lwip_dnssd_gethostbyname(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err);
|
||||
|
||||
#endif /* LWIP_HDR_DNSSD_H */
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* Reference implementation of the TCP ISN algorithm standardized in RFC 6528.
|
||||
* Produce TCP Initial Sequence Numbers by combining an MD5-generated hash
|
||||
* based on the new TCP connection's identity and a stable secret, with the
|
||||
* current time at 4-microsecond granularity.
|
||||
*
|
||||
* Specifically, the implementation uses MD5 to compute a hash of the input
|
||||
* buffer, which contains both the four-tuple of the new TCP connection (local
|
||||
* and remote IP address and port), as well as a 16-byte secret to make the
|
||||
* results unpredictable to external parties. The secret must be given at
|
||||
* initialization time and should ideally remain the same across system
|
||||
* reboots. To be sure: the spoofing-resistance of the resulting ISN depends
|
||||
* mainly on the strength of the supplied secret!
|
||||
*
|
||||
* The implementation takes 32 bits from the computed hash, and adds to it the
|
||||
* current time, in 4-microsecond units. The current time is computed from a
|
||||
* boot time given at initialization, and the current uptime as provided by
|
||||
* sys_now(). Thus, it assumes that sys_now() returns a time value that is
|
||||
* relative to the boot time, i.e., that it starts at 0 at system boot, and
|
||||
* only ever increases monotonically.
|
||||
*
|
||||
* For efficiency reasons, a single MD5 input buffer is used, and partially
|
||||
* filled in at initialization time. Specifically, of this 64-byte buffer, the
|
||||
* first 36 bytes are used for the four-way TCP tuple data, followed by the
|
||||
* 16-byte secret, followed by 12-byte zero padding. The 64-byte size of the
|
||||
* buffer should achieve the best performance for the actual MD5 computation.
|
||||
*
|
||||
* Basic usage:
|
||||
*
|
||||
* 1. in your lwipopts.h, add the following lines:
|
||||
*
|
||||
* #include <lwip/arch.h>
|
||||
* struct ip_addr;
|
||||
* u32_t lwip_hook_tcp_isn(const struct ip_addr *local_ip, u16_t local_port,
|
||||
* const struct ip_addr *remote_ip, u16_t remote_port);
|
||||
* "#define LWIP_HOOK_TCP_ISN lwip_hook_tcp_isn";
|
||||
*
|
||||
* 2. from your own code, call lwip_init_tcp_isn() at initialization time, with
|
||||
* appropriate parameters.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 The MINIX 3 Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: David van Moolenbroek <david@minix3.org>
|
||||
*/
|
||||
|
||||
#include "tcp_isn.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef LWIP_HOOK_TCP_ISN
|
||||
|
||||
/* pull in md5 of ppp? */
|
||||
#include "netif/ppp/ppp_opts.h"
|
||||
#if !PPP_SUPPORT || (!LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS)
|
||||
#undef LWIP_INCLUDED_POLARSSL_MD5
|
||||
#define LWIP_INCLUDED_POLARSSL_MD5 1
|
||||
#include "netif/ppp/polarssl/md5.h"
|
||||
#endif
|
||||
|
||||
static u8_t input[64];
|
||||
static u32_t base_time;
|
||||
|
||||
/**
|
||||
* Initialize the TCP ISN module, with the boot time and a secret.
|
||||
*
|
||||
* @param boot_time Wall clock boot time of the system, in seconds.
|
||||
* @param secret_16_bytes A 16-byte secret used to randomize the TCP ISNs.
|
||||
*/
|
||||
void
|
||||
lwip_init_tcp_isn(u32_t boot_time, const u8_t *secret_16_bytes)
|
||||
{
|
||||
/* Initialize the input buffer with the secret and trailing zeroes. */
|
||||
memset(input, 0, sizeof(input));
|
||||
|
||||
MEMCPY(&input[36], secret_16_bytes, 16);
|
||||
|
||||
/* Save the boot time in 4-us units. Overflow is no problem here. */
|
||||
base_time = boot_time * 250000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to generate an Initial Sequence Number (ISN) for a new TCP connection.
|
||||
*
|
||||
* @param local_ip The local IP address.
|
||||
* @param local_port The local port number, in host-byte order.
|
||||
* @param remote_ip The remote IP address.
|
||||
* @param remote_port The remote port number, in host-byte order.
|
||||
* @return The ISN to use for the new TCP connection.
|
||||
*/
|
||||
u32_t
|
||||
lwip_hook_tcp_isn(const ip_addr_t *local_ip, u16_t local_port,
|
||||
const ip_addr_t *remote_ip, u16_t remote_port)
|
||||
{
|
||||
md5_context ctx;
|
||||
u8_t output[16];
|
||||
u32_t isn;
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
if (IP_IS_V6(local_ip))
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
#if LWIP_IPV6
|
||||
{
|
||||
const ip6_addr_t *local_ip6, *remote_ip6;
|
||||
|
||||
local_ip6 = ip_2_ip6(local_ip);
|
||||
remote_ip6 = ip_2_ip6(remote_ip);
|
||||
|
||||
SMEMCPY(&input[0], &local_ip6->addr, 16);
|
||||
SMEMCPY(&input[16], &remote_ip6->addr, 16);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
else
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
#if LWIP_IPV4
|
||||
{
|
||||
const ip4_addr_t *local_ip4, *remote_ip4;
|
||||
|
||||
local_ip4 = ip_2_ip4(local_ip);
|
||||
remote_ip4 = ip_2_ip4(remote_ip);
|
||||
|
||||
/* Represent IPv4 addresses as IPv4-mapped IPv6 addresses, to ensure that
|
||||
* the IPv4 and IPv6 address spaces are completely disjoint. */
|
||||
memset(&input[0], 0, 10);
|
||||
input[10] = 0xff;
|
||||
input[11] = 0xff;
|
||||
SMEMCPY(&input[12], &local_ip4->addr, 4);
|
||||
memset(&input[16], 0, 10);
|
||||
input[26] = 0xff;
|
||||
input[27] = 0xff;
|
||||
SMEMCPY(&input[28], &remote_ip4->addr, 4);
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
input[32] = (u8_t)(local_port >> 8);
|
||||
input[33] = (u8_t)(local_port & 0xff);
|
||||
input[34] = (u8_t)(remote_port >> 8);
|
||||
input[35] = (u8_t)(remote_port & 0xff);
|
||||
|
||||
/* The secret and padding are already filled in. */
|
||||
|
||||
/* Generate the hash, using MD5. */
|
||||
md5_starts(&ctx);
|
||||
md5_update(&ctx, input, sizeof(input));
|
||||
md5_finish(&ctx, output);
|
||||
|
||||
/* Arbitrarily take the first 32 bits from the generated hash. */
|
||||
MEMCPY(&isn, output, sizeof(isn));
|
||||
|
||||
/* Add the current time in 4-microsecond units. */
|
||||
return isn + base_time + sys_now() * 250;
|
||||
}
|
||||
|
||||
#endif /* LWIP_HOOK_TCP_ISN */
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016 The MINIX 3 Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: David van Moolenbroek <david@minix3.org>
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_CONTRIB_ADDONS_TCP_ISN_H
|
||||
#define LWIP_HDR_CONTRIB_ADDONS_TCP_ISN_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void lwip_init_tcp_isn(u32_t boot_time, const u8_t *secret_16_bytes);
|
||||
u32_t lwip_hook_tcp_isn(const ip_addr_t *local_ip, u16_t local_port,
|
||||
const ip_addr_t *remote_ip, u16_t remote_port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_CONTRIB_ADDONS_TCP_ISN_H */
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
This folder provides an example implementation of how to add custom tcp header
|
||||
options and custom socket options.
|
||||
|
||||
It does this by implementing the (seldom used) tcp md5 signature.
|
||||
|
||||
To enable it, add an LWIP_HOOK_FILENAME hook file, include tcp_md5.h in it and
|
||||
define these hooks:
|
||||
|
||||
#define LWIP_HOOK_TCP_INPACKET_PCB(pcb, hdr, optlen, opt1len, opt2, p) tcp_md5_check_inpacket(pcb, hdr, optlen, opt1len, opt2, p)
|
||||
#define LWIP_HOOK_TCP_OPT_LENGTH_SEGMENT(pcb, internal_len) tcp_md5_get_additional_option_length(pcb, internal_len)
|
||||
#define LWIP_HOOK_TCP_ADD_TX_OPTIONS(p, hdr, pcb, opts) tcp_md5_add_tx_options(p, hdr, pcb, opts)
|
||||
#define LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err) tcp_md5_setsockopt_hook(sock, level, optname, optval, optlen, err)
|
||||
|
||||
Then, in your sockets application, enable md5 signature on a socket like this:
|
||||
|
||||
struct tcp_md5sig md5;
|
||||
struct sockaddr_storage addr_remote; /* Initialize this to remote address and port */
|
||||
memcpy(&md5.tcpm_addr, &addr_remote, sizeof(addr_remote));
|
||||
strcpy(md5.tcpm_key, key); /* this is the md5 key per connection */
|
||||
md5.tcpm_keylen = strlen(key);
|
||||
if ((ret = setsockopt(sockfd, IPPROTO_TCP, TCP_MD5SIG, &md5, sizeof(md5))) < 0) {
|
||||
perror("setsockopt TCP_MD5SIG");
|
||||
return;
|
||||
}
|
||||
|
||||
After that, your connection (client) or all incoming connections (server) require
|
||||
tcp md5 signatures.
|
||||
|
|
@ -0,0 +1,534 @@
|
|||
/**
|
||||
* @file: An implementation of TCP MD5 signatures by using various hooks in
|
||||
* lwIP to implement custom tcp options and custom socket options.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 Simon Goldschmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Simon Goldschmidt <goldsimon@gmx.de>
|
||||
*/
|
||||
|
||||
#include "tcp_md5.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/prot/tcp.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/priv/sockets_priv.h"
|
||||
#include "lwip/api.h"
|
||||
#include <string.h>
|
||||
|
||||
/* pull in md5 of ppp? */
|
||||
#include "netif/ppp/ppp_opts.h"
|
||||
#if !PPP_SUPPORT || (!LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS)
|
||||
#undef LWIP_INCLUDED_POLARSSL_MD5
|
||||
#define LWIP_INCLUDED_POLARSSL_MD5 1
|
||||
#include "netif/ppp/polarssl/md5.h"
|
||||
#endif
|
||||
|
||||
#if !LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||
#error tcp_md5 needs LWIP_TCP_PCB_NUM_EXT_ARGS
|
||||
#endif
|
||||
|
||||
#define LWIP_TCP_OPT_MD5 19 /* number of the md5 option */
|
||||
#define LWIP_TCP_OPT_LEN_MD5 18 /* length of the md5 option */
|
||||
#define LWIP_TCP_OPT_LEN_MD5_OUT 20 /* 18 + alignment */
|
||||
|
||||
#define LWIP_TCP_MD5_DIGEST_LEN 16
|
||||
|
||||
/* This keeps the md5 state internally */
|
||||
struct tcp_md5_conn_info {
|
||||
struct tcp_md5_conn_info *next;
|
||||
ip_addr_t remote_addr;
|
||||
u16_t remote_port;
|
||||
u8_t key[TCP_MD5SIG_MAXKEYLEN];
|
||||
u16_t key_len;
|
||||
};
|
||||
|
||||
/* Callback function prototypes: */
|
||||
static void tcp_md5_extarg_destroy(u8_t id, void *data);
|
||||
static err_t tcp_md5_extarg_passive_open(u8_t id, struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
|
||||
/* Define our tcp ext arg callback structure: */
|
||||
const struct tcp_ext_arg_callbacks tcp_md5_ext_arg_callbacks = {
|
||||
tcp_md5_extarg_destroy,
|
||||
tcp_md5_extarg_passive_open
|
||||
};
|
||||
|
||||
static u8_t tcp_md5_extarg_id = LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID;
|
||||
static u8_t tcp_md5_opts_buf[40];
|
||||
|
||||
/** Initialize this module (allocates a tcp ext arg id) */
|
||||
void
|
||||
tcp_md5_init(void)
|
||||
{
|
||||
tcp_md5_extarg_id = tcp_ext_arg_alloc_id();
|
||||
}
|
||||
|
||||
/* Create a conn-info structure that holds the md5 state per connection */
|
||||
static struct tcp_md5_conn_info *
|
||||
tcp_md5_conn_info_alloc(void)
|
||||
{
|
||||
return (struct tcp_md5_conn_info *)mem_malloc(sizeof(struct tcp_md5_conn_info));
|
||||
}
|
||||
|
||||
/* Frees a conn-info structure that holds the md5 state per connection */
|
||||
static void
|
||||
tcp_md5_conn_info_free(struct tcp_md5_conn_info *info)
|
||||
{
|
||||
mem_free(info);
|
||||
}
|
||||
|
||||
/* A pcb is about to be destroyed. Free its extdata */
|
||||
static void
|
||||
tcp_md5_extarg_destroy(u8_t id, void *data)
|
||||
{
|
||||
struct tcp_md5_conn_info *iter;
|
||||
|
||||
LWIP_ASSERT("tcp_md5_extarg_id != LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID",
|
||||
tcp_md5_extarg_id != LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID);
|
||||
LWIP_ASSERT("id == tcp_md5_extarg_id", id == tcp_md5_extarg_id);
|
||||
LWIP_UNUSED_ARG(id);
|
||||
|
||||
iter = (struct tcp_md5_conn_info *)data;
|
||||
while (iter != NULL) {
|
||||
struct tcp_md5_conn_info *info = iter;
|
||||
iter = iter->next;
|
||||
tcp_md5_conn_info_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find an md5 connection info for the specified remote connection */
|
||||
static struct tcp_md5_conn_info *
|
||||
tcp_md5_get_info(const struct tcp_pcb *pcb, const ip_addr_t *remote_ip, u16_t remote_port)
|
||||
{
|
||||
if (pcb != NULL) {
|
||||
struct tcp_md5_conn_info *info = (struct tcp_md5_conn_info *)tcp_ext_arg_get(pcb, tcp_md5_extarg_id);
|
||||
while (info != NULL) {
|
||||
if (ip_addr_eq(&info->remote_addr, remote_ip)) {
|
||||
if (info->remote_port == remote_port) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
info = info->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Passive open: copy md5 connection info from listen pcb to connection pcb
|
||||
* or return error (connection will be closed)
|
||||
*/
|
||||
static err_t
|
||||
tcp_md5_extarg_passive_open(u8_t id, struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb)
|
||||
{
|
||||
struct tcp_md5_conn_info *iter;
|
||||
|
||||
LWIP_ASSERT("lpcb != NULL", lpcb != NULL);
|
||||
LWIP_ASSERT("cpcb != NULL", cpcb != NULL);
|
||||
LWIP_ASSERT("tcp_md5_extarg_id != LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID",
|
||||
tcp_md5_extarg_id != LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID);
|
||||
LWIP_ASSERT("id == tcp_md5_extarg_id", id == tcp_md5_extarg_id);
|
||||
LWIP_UNUSED_ARG(id);
|
||||
|
||||
iter = (struct tcp_md5_conn_info *)tcp_ext_arg_get((struct tcp_pcb *)lpcb, id);
|
||||
while (iter != NULL) {
|
||||
if (iter->remote_port == cpcb->remote_port) {
|
||||
if (ip_addr_eq(&iter->remote_addr, &cpcb->remote_ip)) {
|
||||
struct tcp_md5_conn_info *info = tcp_md5_conn_info_alloc();
|
||||
if (info != NULL) {
|
||||
memcpy(info, iter, sizeof(struct tcp_md5_conn_info));
|
||||
tcp_ext_arg_set(cpcb, id, info);
|
||||
tcp_ext_arg_set_callbacks(cpcb, id, &tcp_md5_ext_arg_callbacks);
|
||||
return ERR_OK;
|
||||
} else {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
/* remote connection not found */
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
/* Parse tcp header options and return 1 if an md5 signature option was found */
|
||||
static int
|
||||
tcp_md5_parseopt(const u8_t *opts, u16_t optlen, u8_t *md5_digest_out)
|
||||
{
|
||||
u8_t data;
|
||||
u16_t optidx;
|
||||
|
||||
/* Parse the TCP MSS option, if present. */
|
||||
if (optlen != 0) {
|
||||
for (optidx = 0; optidx < optlen; ) {
|
||||
u8_t opt = opts[optidx++];
|
||||
switch (opt) {
|
||||
case LWIP_TCP_OPT_EOL:
|
||||
/* End of options. */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
|
||||
return 0;
|
||||
case LWIP_TCP_OPT_NOP:
|
||||
/* NOP option. */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
|
||||
break;
|
||||
case LWIP_TCP_OPT_MD5:
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MD5\n"));
|
||||
if (opts[optidx++] != LWIP_TCP_OPT_LEN_MD5 || (optidx - 2 + LWIP_TCP_OPT_LEN_MD5) > optlen) {
|
||||
/* Bad length */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
return 0;
|
||||
}
|
||||
/* An MD5 option with the right option length. */
|
||||
memcpy(md5_digest_out, &opts[optidx], LWIP_TCP_MD5_DIGEST_LEN);
|
||||
/* no need to process the options further */
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
|
||||
data = opts[optidx++];
|
||||
if (data < 2) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
/* If the length field is zero, the options are malformed
|
||||
and we don't process them further. */
|
||||
return 0;
|
||||
}
|
||||
/* All other options have a length field, so that we easily
|
||||
can skip past them. */
|
||||
optidx += data - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get tcp options into contiguous memory. May be required if input pbufs
|
||||
* are chained.
|
||||
*/
|
||||
static const u8_t*
|
||||
tcp_md5_options_singlebuf(struct tcp_hdr *hdr, u16_t optlen, u16_t opt1len, u8_t *opt2)
|
||||
{
|
||||
const u8_t *opts;
|
||||
LWIP_ASSERT("hdr != NULL", hdr != NULL);
|
||||
LWIP_ASSERT("optlen >= opt1len", optlen >= opt1len);
|
||||
opts = (const u8_t *)hdr + TCP_HLEN;
|
||||
if (optlen == opt1len) {
|
||||
/* arleady in one piece */
|
||||
return opts;
|
||||
}
|
||||
if (optlen > sizeof(tcp_md5_opts_buf)) {
|
||||
/* options too long */
|
||||
return NULL;
|
||||
}
|
||||
LWIP_ASSERT("opt2 != NULL", opt2 != NULL);
|
||||
/* copy first part */
|
||||
memcpy(tcp_md5_opts_buf, opts, opt1len);
|
||||
/* copy second part */
|
||||
memcpy(&tcp_md5_opts_buf[opt1len], opt2, optlen - opt1len);
|
||||
return tcp_md5_opts_buf;
|
||||
}
|
||||
|
||||
/* Create the md5 digest for a given segment */
|
||||
static int
|
||||
tcp_md5_create_digest(const ip_addr_t *ip_src, const ip_addr_t *ip_dst, const struct tcp_hdr *hdr,
|
||||
const u8_t *key, size_t key_len, u8_t *digest_out, struct pbuf *p)
|
||||
{
|
||||
md5_context ctx;
|
||||
u8_t tmp8;
|
||||
u16_t tmp16;
|
||||
const size_t addr_len = IP_ADDR_RAW_SIZE(*ip_src);
|
||||
|
||||
if (p != NULL) {
|
||||
LWIP_ASSERT("pbuf must not point to tcp header here!", (const void *)hdr != p->payload);
|
||||
}
|
||||
|
||||
/* Generate the hash, using MD5. */
|
||||
md5_starts(&ctx);
|
||||
/* 1. the TCP pseudo-header (in the order: source IP address,
|
||||
destination IP address, zero-padded protocol number, and
|
||||
segment length) */
|
||||
md5_update(&ctx, (const unsigned char*)ip_src, addr_len);
|
||||
md5_update(&ctx, (const unsigned char*)ip_dst, addr_len);
|
||||
tmp8 = 0; /* zero-padded */
|
||||
md5_update(&ctx, &tmp8, 1);
|
||||
tmp8 = IP_PROTO_TCP;
|
||||
md5_update(&ctx, &tmp8, 1);
|
||||
tmp16 = lwip_htons(TCPH_HDRLEN_BYTES(hdr) + (p ? p->tot_len : 0));
|
||||
md5_update(&ctx, (const unsigned char*)&tmp16, 2);
|
||||
/* 2. the TCP header, excluding options, and assuming a checksum of
|
||||
zero */
|
||||
md5_update(&ctx, (const unsigned char*)hdr, sizeof(struct tcp_hdr));
|
||||
/* 3. the TCP segment data (if any) */
|
||||
if ((p != NULL) && (p->tot_len != 0)) {
|
||||
struct pbuf *q;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
md5_update(&ctx, (const unsigned char*)q->payload, q->len);
|
||||
}
|
||||
}
|
||||
/* 4. an independently-specified key or password, known to both TCPs
|
||||
and presumably connection-specific */
|
||||
md5_update(&ctx, key, key_len);
|
||||
|
||||
md5_finish(&ctx, digest_out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Duplicate a tcp header and make sure the fields are in network byte order */
|
||||
static void
|
||||
tcp_md5_dup_tcphdr(struct tcp_hdr *tcphdr_copy, const struct tcp_hdr *tcphdr_in, int tcphdr_in_is_host_order)
|
||||
{
|
||||
memcpy(tcphdr_copy, tcphdr_in, sizeof(struct tcp_hdr));
|
||||
tcphdr_copy->chksum = 0; /* checksum is zero for the pseudo header */
|
||||
if (tcphdr_in_is_host_order) {
|
||||
/* lwIP writes the TCP header values back to the buffer, we need to invert that here: */
|
||||
tcphdr_copy->src = lwip_htons(tcphdr_copy->src);
|
||||
tcphdr_copy->dest = lwip_htons(tcphdr_copy->dest);
|
||||
tcphdr_copy->seqno = lwip_htonl(tcphdr_copy->seqno);
|
||||
tcphdr_copy->ackno = lwip_htonl(tcphdr_copy->ackno);
|
||||
tcphdr_copy->wnd = lwip_htons(tcphdr_copy->wnd);
|
||||
tcphdr_copy->urgp = lwip_htons(tcphdr_copy->urgp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if md5 is enabled on a given pcb */
|
||||
static int
|
||||
tcp_md5_is_enabled_on_pcb(const struct tcp_pcb *pcb)
|
||||
{
|
||||
if (tcp_md5_extarg_id != LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID) {
|
||||
struct tcp_md5_conn_info *info = (struct tcp_md5_conn_info *)tcp_ext_arg_get(pcb, tcp_md5_extarg_id);
|
||||
if (info != NULL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if md5 is enabled on a given listen pcb */
|
||||
static int
|
||||
tcp_md5_is_enabled_on_lpcb(const struct tcp_pcb_listen *lpcb)
|
||||
{
|
||||
/* same as for connection pcbs */
|
||||
return tcp_md5_is_enabled_on_pcb((const struct tcp_pcb *)lpcb);
|
||||
}
|
||||
|
||||
/* Hook implementation for LWIP_HOOK_TCP_OPT_LENGTH_SEGMENT */
|
||||
u8_t
|
||||
tcp_md5_get_additional_option_length(const struct tcp_pcb *pcb, u8_t internal_option_length)
|
||||
{
|
||||
if ((pcb != NULL) && tcp_md5_is_enabled_on_pcb(pcb)) {
|
||||
u8_t new_option_length = internal_option_length + LWIP_TCP_OPT_LEN_MD5_OUT;
|
||||
LWIP_ASSERT("overflow", new_option_length > internal_option_length);
|
||||
LWIP_ASSERT("options too long", new_option_length <= TCP_MAX_OPTION_BYTES);
|
||||
return new_option_length;
|
||||
}
|
||||
return internal_option_length;
|
||||
}
|
||||
|
||||
/* Hook implementation for LWIP_HOOK_TCP_INPACKET_PCB when called for listen pcbs */
|
||||
static err_t
|
||||
tcp_md5_check_listen(struct tcp_pcb_listen* lpcb, struct tcp_hdr *hdr, u16_t optlen, u16_t opt1len, u8_t *opt2)
|
||||
{
|
||||
LWIP_ASSERT("lpcb != NULL", lpcb != NULL);
|
||||
|
||||
if (tcp_md5_is_enabled_on_lpcb(lpcb)) {
|
||||
const u8_t *opts;
|
||||
u8_t digest_received[LWIP_TCP_MD5_DIGEST_LEN];
|
||||
u8_t digest_calculated[LWIP_TCP_MD5_DIGEST_LEN];
|
||||
const struct tcp_md5_conn_info *info = tcp_md5_get_info((struct tcp_pcb *)lpcb, ip_current_src_addr(), hdr->src);
|
||||
if (info != NULL) {
|
||||
opts = tcp_md5_options_singlebuf(hdr, optlen, opt1len, opt2);
|
||||
if (opts != NULL) {
|
||||
if (tcp_md5_parseopt(opts, optlen, digest_received)) {
|
||||
struct tcp_hdr tcphdr_copy;
|
||||
tcp_md5_dup_tcphdr(&tcphdr_copy, hdr, 1);
|
||||
if (tcp_md5_create_digest(ip_current_src_addr(), ip_current_dest_addr(), &tcphdr_copy, info->key, info->key_len, digest_calculated, NULL)) {
|
||||
/* everything set up, compare the digests */
|
||||
if (!memcmp(digest_received, digest_calculated, LWIP_TCP_MD5_DIGEST_LEN)) {
|
||||
/* equal */
|
||||
return ERR_OK;
|
||||
}
|
||||
/* not equal */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* md5 enabled on this pcb but no match or other error -> fail */
|
||||
return ERR_VAL;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Hook implementation for LWIP_HOOK_TCP_INPACKET_PCB */
|
||||
err_t
|
||||
tcp_md5_check_inpacket(struct tcp_pcb* pcb, struct tcp_hdr *hdr, u16_t optlen, u16_t opt1len, u8_t *opt2, struct pbuf *p)
|
||||
{
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
|
||||
if (pcb->state == LISTEN) {
|
||||
return tcp_md5_check_listen((struct tcp_pcb_listen *)pcb, hdr, optlen, opt1len, opt2);
|
||||
}
|
||||
|
||||
if (tcp_md5_is_enabled_on_pcb(pcb)) {
|
||||
const struct tcp_md5_conn_info *info = tcp_md5_get_info(pcb, ip_current_src_addr(), hdr->src);
|
||||
if (info != NULL) {
|
||||
const u8_t *opts;
|
||||
u8_t digest_received[LWIP_TCP_MD5_DIGEST_LEN];
|
||||
u8_t digest_calculated[LWIP_TCP_MD5_DIGEST_LEN];
|
||||
opts = tcp_md5_options_singlebuf(hdr, optlen, opt1len, opt2);
|
||||
if (opts != NULL) {
|
||||
if (tcp_md5_parseopt(opts, optlen, digest_received)) {
|
||||
struct tcp_hdr hdr_copy;
|
||||
tcp_md5_dup_tcphdr(&hdr_copy, hdr, 1);
|
||||
if (tcp_md5_create_digest(&pcb->remote_ip, &pcb->local_ip, &hdr_copy, info->key, info->key_len, digest_calculated, p)) {
|
||||
/* everything set up, compare the digests */
|
||||
if (!memcmp(digest_received, digest_calculated, LWIP_TCP_MD5_DIGEST_LEN)) {
|
||||
/* equal */
|
||||
return ERR_OK;
|
||||
}
|
||||
/* not equal */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* md5 enabled on this pcb but no match or other error -> fail */
|
||||
return ERR_VAL;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Hook implementation for LWIP_HOOK_TCP_ADD_TX_OPTIONS */
|
||||
u32_t *
|
||||
tcp_md5_add_tx_options(struct pbuf *p, struct tcp_hdr *hdr, const struct tcp_pcb *pcb, u32_t *opts)
|
||||
{
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
LWIP_ASSERT("hdr != NULL", hdr != NULL);
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
LWIP_ASSERT("opts != NULL", opts != NULL);
|
||||
|
||||
if (tcp_md5_is_enabled_on_pcb(pcb)) {
|
||||
u8_t digest_calculated[LWIP_TCP_MD5_DIGEST_LEN];
|
||||
u32_t *opts_ret = opts + 5; /* we use 20 bytes: 2 bytes padding + 18 bytes for this option */
|
||||
u8_t *ptr = (u8_t*)opts;
|
||||
|
||||
const struct tcp_md5_conn_info *info = tcp_md5_get_info(pcb, &pcb->remote_ip, pcb->remote_port);
|
||||
if (info != NULL) {
|
||||
struct tcp_hdr hdr_copy;
|
||||
size_t hdrsize = TCPH_HDRLEN_BYTES(hdr);
|
||||
tcp_md5_dup_tcphdr(&hdr_copy, hdr, 0);
|
||||
/* p->payload points to the tcp header */
|
||||
LWIP_ASSERT("p->payload == hdr", p->payload == hdr);
|
||||
if (!pbuf_remove_header(p, hdrsize)) {
|
||||
u8_t ret;
|
||||
if (!tcp_md5_create_digest(&pcb->local_ip, &pcb->remote_ip, &hdr_copy, info->key, info->key_len, digest_calculated, p)) {
|
||||
info = NULL;
|
||||
}
|
||||
ret = pbuf_add_header_force(p, hdrsize);
|
||||
LWIP_ASSERT("tcp_md5_add_tx_options: pbuf_add_header_force failed", !ret);
|
||||
LWIP_UNUSED_ARG(ret);
|
||||
} else {
|
||||
LWIP_ASSERT("error", 0);
|
||||
}
|
||||
}
|
||||
if (info == NULL) {
|
||||
/* create an invalid signature by zeroing the digest */
|
||||
memset(&digest_calculated, 0, sizeof(digest_calculated));
|
||||
}
|
||||
|
||||
*ptr++ = LWIP_TCP_OPT_NOP;
|
||||
*ptr++ = LWIP_TCP_OPT_NOP;
|
||||
*ptr++ = LWIP_TCP_OPT_MD5;
|
||||
*ptr++ = LWIP_TCP_OPT_LEN_MD5;
|
||||
memcpy(ptr, digest_calculated, LWIP_TCP_MD5_DIGEST_LEN);
|
||||
ptr += LWIP_TCP_MD5_DIGEST_LEN;
|
||||
LWIP_ASSERT("ptr == opts_ret", ptr == (u8_t *)opts_ret);
|
||||
return opts_ret;
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
/* Hook implementation for LWIP_HOOK_SOCKETS_SETSOCKOPT */
|
||||
int
|
||||
tcp_md5_setsockopt_hook(struct lwip_sock *sock, int level, int optname, const void *optval, socklen_t optlen, int *err)
|
||||
{
|
||||
LWIP_ASSERT("sock != NULL", sock != NULL);
|
||||
LWIP_ASSERT("err != NULL", err != NULL);
|
||||
|
||||
if ((level == IPPROTO_TCP) && (optname == TCP_MD5SIG)) {
|
||||
const struct tcp_md5sig *md5 = (const struct tcp_md5sig*)optval;
|
||||
if ((optval == NULL) || (optlen < sizeof(struct tcp_md5sig))) {
|
||||
*err = EINVAL;
|
||||
} else {
|
||||
if (sock->conn && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (sock->conn->pcb.tcp != NULL)) {
|
||||
if (tcp_md5_extarg_id == LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID) {
|
||||
/* not initialized */
|
||||
*err = EINVAL;
|
||||
} else {
|
||||
struct tcp_md5_conn_info *info = tcp_md5_conn_info_alloc();
|
||||
if (info == NULL) {
|
||||
*err = ENOMEM;
|
||||
} else {
|
||||
int addr_valid = 0;
|
||||
/* OK, fill and link this request */
|
||||
memcpy(info->key, md5->tcpm_key, TCP_MD5SIG_MAXKEYLEN);
|
||||
info->key_len = md5->tcpm_keylen;
|
||||
memset(&info->remote_addr, 0, sizeof(info->remote_addr));
|
||||
if (md5->tcpm_addr.ss_family == AF_INET) {
|
||||
#if LWIP_IPV4
|
||||
const struct sockaddr_in *sin = (const struct sockaddr_in *)&md5->tcpm_addr;
|
||||
memcpy(&info->remote_addr, &sin->sin_addr, sizeof(sin->sin_addr));
|
||||
IP_SET_TYPE_VAL(info->remote_addr, IPADDR_TYPE_V4);
|
||||
info->remote_port = lwip_htons(sin->sin_port);
|
||||
addr_valid = 1;
|
||||
#endif /* LWIP_IPV4 */
|
||||
} else if (md5->tcpm_addr.ss_family == AF_INET6) {
|
||||
#if LWIP_IPV6
|
||||
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)&md5->tcpm_addr;
|
||||
memcpy(&info->remote_addr, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
|
||||
IP_SET_TYPE_VAL(info->remote_addr, IPADDR_TYPE_V6);
|
||||
info->remote_port = lwip_htons(sin6->sin6_port);
|
||||
addr_valid = 1;
|
||||
#endif /* LWIP_IPV6 */
|
||||
}
|
||||
if (addr_valid) {
|
||||
/* store it */
|
||||
tcp_ext_arg_set_callbacks(sock->conn->pcb.tcp, tcp_md5_extarg_id, &tcp_md5_ext_arg_callbacks);
|
||||
info->next = (struct tcp_md5_conn_info *)tcp_ext_arg_get(sock->conn->pcb.tcp, tcp_md5_extarg_id);
|
||||
tcp_ext_arg_set(sock->conn->pcb.tcp, tcp_md5_extarg_id, info);
|
||||
} else {
|
||||
*err = EINVAL;
|
||||
tcp_md5_conn_info_free(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* not a tcp netconn */
|
||||
*err = EINVAL;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Simon Goldschmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Simon Goldschmidt <goldsimon@gmx.de>
|
||||
*
|
||||
* To use the hooks in this file, make sure this file is included in LWIP_HOOK_FILENAME
|
||||
* and define these hooks:
|
||||
*
|
||||
* #define LWIP_HOOK_TCP_INPACKET_PCB(pcb, hdr, optlen, opt1len, opt2, p) tcp_md5_check_inpacket(pcb, hdr, optlen, opt1len, opt2, p)
|
||||
* #define LWIP_HOOK_TCP_OPT_LENGTH_SEGMENT(pcb, internal_len) tcp_md5_get_additional_option_length(pcb, internal_len)
|
||||
* #define LWIP_HOOK_TCP_ADD_TX_OPTIONS(p, hdr, pcb, opts) tcp_md5_add_tx_options(p, hdr, pcb, opts)
|
||||
*
|
||||
* #define LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err) tcp_md5_setsockopt_hook(sock, level, optname, optval, optlen, err)
|
||||
*/
|
||||
|
||||
#ifndef LWIP_HDR_CONTRIB_ADDONS_TCP_MD5_H
|
||||
#define LWIP_HDR_CONTRIB_ADDONS_TCP_MD5_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include "lwip/priv/sockets_priv.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* setsockopt definitions and structs: */
|
||||
|
||||
/* This is the optname (for level = IPPROTO_TCP) */
|
||||
#ifndef TCP_MD5SIG
|
||||
#define TCP_MD5SIG 14
|
||||
#endif
|
||||
|
||||
#define TCP_MD5SIG_MAXKEYLEN 80
|
||||
|
||||
/* This is the optval type */
|
||||
struct tcp_md5sig {
|
||||
struct sockaddr_storage tcpm_addr;
|
||||
u16_t __tcpm_pad1;
|
||||
u16_t tcpm_keylen;
|
||||
u32_t __tcpm_pad2;
|
||||
u8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
|
||||
};
|
||||
|
||||
/* socket setsockopt hook: */
|
||||
int tcp_md5_setsockopt_hook(struct lwip_sock *sock, int level, int optname, const void *optval, u32_t optlen, int *err);
|
||||
|
||||
/* Internal hook functions */
|
||||
void tcp_md5_init(void);
|
||||
err_t tcp_md5_check_inpacket(struct tcp_pcb* pcb, struct tcp_hdr *hdr, u16_t optlen, u16_t opt1len, u8_t *opt2, struct pbuf *p);
|
||||
u8_t tcp_md5_get_additional_option_length(const struct tcp_pcb *pcb, u8_t internal_option_length);
|
||||
u32_t *tcp_md5_add_tx_options(struct pbuf *p, struct tcp_hdr *hdr, const struct tcp_pcb *pcb, u32_t *opts);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_CONTRIB_ADDONS_TCP_MD5_H */
|
||||
67
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj
vendored
Normal file
67
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CCodeGeneration</RootNamespace>
|
||||
<AssemblyName>CCodeGeneration</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CFile.cs" />
|
||||
<Compile Include="Code.cs" />
|
||||
<Compile Include="CodeContainerBase.cs" />
|
||||
<Compile Include="CodeElement.cs" />
|
||||
<Compile Include="Comment.cs" />
|
||||
<Compile Include="EmptyLine.cs" />
|
||||
<Compile Include="Function.cs" />
|
||||
<Compile Include="CGenerator.cs" />
|
||||
<Compile Include="IfThenElse.cs" />
|
||||
<Compile Include="PlainText.cs" />
|
||||
<Compile Include="Switch.cs" />
|
||||
<Compile Include="PP_If.cs" />
|
||||
<Compile Include="PP_Ifdef.cs" />
|
||||
<Compile Include="PP_Include.cs" />
|
||||
<Compile Include="FunctionDeclaration.cs" />
|
||||
<Compile Include="PP_Macro.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="VariableDeclaration.cs" />
|
||||
<Compile Include="VariablePrototype.cs" />
|
||||
<Compile Include="VariableType.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
54
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CFile.cs
vendored
Normal file
54
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CFile.cs
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class CFile: CodeContainerBase
|
||||
{
|
||||
public CFile()
|
||||
{
|
||||
base.IncreaseLevel = false;
|
||||
}
|
||||
|
||||
public void Save(CGenerator generator)
|
||||
{
|
||||
if (generator == null)
|
||||
{
|
||||
throw new ArgumentNullException("generator");
|
||||
}
|
||||
|
||||
this.GenerateCode(0, generator);
|
||||
}
|
||||
}
|
||||
}
|
||||
119
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CGenerator.cs
vendored
Normal file
119
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CGenerator.cs
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class CGenerator
|
||||
{
|
||||
public TextWriter OutputStream { get; private set; }
|
||||
public string File { get; private set; }
|
||||
public uint IndentCount { get; private set; }
|
||||
public string IndentChar { get; private set; }
|
||||
public string NewLine { get; private set; }
|
||||
|
||||
public CGenerator(System.IO.TextWriter outputStream, string file, uint indentCount, string indentChar, string newLine)
|
||||
{
|
||||
this.OutputStream = outputStream;
|
||||
this.File = file;
|
||||
this.IndentCount = indentCount;
|
||||
this.IndentChar = indentChar;
|
||||
this.NewLine = newLine;
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.File))
|
||||
{
|
||||
return Path.GetFileName(this.File);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteSequence(string value, uint repetitions)
|
||||
{
|
||||
while (repetitions > 0)
|
||||
{
|
||||
this.OutputStream.Write(value);
|
||||
repetitions--;
|
||||
}
|
||||
}
|
||||
|
||||
public void IndentLine(int level)
|
||||
{
|
||||
while (level > 0)
|
||||
{
|
||||
WriteSequence(this.IndentChar, this.IndentCount);
|
||||
level--;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteNewLine()
|
||||
{
|
||||
this.OutputStream.Write(this.NewLine);
|
||||
}
|
||||
|
||||
public void WriteMultilineString(string value, int level = 0)
|
||||
{
|
||||
if (String.IsNullOrEmpty(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// only \n and \r\n are recognized as linebreaks
|
||||
string[] lines = value.Split(new char[] { '\n' }, StringSplitOptions.None);
|
||||
|
||||
for (int l = 0; l < (lines.Length - 1); l++)
|
||||
{
|
||||
if (lines[l].EndsWith("\r"))
|
||||
{
|
||||
this.OutputStream.Write(lines[l].Substring(0, lines[l].Length-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.OutputStream.Write(lines[l]);
|
||||
}
|
||||
|
||||
this.WriteNewLine();
|
||||
this.IndentLine(level);
|
||||
}
|
||||
|
||||
this.OutputStream.Write(lines[lines.Length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Code.cs
vendored
Normal file
56
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Code.cs
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class Code: CodeElement
|
||||
{
|
||||
public string Code_ { get; set; }
|
||||
|
||||
public Code()
|
||||
{
|
||||
}
|
||||
|
||||
public Code(string code)
|
||||
{
|
||||
this.Code_ = code;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
generator.WriteMultilineString(this.Code_, level);
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
139
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs
vendored
Normal file
139
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class CodeContainerBase: CodeElement
|
||||
{
|
||||
private readonly List<CodeElement> declarations = new List<CodeElement>();
|
||||
private readonly List<CodeElement> innerElements = new List<CodeElement>();
|
||||
private bool increaseLevel = true;
|
||||
|
||||
public List<CodeElement> Declarations
|
||||
{
|
||||
get { return this.declarations; }
|
||||
}
|
||||
|
||||
public List<CodeElement> InnerElements
|
||||
{
|
||||
get { return this.innerElements; }
|
||||
}
|
||||
|
||||
protected bool IncreaseLevel
|
||||
{
|
||||
get { return this.increaseLevel; }
|
||||
set { this.increaseLevel = value; }
|
||||
}
|
||||
|
||||
public void AddElements(IList<CodeElement> elements, params CodeElement[] spacerElements)
|
||||
{
|
||||
if (elements != null)
|
||||
{
|
||||
if ((spacerElements == null) || (spacerElements.Length == 0))
|
||||
{
|
||||
this.innerElements.AddRange(elements);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool spacerAdded = false;
|
||||
|
||||
foreach (CodeElement element in elements)
|
||||
{
|
||||
this.innerElements.Add(element);
|
||||
this.innerElements.AddRange(spacerElements);
|
||||
spacerAdded = true;
|
||||
}
|
||||
|
||||
if (spacerAdded)
|
||||
{
|
||||
// remove last spacer again
|
||||
this.innerElements.RemoveRange(this.innerElements.Count - spacerElements.Length, spacerElements.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CodeElement AddElement(CodeElement element)
|
||||
{
|
||||
if (element != null)
|
||||
{
|
||||
this.innerElements.Add(element);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
public Code AddCode(string code)
|
||||
{
|
||||
return this.AddElement(new Code(code)) as Code;
|
||||
}
|
||||
|
||||
public Code AddCodeFormat(string codeFormat, params object[] args)
|
||||
{
|
||||
return this.AddElement(new Code(String.Format(codeFormat, args))) as Code;
|
||||
}
|
||||
|
||||
public CodeElement AddDeclaration(CodeElement declaration)
|
||||
{
|
||||
if (declaration != null)
|
||||
{
|
||||
this.declarations.Add(declaration);
|
||||
}
|
||||
|
||||
return declaration;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (this.increaseLevel)
|
||||
level++;
|
||||
|
||||
if (this.declarations.Count > 0)
|
||||
{
|
||||
foreach (CodeElement element in this.declarations)
|
||||
{
|
||||
element.GenerateCode(level, generator);
|
||||
}
|
||||
|
||||
EmptyLine.SingleLine.GenerateCode(level, generator);
|
||||
}
|
||||
|
||||
foreach (CodeElement element in this.innerElements)
|
||||
{
|
||||
element.GenerateCode(level, generator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CodeElement.cs
vendored
Normal file
41
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/CodeElement.cs
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class CodeElement
|
||||
{
|
||||
public virtual void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
75
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Comment.cs
vendored
Normal file
75
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Comment.cs
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class Comment: CodeElement
|
||||
{
|
||||
public const string CommentStart = "/*";
|
||||
public const string CommentEnd = "*/";
|
||||
|
||||
public string Comment_ { get; set; }
|
||||
public bool SingleLine { get; set; }
|
||||
|
||||
public Comment()
|
||||
{
|
||||
}
|
||||
|
||||
public Comment(string comment, bool singleLine = false)
|
||||
{
|
||||
this.Comment_ = comment;
|
||||
this.SingleLine = singleLine;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write(CommentStart);
|
||||
|
||||
if (!this.SingleLine)
|
||||
{
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
generator.WriteMultilineString(this.Comment_, level);
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.OutputStream.Write(" " + Comment_ + " ");
|
||||
}
|
||||
|
||||
generator.OutputStream.Write(CommentEnd);
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/EmptyLine.cs
vendored
Normal file
64
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/EmptyLine.cs
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class EmptyLine : CodeElement
|
||||
{
|
||||
public static readonly EmptyLine SingleLine = new EmptyLine();
|
||||
public static readonly EmptyLine TwoLines = new EmptyLine(2);
|
||||
public static readonly EmptyLine ThreeLines = new EmptyLine(3);
|
||||
|
||||
public uint Count { get; set; }
|
||||
|
||||
public EmptyLine()
|
||||
{
|
||||
this.Count = 1;
|
||||
}
|
||||
|
||||
public EmptyLine(uint count)
|
||||
{
|
||||
this.Count = count;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
uint c = this.Count;
|
||||
|
||||
while (c > 0)
|
||||
{
|
||||
generator.WriteNewLine();
|
||||
c--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Function.cs
vendored
Normal file
129
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Function.cs
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class Function: CodeContainerBase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool IsStatic { get; set; }
|
||||
|
||||
private readonly List<VariableType> parameter = new List<VariableType>();
|
||||
private VariableType returnType = VariableType.Void;
|
||||
|
||||
public Function()
|
||||
{
|
||||
}
|
||||
|
||||
public Function(string name, bool isStatic = false)
|
||||
{
|
||||
this.Name = name;
|
||||
this.IsStatic = isStatic;
|
||||
}
|
||||
|
||||
public List<VariableType> Parameter
|
||||
{
|
||||
get { return this.parameter; }
|
||||
}
|
||||
|
||||
public VariableType ReturnType
|
||||
{
|
||||
get { return this.returnType; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("ReturnValue");
|
||||
}
|
||||
this.returnType = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Function FromDeclaration(FunctionDeclaration decl)
|
||||
{
|
||||
Function result = new Function(decl.Name, decl.IsStatic);
|
||||
result.ReturnType = decl.ReturnType.Clone() as VariableType;
|
||||
|
||||
foreach (VariableType param in decl.Parameter)
|
||||
{
|
||||
result.parameter.Add(param.Clone() as VariableType);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
|
||||
if (this.IsStatic)
|
||||
{
|
||||
generator.OutputStream.Write("static ");
|
||||
}
|
||||
|
||||
this.returnType.GenerateCode(generator);
|
||||
generator.OutputStream.Write(" " + this.Name + "(");
|
||||
|
||||
if (this.Parameter.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < this.parameter.Count; i++)
|
||||
{
|
||||
this.parameter[i].GenerateCode(generator);
|
||||
|
||||
if (i < (this.parameter.Count - 1))
|
||||
{
|
||||
generator.OutputStream.Write(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.OutputStream.Write("void");
|
||||
}
|
||||
|
||||
generator.OutputStream.Write(")");
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("{");
|
||||
generator.WriteNewLine();
|
||||
|
||||
base.GenerateCode(level, generator);
|
||||
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("}");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
114
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs
vendored
Normal file
114
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class FunctionDeclaration: CodeElement
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool IsStatic { get; set; }
|
||||
public bool IsExtern { get; set; }
|
||||
|
||||
private readonly List<VariableType> parameter = new List<VariableType>();
|
||||
private VariableType returnType = VariableType.Void;
|
||||
|
||||
public FunctionDeclaration()
|
||||
{
|
||||
}
|
||||
|
||||
public FunctionDeclaration(string name, bool isStatic = false, bool isExtern = false)
|
||||
{
|
||||
this.Name = name;
|
||||
this.IsStatic = isStatic;
|
||||
this.IsExtern = isExtern;
|
||||
}
|
||||
|
||||
public List<VariableType> Parameter
|
||||
{
|
||||
get { return this.parameter; }
|
||||
}
|
||||
|
||||
public VariableType ReturnType
|
||||
{
|
||||
get { return this.returnType; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("ReturnValue");
|
||||
}
|
||||
this.returnType = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
|
||||
if (this.IsExtern)
|
||||
{
|
||||
generator.OutputStream.Write("extern ");
|
||||
}
|
||||
|
||||
if (this.IsStatic)
|
||||
{
|
||||
generator.OutputStream.Write("static ");
|
||||
}
|
||||
|
||||
this.returnType.GenerateCode(generator);
|
||||
generator.OutputStream.Write(" " + this.Name + "(");
|
||||
|
||||
if (this.Parameter.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < this.parameter.Count; i++)
|
||||
{
|
||||
this.parameter[i].GenerateCode(generator);
|
||||
|
||||
if (i < (this.parameter.Count - 1))
|
||||
{
|
||||
generator.OutputStream.Write(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.OutputStream.Write("void");
|
||||
}
|
||||
|
||||
generator.OutputStream.Write(");");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
137
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/IfThenElse.cs
vendored
Normal file
137
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/IfThenElse.cs
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class ElseIf : CodeContainerBase
|
||||
{
|
||||
public string Condition { get; set; }
|
||||
|
||||
public ElseIf()
|
||||
{
|
||||
}
|
||||
|
||||
public ElseIf(string condition)
|
||||
{
|
||||
this.Condition = condition;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Condition))
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write(String.Format("else if ({0})", this.Condition));
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("{");
|
||||
generator.WriteNewLine();
|
||||
|
||||
base.GenerateCode(level, generator);
|
||||
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("}");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IfThenElse: CodeContainerBase
|
||||
{
|
||||
public string Condition { get; set; }
|
||||
|
||||
private List<ElseIf> elseIf = new List<ElseIf>();
|
||||
private CodeContainerBase else_ = new CodeContainerBase();
|
||||
|
||||
public IfThenElse()
|
||||
{
|
||||
}
|
||||
|
||||
public IfThenElse(string condition)
|
||||
{
|
||||
this.Condition = condition;
|
||||
}
|
||||
|
||||
public List<ElseIf> ElseIf
|
||||
{
|
||||
get { return this.elseIf; }
|
||||
}
|
||||
|
||||
public CodeContainerBase Else
|
||||
{
|
||||
get { return this.else_; }
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Condition))
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write(String.Format("if ({0})", this.Condition));
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("{");
|
||||
generator.WriteNewLine();
|
||||
|
||||
base.GenerateCode(level, generator);
|
||||
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("}");
|
||||
generator.WriteNewLine();
|
||||
|
||||
foreach (ElseIf elif in this.elseIf)
|
||||
{
|
||||
elif.GenerateCode(level, generator);
|
||||
}
|
||||
|
||||
if (this.else_.InnerElements.Count > 0)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("else");
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("{");
|
||||
generator.WriteNewLine();
|
||||
|
||||
this.else_.GenerateCode(level, generator);
|
||||
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("}");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_If.cs
vendored
Normal file
67
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_If.cs
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class PP_If: CodeContainerBase
|
||||
{
|
||||
public string Condition { get; set; }
|
||||
|
||||
public PP_If()
|
||||
{
|
||||
base.IncreaseLevel = false;
|
||||
}
|
||||
|
||||
public PP_If(string condition)
|
||||
: this()
|
||||
{
|
||||
this.Condition = condition;
|
||||
}
|
||||
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Condition))
|
||||
{
|
||||
generator.OutputStream.Write("#if " + this.Condition);
|
||||
generator.WriteNewLine();
|
||||
|
||||
base.GenerateCode(level, generator);
|
||||
|
||||
generator.OutputStream.Write("#endif /* " + this.Condition + " */");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
76
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs
vendored
Normal file
76
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class PP_Ifdef: CodeContainerBase
|
||||
{
|
||||
public string Macro { get; set; }
|
||||
public bool Inverted { get; set; }
|
||||
|
||||
public PP_Ifdef()
|
||||
{
|
||||
base.IncreaseLevel = false;
|
||||
}
|
||||
|
||||
public PP_Ifdef(string macro, bool inverted = false)
|
||||
: this()
|
||||
{
|
||||
this.Macro = macro;
|
||||
this.Inverted = inverted;
|
||||
}
|
||||
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Macro))
|
||||
{
|
||||
if (this.Inverted)
|
||||
{
|
||||
generator.OutputStream.Write("#ifndef " + this.Macro);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.OutputStream.Write("#ifdef " + this.Macro);
|
||||
}
|
||||
generator.WriteNewLine();
|
||||
|
||||
base.GenerateCode(level, generator);
|
||||
|
||||
generator.OutputStream.Write("#endif /* " + this.Macro + " */");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
71
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_Include.cs
vendored
Normal file
71
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_Include.cs
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class PP_Include : CodeElement
|
||||
{
|
||||
public string File { get; set; }
|
||||
public bool IsLocal { get; set; }
|
||||
|
||||
public PP_Include()
|
||||
{
|
||||
this.IsLocal = true;
|
||||
}
|
||||
|
||||
public PP_Include(string file, bool isLocal = true)
|
||||
{
|
||||
this.File = file;
|
||||
this.IsLocal = isLocal;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.File))
|
||||
{
|
||||
// includes are never indented
|
||||
if (this.IsLocal)
|
||||
{
|
||||
generator.OutputStream.Write("#include \"" + this.File + "\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.OutputStream.Write("#include <" + this.File + ">");
|
||||
}
|
||||
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_Macro.cs
vendored
Normal file
59
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PP_Macro.cs
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class PP_Macro: CodeElement
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public PP_Macro()
|
||||
{
|
||||
}
|
||||
|
||||
public PP_Macro(string name, string value)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
// macros are not indented at all
|
||||
generator.OutputStream.Write("#define " + this.Name + " ");
|
||||
generator.WriteMultilineString(this.Value);
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
49
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PlainText.cs
vendored
Normal file
49
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/PlainText.cs
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class PlainText : CodeElement
|
||||
{
|
||||
public string Value { get; set; }
|
||||
|
||||
public PlainText(string value)
|
||||
{
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
generator.WriteMultilineString(this.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die mit einer Assembly verknüpft sind.
|
||||
[assembly: AssemblyTitle("CCodeGeneration")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CCodeGeneration")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("8f07a0fa-86f4-48a0-97c7-f94fc5c3f103")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
146
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Switch.cs
vendored
Normal file
146
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/Switch.cs
vendored
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class SwitchCase : CodeContainerBase
|
||||
{
|
||||
public string Value { get; set; }
|
||||
|
||||
public SwitchCase()
|
||||
{
|
||||
}
|
||||
|
||||
public SwitchCase(string value)
|
||||
{
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public bool IsDefault
|
||||
{
|
||||
get { return (this.Value.ToLowerInvariant() == "default"); }
|
||||
}
|
||||
|
||||
public static SwitchCase GenerateDefault()
|
||||
{
|
||||
return new SwitchCase("default");
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Value))
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
if (this.IsDefault)
|
||||
{
|
||||
generator.OutputStream.Write("default:");
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.OutputStream.Write(String.Format("case {0}:", this.Value));
|
||||
}
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level + 1);
|
||||
generator.OutputStream.Write("{");
|
||||
generator.WriteNewLine();
|
||||
|
||||
base.GenerateCode(level + 1, generator);
|
||||
|
||||
generator.IndentLine(level + 1);
|
||||
generator.OutputStream.Write("}");
|
||||
generator.WriteNewLine();
|
||||
|
||||
generator.IndentLine(level + 1);
|
||||
generator.OutputStream.Write("break;");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Switch: CodeElement
|
||||
{
|
||||
public string SwitchVar { get; set; }
|
||||
|
||||
private List<SwitchCase> switches = new List<SwitchCase>();
|
||||
|
||||
public Switch()
|
||||
{
|
||||
}
|
||||
|
||||
public Switch(string switchVar)
|
||||
{
|
||||
this.SwitchVar = switchVar;
|
||||
}
|
||||
|
||||
public List<SwitchCase> Switches
|
||||
{
|
||||
get { return this.switches; }
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.SwitchVar))
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write(String.Format("switch ({0})", this.SwitchVar));
|
||||
generator.WriteNewLine();
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("{");
|
||||
generator.WriteNewLine();
|
||||
|
||||
SwitchCase defaultCase = null; // generate 'default' always as last case
|
||||
foreach (SwitchCase switchCase in this.switches)
|
||||
{
|
||||
if (switchCase.IsDefault)
|
||||
{
|
||||
defaultCase = switchCase;
|
||||
}
|
||||
else
|
||||
{
|
||||
switchCase.GenerateCode(level + 1, generator);
|
||||
}
|
||||
}
|
||||
if (defaultCase != null)
|
||||
{
|
||||
defaultCase.GenerateCode(level + 1, generator);
|
||||
}
|
||||
|
||||
generator.IndentLine(level);
|
||||
generator.OutputStream.Write("}");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
82
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs
vendored
Normal file
82
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class VariableDeclaration : CodeElement
|
||||
{
|
||||
public VariableType Type { get; set; }
|
||||
public string InitialValue { get; set; }
|
||||
public bool IsStatic { get; set; }
|
||||
|
||||
public VariableDeclaration()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public VariableDeclaration(VariableType type, string initialValue = null, bool isStatic = false) :
|
||||
base()
|
||||
{
|
||||
this.Type = type;
|
||||
this.InitialValue = initialValue;
|
||||
this.IsStatic = isStatic;
|
||||
}
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (this.Type != null)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
|
||||
if (this.IsStatic)
|
||||
{
|
||||
generator.OutputStream.Write("static ");
|
||||
}
|
||||
|
||||
// declare the variable
|
||||
this.Type.GenerateCode(generator);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(this.InitialValue))
|
||||
{
|
||||
// add initialization value
|
||||
generator.OutputStream.Write(" = ");
|
||||
generator.WriteMultilineString(this.InitialValue, level);
|
||||
}
|
||||
|
||||
generator.OutputStream.Write(";");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs
vendored
Normal file
73
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public class VariablePrototype : CodeElement
|
||||
{
|
||||
public VariableType Type { get; set; }
|
||||
|
||||
public VariablePrototype()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public VariablePrototype(VariableType type) :
|
||||
base()
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public static VariablePrototype FromVariableDeclaration(VariableDeclaration declaration)
|
||||
{
|
||||
return new VariablePrototype(declaration.Type);
|
||||
}
|
||||
|
||||
|
||||
public override void GenerateCode(int level, CGenerator generator)
|
||||
{
|
||||
if (this.Type != null)
|
||||
{
|
||||
generator.IndentLine(level);
|
||||
|
||||
generator.OutputStream.Write("extern ");
|
||||
|
||||
// declare the variable
|
||||
this.Type.GenerateCode(generator);
|
||||
|
||||
generator.OutputStream.Write(";");
|
||||
generator.WriteNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
130
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/VariableType.cs
vendored
Normal file
130
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/CCodeGeneration/VariableType.cs
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace CCodeGeneration
|
||||
{
|
||||
public enum ConstType
|
||||
{
|
||||
None,
|
||||
Value,
|
||||
Indirection,
|
||||
Both
|
||||
}
|
||||
|
||||
public class VariableType : ICloneable
|
||||
{
|
||||
public const string VoidString = "void";
|
||||
public static readonly VariableType Void = new VariableType(null, "void");
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Indirection { get; set; }
|
||||
public ConstType Const { get; set; }
|
||||
public string ArraySpecifier { get; set; }
|
||||
|
||||
public VariableType()
|
||||
{
|
||||
}
|
||||
|
||||
public VariableType(string name, string type, string indirection = null, ConstType const_ = ConstType.None, string arraySpecifier = null)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Type = type;
|
||||
this.Indirection = indirection;
|
||||
this.Const = const_;
|
||||
this.ArraySpecifier = arraySpecifier;
|
||||
}
|
||||
|
||||
public void GenerateCode(CGenerator generator)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Type))
|
||||
{
|
||||
generator.OutputStream.Write(this.ToString().Trim());
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(this.Type))
|
||||
{
|
||||
StringBuilder vt = new StringBuilder();
|
||||
|
||||
if ((this.Const == ConstType.Value) || (this.Const == ConstType.Both))
|
||||
{
|
||||
vt.Append("const ");
|
||||
}
|
||||
|
||||
vt.Append(this.Type);
|
||||
vt.Append(" ");
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(this.Indirection))
|
||||
{
|
||||
vt.Append(this.Indirection);
|
||||
}
|
||||
|
||||
if ((this.Const == ConstType.Indirection) || (this.Const == ConstType.Both))
|
||||
{
|
||||
vt.Append("const ");
|
||||
}
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(this.Name))
|
||||
{
|
||||
vt.Append(this.Name);
|
||||
}
|
||||
|
||||
if (this.ArraySpecifier != null)
|
||||
{
|
||||
vt.Append("[");
|
||||
vt.Append(this.ArraySpecifier);
|
||||
vt.Append("]");
|
||||
}
|
||||
|
||||
return vt.ToString().Trim();
|
||||
}
|
||||
|
||||
return base.ToString();
|
||||
}
|
||||
|
||||
#region ICloneable Member
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
// we only have value types as members -> simply use .net base function
|
||||
return this.MemberwiseClone();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
47
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/LwipMibCompiler.sln
vendored
Normal file
47
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/LwipMibCompiler.sln
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipMibCompiler", "LwipMibCompiler\LwipMibCompiler.csproj", "{C25D5640-D999-49BD-82E0-A1975296A91E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipSnmpCodeGeneration", "LwipSnmpCodeGeneration\LwipSnmpCodeGeneration.csproj", "{AABCAB90-1540-45D4-A159-14831A54E9A3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CCodeGeneration", "CCodeGeneration\CCodeGeneration.csproj", "{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpSnmpLib.Mib", "SharpSnmpLib\SharpSnmpLib.Mib.csproj", "{CBE20411-5DB7-487D-825D-7694267BB6F5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MibViewer", "MibViewer\MibViewer.csproj", "{86CC0B65-7985-4017-A252-0A7A18DCAEF3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AABCAB90-1540-45D4-A159-14831A54E9A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AABCAB90-1540-45D4-A159-14831A54E9A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AABCAB90-1540-45D4-A159-14831A54E9A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AABCAB90-1540-45D4-A159-14831A54E9A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C25D5640-D999-49BD-82E0-A1975296A91E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C25D5640-D999-49BD-82E0-A1975296A91E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C25D5640-D999-49BD-82E0-A1975296A91E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C25D5640-D999-49BD-82E0-A1975296A91E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CBE20411-5DB7-487D-825D-7694267BB6F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CBE20411-5DB7-487D-825D-7694267BB6F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CBE20411-5DB7-487D-825D-7694267BB6F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CBE20411-5DB7-487D-825D-7694267BB6F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = LwipMibCompiler\LwipMibCompiler.csproj
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
73
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj
vendored
Normal file
73
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C25D5640-D999-49BD-82E0-A1975296A91E}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LwipMibCompiler</RootNamespace>
|
||||
<AssemblyName>LwipMibCompiler</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CCodeGeneration\CCodeGeneration.csproj">
|
||||
<Project>{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}</Project>
|
||||
<Name>CCodeGeneration</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\LwipSnmpCodeGeneration\LwipSnmpCodeGeneration.csproj">
|
||||
<Project>{AABCAB90-1540-45D4-A159-14831A54E9A3}</Project>
|
||||
<Name>LwipSnmpCodeGeneration</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SharpSnmpLib\SharpSnmpLib.Mib.csproj">
|
||||
<Project>{CBE20411-5DB7-487D-825D-7694267BB6F5}</Project>
|
||||
<Name>SharpSnmpLib.Mib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
480
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/LwipMibCompiler/Program.cs
vendored
Normal file
480
libs/membrane/external/lwip/contrib/apps/LwipMibCompiler/LwipMibCompiler/Program.cs
vendored
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Martin Hentschel <info@cl-soft.de>
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using CCodeGeneration;
|
||||
using Lextm.SharpSnmpLib.Mib;
|
||||
using Lextm.SharpSnmpLib.Mib.Elements.Entities;
|
||||
using Lextm.SharpSnmpLib.Mib.Elements.Types;
|
||||
using LwipSnmpCodeGeneration;
|
||||
|
||||
namespace LwipMibCompiler
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static readonly Regex _alphaNumericRegex = new Regex("[^a-zA-Z0-9]");
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("lwIP MIB Compiler");
|
||||
Console.WriteLine("");
|
||||
|
||||
// check args
|
||||
if ((args.Length < 2) || String.IsNullOrWhiteSpace(args[0]) || String.IsNullOrWhiteSpace(args[1]))
|
||||
{
|
||||
PrintUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
string mibFile = args[0];
|
||||
if (!File.Exists(mibFile))
|
||||
{
|
||||
Console.WriteLine(String.Format("Unable to find file '{0}'!", mibFile));
|
||||
}
|
||||
|
||||
string destFile = args[1];
|
||||
string destHeaderFile;
|
||||
|
||||
if (Directory.Exists(destFile))
|
||||
{
|
||||
// only directory passed -> create dest filename from mib filename
|
||||
string mibFileName = Path.GetFileNameWithoutExtension(mibFile).ToLowerInvariant();
|
||||
destFile = Path.Combine(destFile, mibFileName + ".c");
|
||||
}
|
||||
|
||||
string destFileExt = Path.GetExtension(destFile);
|
||||
if (!String.IsNullOrEmpty(destFileExt))
|
||||
{
|
||||
destHeaderFile = destFile.Substring(0, destFile.Length - destFileExt.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
destHeaderFile = destFile;
|
||||
}
|
||||
destHeaderFile += ".h";
|
||||
|
||||
for (int i=2; i<args.Length; i++)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(args[i]) && Directory.Exists(args[i]))
|
||||
{
|
||||
MibTypesResolver.RegisterResolver(new FileSystemMibResolver(args[i], true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read and resolve MIB
|
||||
Console.WriteLine(" Reading MIB file...");
|
||||
|
||||
MibDocument md = new MibDocument(mibFile);
|
||||
MibTypesResolver.ResolveTypes(md.Modules[0]);
|
||||
MibTree mt = new MibTree(md.Modules[0] as MibModule);
|
||||
|
||||
if (mt.Root.Count == 0)
|
||||
{
|
||||
Console.WriteLine("No root element found inside MIB!");
|
||||
return;
|
||||
}
|
||||
|
||||
MibCFile generatedFile = new MibCFile();
|
||||
MibHeaderFile generatedHeaderFile = new MibHeaderFile();
|
||||
|
||||
foreach (MibTreeNode mibTreeNode in mt.Root)
|
||||
{
|
||||
// create LWIP object tree from MIB structure
|
||||
Console.WriteLine(" Creating lwIP object tree " + mibTreeNode.Entity.Name);
|
||||
|
||||
SnmpMib snmpMib = new SnmpMib();
|
||||
snmpMib.Oid = mibTreeNode.Entity.Value;
|
||||
snmpMib.BaseOid = MibTypesResolver.ResolveOid(mibTreeNode.Entity).GetOidValues();
|
||||
snmpMib.Name = mibTreeNode.Entity.Name;
|
||||
|
||||
ProcessMibTreeNode(mibTreeNode, snmpMib);
|
||||
|
||||
// let the tree transform itself depending on node structure
|
||||
snmpMib.Analyze();
|
||||
|
||||
if (snmpMib.ChildNodes.Count != 0)
|
||||
{
|
||||
// generate code from LWIP object tree
|
||||
Console.WriteLine(" Generating code " + snmpMib.Name);
|
||||
snmpMib.Generate(generatedFile, generatedHeaderFile);
|
||||
}
|
||||
}
|
||||
|
||||
string preservedCode = MibCFile.GetPreservedCode(destFile);
|
||||
if (!string.IsNullOrEmpty(preservedCode))
|
||||
{
|
||||
generatedFile.PreservedCode.Add(new PlainText(preservedCode));
|
||||
}
|
||||
else
|
||||
{
|
||||
generatedFile.PreservedCode.AddRange(generatedFile.Implementation);
|
||||
}
|
||||
generatedFile.Implementation.Clear();
|
||||
|
||||
|
||||
using (StreamWriter fileWriter = new StreamWriter(destHeaderFile))
|
||||
{
|
||||
CGenerator cGenerator = new CGenerator(fileWriter, destHeaderFile, 3, " ", Environment.NewLine);
|
||||
generatedHeaderFile.Save(cGenerator);
|
||||
}
|
||||
using (StreamWriter fileWriter = new StreamWriter(destFile))
|
||||
{
|
||||
CGenerator cGenerator = new CGenerator(fileWriter, destFile, 3, " ", Environment.NewLine);
|
||||
generatedFile.Save(cGenerator);
|
||||
}
|
||||
|
||||
Console.WriteLine(" Done");
|
||||
}
|
||||
|
||||
private static void PrintUsage()
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
string appName = Path.GetFileName(codeBase);
|
||||
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine(String.Format(" {0} <source MIB file> <dest C file> [<search path 1 for referred MIB's> <search path 2 for referred MIB's> ...]", appName));
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine(" <source MIB file>");
|
||||
Console.WriteLine(" Path and filename of MIB file to convert.");
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine(" <dest C file>");
|
||||
Console.WriteLine(" Destination path and file. If a path is passed only, filename is auto");
|
||||
Console.WriteLine(" generated from MIB file name.");
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine(" <search path X for referred MIB's>");
|
||||
Console.WriteLine(" It's important to provide all referred MIB's in order to correctly ");
|
||||
Console.WriteLine(" resolve all used types.");
|
||||
Console.WriteLine("");
|
||||
}
|
||||
|
||||
|
||||
#region Generation of LWIP Object Tree
|
||||
|
||||
private static void ProcessMibTreeNode(MibTreeNode mibTreeNode, SnmpTreeNode assignedSnmpNode)
|
||||
{
|
||||
foreach (MibTreeNode mtn in mibTreeNode.ChildNodes)
|
||||
{
|
||||
// in theory container nodes may also be scalars or tables at the same time (for now only process real containers)
|
||||
if (mtn.NodeType == MibTreeNodeType.Container)
|
||||
{
|
||||
SnmpTreeNode snmpTreeNode = GenerateSnmpTreeNode(mtn, assignedSnmpNode);
|
||||
assignedSnmpNode.ChildNodes.Add(snmpTreeNode);
|
||||
|
||||
ProcessMibTreeNode(mtn, snmpTreeNode);
|
||||
}
|
||||
else if ((mtn.NodeType & MibTreeNodeType.Scalar) != 0)
|
||||
{
|
||||
SnmpScalarNode snmpScalarNode = GenerateSnmpScalarNode(mtn, assignedSnmpNode);
|
||||
if (snmpScalarNode != null)
|
||||
{
|
||||
assignedSnmpNode.ChildNodes.Add(snmpScalarNode);
|
||||
}
|
||||
}
|
||||
else if ((mtn.NodeType & MibTreeNodeType.Table) != 0)
|
||||
{
|
||||
SnmpTableNode snmpTableNode = GenerateSnmpTableNode(mtn, assignedSnmpNode);
|
||||
if (snmpTableNode != null)
|
||||
{
|
||||
assignedSnmpNode.ChildNodes.Add(snmpTableNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static SnmpTreeNode GenerateSnmpTreeNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode)
|
||||
{
|
||||
SnmpTreeNode result = new SnmpTreeNode(parentNode);
|
||||
result.Name = _alphaNumericRegex.Replace (mibTreeNode.Entity.Name, "");
|
||||
result.Oid = mibTreeNode.Entity.Value;
|
||||
result.FullOid = MibTypesResolver.ResolveOid(mibTreeNode.Entity).GetOidString();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SnmpScalarNode GenerateSnmpScalarNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode, bool ignoreAccessibleFlag = false)
|
||||
{
|
||||
ObjectType ote = mibTreeNode.Entity as ObjectType;
|
||||
if (ote != null)
|
||||
{
|
||||
return GenerateSnmpScalarNode(ote, parentNode, ignoreAccessibleFlag);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static SnmpScalarNode GenerateSnmpScalarNode(ObjectType ote, SnmpTreeNode parentNode, bool ignoreAccessibleFlag = false)
|
||||
{
|
||||
SnmpScalarNode result;
|
||||
|
||||
ITypeAssignment mibType = ote.BaseType;
|
||||
IntegerType it = (mibType as IntegerType);
|
||||
if (it != null)
|
||||
{
|
||||
if (ote.ReferredType.Name == Symbol.TruthValue.ToString())
|
||||
{
|
||||
result = new SnmpScalarNodeTruthValue(parentNode);
|
||||
}
|
||||
else if ((it.Type == IntegerType.Types.Integer) || (it.Type == IntegerType.Types.Integer32))
|
||||
{
|
||||
result = new SnmpScalarNodeInt(parentNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(String.Format("Unsupported IntegerType '{0}'!", it.Type));
|
||||
return null;
|
||||
}
|
||||
if (it.IsEnumeration)
|
||||
{
|
||||
result.Restrictions.AddRange(CreateRestrictions(it.Enumeration));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Restrictions.AddRange(CreateRestrictions(it.Ranges));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnsignedType ut = (mibType as UnsignedType);
|
||||
if (ut != null)
|
||||
{
|
||||
if ((ut.Type == UnsignedType.Types.Unsigned32) ||
|
||||
(ut.Type == UnsignedType.Types.Gauge32))
|
||||
{
|
||||
result = new SnmpScalarNodeUint(SnmpDataType.Gauge, parentNode);
|
||||
}
|
||||
else if (ut.Type == UnsignedType.Types.Counter32)
|
||||
{
|
||||
result = new SnmpScalarNodeUint(SnmpDataType.Counter, parentNode);
|
||||
}
|
||||
else if (ut.Type == UnsignedType.Types.TimeTicks)
|
||||
{
|
||||
result = new SnmpScalarNodeUint(SnmpDataType.TimeTicks, parentNode);
|
||||
}
|
||||
else if (ut.Type == UnsignedType.Types.Counter64)
|
||||
{
|
||||
result = new SnmpScalarNodeCounter64(parentNode);
|
||||
if ((ut.Ranges != null) && (ut.Ranges.Count > 0))
|
||||
{
|
||||
Console.WriteLine(String.Format("Generation of ranges is not supported for Counter64 type!"));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(String.Format("Unsupported UnsignedType '{0}'!", ut.Type));
|
||||
return null;
|
||||
}
|
||||
result.Restrictions.AddRange(CreateRestrictions(ut.Ranges));
|
||||
}
|
||||
else if (mibType is IpAddressType)
|
||||
{
|
||||
result = new SnmpScalarNodeOctetString(SnmpDataType.IpAddress, parentNode);
|
||||
result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size));
|
||||
}
|
||||
else if (mibType is OpaqueType)
|
||||
{
|
||||
result = new SnmpScalarNodeOctetString(SnmpDataType.Opaque, parentNode);
|
||||
result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size));
|
||||
}
|
||||
else if (mibType is OctetStringType)
|
||||
{
|
||||
result = new SnmpScalarNodeOctetString(SnmpDataType.OctetString, parentNode);
|
||||
result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size));
|
||||
}
|
||||
else if (mibType is ObjectIdentifierType)
|
||||
{
|
||||
result = new SnmpScalarNodeObjectIdentifier(parentNode);
|
||||
}
|
||||
else if (mibType is BitsType)
|
||||
{
|
||||
result = new SnmpScalarNodeBits(parentNode, (uint)((mibType as BitsType).Map.GetHighestValue() + 1));
|
||||
result.Restrictions.AddRange(CreateRestrictions(mibType as BitsType));
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeAssignment ta = mibType as TypeAssignment;
|
||||
if (ta != null)
|
||||
{
|
||||
Console.WriteLine(String.Format("Unsupported BaseType: Module='{0}', Name='{1}', Type='{2}'!", ta.Module.Name, ta.Name, ta.Type));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(String.Format("Unsupported BaseType: Module='{0}', Name='{1}'!", mibType.Module, mibType.Name));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
result.Name = _alphaNumericRegex.Replace(ote.Name, "");
|
||||
result.Oid = ote.Value;
|
||||
|
||||
if (ote.Access == MaxAccess.readWrite)
|
||||
{
|
||||
result.AccessMode = SnmpAccessMode.ReadWrite;
|
||||
}
|
||||
else if (ote.Access == MaxAccess.readOnly)
|
||||
{
|
||||
result.AccessMode = SnmpAccessMode.ReadOnly;
|
||||
}
|
||||
else if (ote.Access == MaxAccess.readCreate)
|
||||
{
|
||||
result.AccessMode = SnmpAccessMode.ReadOnly;
|
||||
}
|
||||
else if (ignoreAccessibleFlag && (ote.Access == MaxAccess.notAccessible))
|
||||
{
|
||||
result.AccessMode = SnmpAccessMode.NotAccessible;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not accessible or unsupported access type
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<IRestriction> CreateRestrictions(ValueRanges ranges)
|
||||
{
|
||||
List<IRestriction> result = new List<IRestriction>();
|
||||
|
||||
if (ranges != null)
|
||||
{
|
||||
foreach (ValueRange range in ranges)
|
||||
{
|
||||
if (!range.End.HasValue)
|
||||
{
|
||||
result.Add(new IsEqualRestriction(range.Start));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new IsInRangeRestriction(range.Start, range.End.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<IRestriction> CreateRestrictions(ValueMap map)
|
||||
{
|
||||
if ((map != null) && (map.Count > 0))
|
||||
{
|
||||
return CreateRestrictions(map.GetContinousRanges());
|
||||
}
|
||||
|
||||
return new List<IRestriction>();
|
||||
}
|
||||
|
||||
private static IEnumerable<IRestriction> CreateRestrictions(BitsType bt)
|
||||
{
|
||||
List<IRestriction> result = new List<IRestriction>();
|
||||
|
||||
if ((bt != null) && (bt.Map != null))
|
||||
{
|
||||
result.Add(new BitMaskRestriction(bt.Map.GetBitMask()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SnmpTableNode GenerateSnmpTableNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode)
|
||||
{
|
||||
SnmpTableNode result = new SnmpTableNode(parentNode);
|
||||
result.Name = mibTreeNode.Entity.Name;
|
||||
result.Oid = mibTreeNode.Entity.Value;
|
||||
|
||||
// expect exactly one row entry
|
||||
if ((mibTreeNode.ChildNodes.Count != 1) || ((mibTreeNode.ChildNodes[0].NodeType & MibTreeNodeType.TableRow) == 0) || (mibTreeNode.ChildNodes[0].Entity.Value != 1))
|
||||
{
|
||||
Console.WriteLine("Found table with unsupported properties! Table needs exactly one (fixed) TableRow with OID=1 ! (" + mibTreeNode.Entity.Name + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
MibTreeNode rowNode = mibTreeNode.ChildNodes[0];
|
||||
|
||||
ObjectType rot = rowNode.Entity as ObjectType;
|
||||
if (rot != null)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(rot.Augments))
|
||||
{
|
||||
result.AugmentedTableRow = rot.Augments;
|
||||
|
||||
// the indices from another table shall be used because this table is only an extension of it
|
||||
rot = MibTypesResolver.ResolveDeclaration(rot.Module, rot.Augments) as ObjectType;
|
||||
}
|
||||
|
||||
if (rot.Indices != null)
|
||||
{
|
||||
foreach (string index in rot.Indices)
|
||||
{
|
||||
ObjectType indexEntity = MibTypesResolver.ResolveDeclaration(rot.Module, index) as ObjectType;
|
||||
if (indexEntity == null)
|
||||
{
|
||||
Console.WriteLine(String.Format("Could not resolve index '{0}' for table '{1}'! Table omitted!", index, result.Name));
|
||||
return null;
|
||||
}
|
||||
|
||||
result.IndexNodes.Add(GenerateSnmpScalarNode(indexEntity, parentNode, ignoreAccessibleFlag: true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.IndexNodes.Count == 0)
|
||||
{
|
||||
// a table cannot be used without index
|
||||
Console.WriteLine("Found table without any index column ! (" + mibTreeNode.Entity.Name + ")");
|
||||
return null;
|
||||
}
|
||||
|
||||
// add child nodes
|
||||
foreach (MibTreeNode cellNode in rowNode.ChildNodes)
|
||||
{
|
||||
SnmpScalarNode ssn = GenerateSnmpScalarNode(cellNode, parentNode);
|
||||
if (ssn != null)
|
||||
{
|
||||
result.CellNodes.Add(ssn);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue