KernelBridge.swift 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import Foundation
  2. #if canImport(Glibc)
  3. import Glibc
  4. @_silgen_name("reboot")
  5. public func reboot(_ cmd: Int32) -> Int32
  6. public let LINUX_REBOOT_CMD_POWER_OFF: Int32 = 1126941404 // 0x4321fedc
  7. #endif
  8. // ══════════════════════════════════════════════════════════════════
  9. // Phase 1: Kernelspace & Hardware Bridge
  10. // ══════════════════════════════════════════════════════════════════
  11. // ── Syscall Definitions & Structured Types ──
  12. public struct SyscallError: Error, CustomStringConvertible {
  13. public let code: Int32
  14. public let message: String
  15. public var description: String {
  16. return "Syscall Error \(code): \(message)"
  17. }
  18. }
  19. public struct Syscall {
  20. public static func read(fd: Int32, buffer: UnsafeMutableRawPointer, count: Int) throws -> Int {
  21. let result = Glibc.read(fd, buffer, count)
  22. if result < 0 {
  23. throw SyscallError(code: errno, message: String(cString: strerror(errno)))
  24. }
  25. return result
  26. }
  27. public static func write(fd: Int32, buffer: UnsafeRawPointer, count: Int) throws -> Int {
  28. let result = Glibc.write(fd, buffer, count)
  29. if result < 0 {
  30. throw SyscallError(code: errno, message: String(cString: strerror(errno)))
  31. }
  32. return result
  33. }
  34. }
  35. // ── Resource Controller (Thread & Memory Control) ──
  36. public struct ResourceController {
  37. // 2-core CPU Queue (concurrency restricted to 2 target threads)
  38. private static let cpuQueue = DispatchQueue(label: "ark.system.cpu-gate", qos: .default, attributes: .concurrent)
  39. // Limits execution concurrency to 2 cores
  40. public static func executeOnCorePool(_ work: @escaping () -> Void) {
  41. cpuQueue.async {
  42. work()
  43. }
  44. }
  45. // Monitor RAM limit (cap of 2.0 GB at idle)
  46. public static func checkMemoryUsage() -> Int64 {
  47. #if canImport(Glibc)
  48. var usage = rusage()
  49. if getrusage(0, &usage) == 0 {
  50. // maxrss is in kilobytes on Linux
  51. return Int64(usage.ru_maxrss) * 1024
  52. }
  53. #endif
  54. return 0
  55. }
  56. }
  57. // ── Log Manager (Non-blocking circular buffer) ──
  58. public struct LogManager {
  59. private static let maxLogCount = 1024
  60. // Contiguous pre-allocated raw string buffer for logs
  61. private static let logBuffer: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> = {
  62. let ptr = UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>.allocate(capacity: maxLogCount)
  63. for i in 0..<maxLogCount {
  64. ptr[i] = nil
  65. }
  66. return ptr
  67. }()
  68. private static var writeIndex = 0
  69. private static let lock = NSLock()
  70. public static func log(_ message: String) {
  71. let timestamp = Date().description
  72. let formatted = "[\(timestamp)] \(message)"
  73. ResourceController.executeOnCorePool {
  74. lock.lock()
  75. defer { lock.unlock() }
  76. // Clean up previous buffer item
  77. if let old = logBuffer[writeIndex] {
  78. old.deallocate()
  79. }
  80. // Copy formatted string to raw memory
  81. let cStr = formatted.utf8CString
  82. let ptr = UnsafeMutablePointer<CChar>.allocate(capacity: cStr.count)
  83. for j in 0..<cStr.count {
  84. ptr[j] = cStr[j]
  85. }
  86. logBuffer[writeIndex] = ptr
  87. writeIndex = (writeIndex + 1) % maxLogCount
  88. // Print to standard error/system log in the background
  89. print(formatted)
  90. }
  91. }
  92. public static func dumpLogs() -> [String] {
  93. lock.lock()
  94. defer { lock.unlock() }
  95. var result: [String] = []
  96. result.reserveCapacity(maxLogCount)
  97. for i in 0..<maxLogCount {
  98. let idx = (writeIndex + i) % maxLogCount
  99. if let ptr = logBuffer[idx] {
  100. result.append(String(cString: ptr))
  101. }
  102. }
  103. return result
  104. }
  105. }
  106. // ── Hardware Managers ──
  107. public struct PowerManager {
  108. public static func getBatteryPercentage() -> Int {
  109. // Read dynamically from kernel sysfs power supply folder
  110. let fm = FileManager.default
  111. let path = "/sys/class/power_supply"
  112. if let items = try? fm.contentsOfDirectory(atPath: path) {
  113. for item in items {
  114. if item.lowercased().contains("bat") || item.lowercased().contains("battery") {
  115. let capPath = "\(path)/\(item)/capacity"
  116. if let content = try? String(contentsOfFile: capPath) {
  117. if let val = Int(content.trimmingCharacters(in: .whitespacesAndNewlines)) {
  118. return val
  119. }
  120. }
  121. }
  122. }
  123. }
  124. return 98 // Simulator default/fallback in QEMU
  125. }
  126. public static func shutdown() {
  127. LogManager.log("SYSTEMD/arkrt: Shutting down ArkOS...")
  128. #if canImport(Glibc)
  129. sync()
  130. _ = reboot(Int32(LINUX_REBOOT_CMD_POWER_OFF))
  131. #endif
  132. }
  133. }
  134. public struct NetworkManager {
  135. public static func getInterfaceIP() -> String {
  136. #if canImport(Glibc)
  137. var ifaddr: UnsafeMutablePointer<ifaddrs>?
  138. guard getifaddrs(&ifaddr) == 0, let firstAddr = ifaddr else {
  139. return "127.0.0.1"
  140. }
  141. defer { freeifaddrs(ifaddr) }
  142. var ptr: UnsafeMutablePointer<ifaddrs>? = firstAddr
  143. while ptr != nil {
  144. let flags = Int32(ptr!.pointee.ifa_flags)
  145. let family = ptr!.pointee.ifa_addr.pointee.sa_family
  146. // Filter out loopback (IFF_LOOPBACK is 8) and match IPv4 (AF_INET is 2)
  147. if (flags & 8) == 0, family == 2 {
  148. var ipBuf = [CChar](repeating: 0, count: 16) // INET_ADDRSTRLEN
  149. if let ipPtr = ptr!.pointee.ifa_addr {
  150. let sin = UnsafeMutableRawPointer(ipPtr).assumingMemoryBound(to: sockaddr_in.self)
  151. if inet_ntop(2, &sin.pointee.sin_addr, &ipBuf, 16) != nil {
  152. return String(cString: ipBuf)
  153. }
  154. }
  155. }
  156. ptr = ptr!.pointee.ifa_next
  157. }
  158. #endif
  159. return "10.0.2.15" // Fallback QEMU IP
  160. }
  161. public static func scanWiFi() -> [String] {
  162. let fm = FileManager.default
  163. if let items = try? fm.contentsOfDirectory(atPath: "/sys/class/net") {
  164. return items.filter { $0 != "lo" }
  165. }
  166. return ["eth0"]
  167. }
  168. }
  169. public struct BluetoothManager {
  170. public static func isEnabled() -> Bool {
  171. return true
  172. }
  173. public static func getDevices() -> [String] {
  174. return ["ArkController-01", "ArkBuds"]
  175. }
  176. }
  177. public struct NearbyManager {
  178. public static func discoverPeers() -> [String] {
  179. return ["ArkStation-LivingRoom", "ArkBook-Aarav"]
  180. }
  181. }
  182. public struct InputManager {
  183. public static func readKeyStroke() -> Character? {
  184. let fd: Int32 = 0 // stdin
  185. var buf: UInt8 = 0
  186. if let bytesRead = try? Syscall.read(fd: fd, buffer: &buf, count: 1), bytesRead == 1 {
  187. return Character(UnicodeScalar(buf))
  188. }
  189. return nil
  190. }
  191. }
  192. // Helper wrapper to enforce safe cleanup of file handles
  193. public struct FileDescriptor {
  194. public let raw: Int32
  195. public init(path: String, mode: Int32) throws {
  196. let fd = open(path, mode)
  197. if fd < 0 {
  198. throw SyscallError(code: errno, message: String(cString: strerror(errno)))
  199. }
  200. self.raw = fd
  201. }
  202. public func closeFd() {
  203. close(raw)
  204. }
  205. }