// // Copyright 2026 Aarav Ravindra Kharade // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // - // ArkOS Runtime Daemon (arkrt) // - import CSystem @_silgen_name("ark_wayland_server_init") func ark_wayland_server_init() @_silgen_name("ark_wayland_server_run") func ark_wayland_server_run() // The primary system daemon, running as PID 1. // Responsible for: // // 1. Mounting system and vendor partitions // 2. Configuring network interfaces // 3. Starting the IPC server for inter-process communication // 4. Discovering and starting system services (display, UI, etc.) // 5. Launching the boot splash animation // 6. Monitoring all child processes and respawning on crash // // Boot Sequence: // - arkrt (PID 1) // - IPC Server (thread) // - NetworkService (thread) // - display service (child process) // - swift_splash (child process — temporary) // - ui_test (child process — launched by ServiceManager) // // - // - Phase 1: System Initialization (PID 1) - // Redirect stdout/stderr to serial console for QEMU log capture let serialFd = ark_open2("/dev/ttyS0", O_RDWR) if serialFd >= 0 { dup2(serialFd, 1) // stdout → serial dup2(serialFd, 2) // stderr → serial if serialFd > 2 { close(serialFd) } } // Mount core kernel filesystems required by Swift and system APIs LogManager.log("ArkOS Runtime Daemon starting as PID 1...", component: "ark.log") LogManager.log("PID=\(getpid()), UID=\(getuid())", component: "ark.log") // Report system resources let cpuCores = ResourceController.getCPUCoreCount() let totalRAM = ResourceController.getTotalMemory() / 1024 / 1024 let initialRSS = ResourceController.checkMemoryUsage() / 1024 LogManager.log("System: \(cpuCores) CPU cores, \(totalRAM) MB RAM, RSS=\(initialRSS) KB", component: "ark.log") // - Phase 2: Mount System Partitions - LogManager.log("Mounting system partitions...", component: "ark.log") if true { let items = ["dev_node"] LogManager.log("arkrt: /dev contents: \(items.joined(separator: ", "))") } func mountPartition(devices: [String], mountPoint: String, fsType: String) { mkdir(mountPoint, 0o755) if fsType == "tmpfs" { let result = mount("tmpfs", mountPoint, fsType, 0, nil) if result == 0 { LogManager.log("Mounted tmpfs → \(mountPoint) (\(fsType))", component: "ark.log") } else { LogManager.log("Failed to mount tmpfs to \(mountPoint)", level: .warn, component: "ark.log") } return } // Wait up to 3 seconds total for ANY of the devices to appear var waited = 0 while waited < 30 { for device in devices { if access(device, F_OK) == 0 { let result = mount(device, mountPoint, fsType, 0, nil) if result == 0 { LogManager.log("Mounted \(device) → \(mountPoint) (\(fsType))", component: "ark.log") return } } } usleep(100_000) // 100ms waited += 1 } LogManager.log("Failed to mount any device to \(mountPoint)", level: .warn, component: "ark.log") } // Mount tmpfs for runtime state mountPartition(devices: ["tmpfs"], mountPoint: "/run", fsType: "tmpfs") mountPartition(devices: ["tmpfs"], mountPoint: "/tmp", fsType: "tmpfs") // Create essential runtime directories mkdir("/run", 0o755) mkdir("/var/log", 0o755) mkdir("/etc", 0o755) mkdir("/system", 0o755) mkdir("/vendor", 0o755) // Attempt to mount system and vendor from disk images (block devices) let systemDevices = ["/dev/vdb", "/dev/sdb", "/dev/hdb", "/dev/sda2"] let vendorDevices = ["/dev/vdc", "/dev/sdc", "/dev/hdc", "/dev/sda3"] mountPartition(devices: systemDevices, mountPoint: "/system", fsType: "ext4") mountPartition(devices: vendorDevices, mountPoint: "/vendor", fsType: "ext4") // - Phase 3: Network Configuration - LogManager.log("Configuring network interfaces...", component: "ark.log") NetworkService.shared.configureInterfaces() NetworkService.shared.startMonitoring() // - Phase 4: IPC Server - LogManager.log("Starting IPC server...", component: "ark.log") var server = IPCServer() server.start() // - Phase 5: Display Initialization - setenv("XDG_RUNTIME_DIR", "/run", 1) setenv("WAYLAND_DEBUG", "1", 1) LogManager.log("Initializing monolithic display daemon...", component: "ark.log") ArkCompositor.shared.start() renderBuffer = UnsafeMutablePointer.allocate(capacity: scrW * scrH * bpp) LogManager.log("Starting display event loop...", component: "ark.log") // The wayland thread is now started internally inside ArkCompositor.shared.start() LogManager.log("Rendering boot splash...", component: "ark.log") drawSwiftSplash() LogManager.log("Starting system services...", component: "ark.log") ServiceManager.shared.startAllServices() var lastResolution: String = "" ResourceController.executeOnCorePool { while true { // Monitor all managed services for crashes ServiceManager.shared.monitorServices() // Periodic resource health check let ram = ResourceController.checkMemoryUsage() if ram > 1_500_000_000 { // 1.5 GB LogManager.log("HIGH MEMORY WARNING: \(ram / 1024 / 1024) MB RSS", level: .warn, component: "ark.log") } // Check for resolution changes if let fp = fopen("/sys/class/graphics/fb0/virtual_size", "r") { var buf = [CChar](repeating: 0, count: 64) if fgets(&buf, Int32(buf.count), fp) != nil { let currentRes = String(cString: buf) if lastResolution != "" && currentRes != lastResolution { LogManager.log("Resolution changed from \(lastResolution) to \(currentRes).", component: "ark.log") // Handle dynamic resolution changes here if needed } lastResolution = currentRes } fclose(fp) } // Log heartbeat every ~60 iterations (2 min) sleep(2) } } // - Phase 8: Main App - // The main thread runs the UI setup app natively. // Background queues (IPC, network monitor, display daemon, and service manager) // continue running in the CorePool. // LogManager.log("Starting SetupApp on main thread...", component: "ark.log") // SetupApp.main() // Keep PID 1 alive while true { sleep(60) }