Browse Source

Fixed Boot Issues and Display issues!

Arphd4 1 month ago
parent
commit
bc0a4ccab0

+ 26 - 27
arkos/Makefile

@@ -36,22 +36,23 @@ run:
 	@qemu-system-x86_64 \
 		-m 2048 \
 		-smp 2 \
-		-drive file=finished/boot.img,format=raw,index=0,media=disk \
-		-drive file=finished/sys.img,format=raw,index=1,media=disk \
-		-drive file=finished/vend.img,format=raw,index=2,media=disk \
-		-vga virtio \
+		-drive file=finished/boot.img,format=raw,index=0,media=disk,if=virtio \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk,if=virtio \
+		-drive file=finished/vend.img,format=raw,index=2,media=disk,if=virtio \
+		-vga virtio -debugcon file:ovmf.log -global isa-debugcon.iobase=0x402 \
 		-netdev user,id=net0 \
 		-device virtio-net-pci,netdev=net0 \
 		-enable-kvm 2>/dev/null || \
 	qemu-system-x86_64 \
 		-m 2048 \
 		-smp 2 \
-		-drive file=finished/boot.img,format=raw,index=0,media=disk \
-		-drive file=finished/sys.img,format=raw,index=1,media=disk \
-		-drive file=finished/vend.img,format=raw,index=2,media=disk \
-		-vga virtio \
+		-drive file=finished/boot.img,format=raw,index=0,media=disk,if=virtio \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk,if=virtio \
+		-drive file=finished/vend.img,format=raw,index=2,media=disk,if=virtio \
+		-vga virtio -debugcon file:ovmf.log -global isa-debugcon.iobase=0x402 \
 		-netdev user,id=net0 \
-		-device virtio-net-pci,netdev=net0
+		-device virtio-net-pci,netdev=net0 \
+		-serial stdio
 
 # ── Run (UEFI) ────────────────────────────────────────────────────
 run-uefi:
@@ -60,10 +61,10 @@ run-uefi:
 		-bios /usr/share/edk2/x64/OVMF.4m.fd \
 		-m 2048 \
 		-smp 2 \
-		-drive file=finished/boot.img,format=raw,index=0,media=disk \
-		-drive file=finished/sys.img,format=raw,index=1,media=disk \
-		-drive file=finished/vend.img,format=raw,index=2,media=disk \
-		-vga virtio \
+		-drive file=finished/boot.img,format=raw,index=0,media=disk,if=virtio \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk,if=virtio \
+		-drive file=finished/vend.img,format=raw,index=2,media=disk,if=virtio \
+		-device virtio-vga,xres=1080,yres=1900 -debugcon file:ovmf.log -global isa-debugcon.iobase=0x402 \
 		-netdev user,id=net0 \
 		-device virtio-net-pci,netdev=net0 \
 		-enable-kvm 2>/dev/null || \
@@ -71,10 +72,10 @@ run-uefi:
 		-bios /usr/share/edk2/x64/OVMF.4m.fd \
 		-m 2048 \
 		-smp 2 \
-		-drive file=finished/boot.img,format=raw,index=0,media=disk \
-		-drive file=finished/sys.img,format=raw,index=1,media=disk \
-		-drive file=finished/vend.img,format=raw,index=2,media=disk \
-		-vga virtio \
+		-drive file=finished/boot.img,format=raw,index=0,media=disk,if=virtio \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk,if=virtio \
+		-drive file=finished/vend.img,format=raw,index=2,media=disk,if=virtio \
+		-device virtio-vga,xres=1080,yres=1900 -debugcon file:ovmf.log -global isa-debugcon.iobase=0x402 \
 		-netdev user,id=net0 \
 		-device virtio-net-pci,netdev=net0
 
@@ -100,11 +101,9 @@ ARK_KEY := $(shell if [ -f vendor/verify/securebuild.ark ]; then \
 out_staging/fb_helper.o: system/core/fb_helper.c
 	gcc -c system/core/fb_helper.c -o out_staging/fb_helper.o
 
-# ── swift_splash — Boot splash animation ──────────────────────────
-out_staging/swift_splash: system/swift_splash.swift out_staging/fb_helper.o
-	swiftc -O -static-executable \
-		system/swift_splash.swift out_staging/fb_helper.o \
-		-o out_staging/swift_splash
+# ── swift_splash — Boot Animation ────────────────────────────────
+# Moved to ui_daemon
+# (Removed swift_splash target)
 
 # ── arkrt — ArkOS Runtime Daemon (PID 2) ──────────────────────────
 out_staging/arkrt: arkrt/main.swift arkrt/KernelBridge.swift \
@@ -140,11 +139,11 @@ out_staging/BOOTX64.EFI: boot/source/bootloader.c
 		-j .rel -j .rela -j .reloc -j .eh_frame \
 		-O pei-x86-64 --subsystem 10 out_staging/bootloader_uefi.so out_staging/BOOTX64.EFI
 
-# ── ui_daemon — Display compositor daemon ─────────────────────────
-out_staging/system/ui_daemon: system/display/main.swift out_staging/fb_helper.o
-	mkdir -p out_staging/system
-	swiftc -O -static-executable \
-		system/display/main.swift out_staging/fb_helper.o \
+# ── ui_daemon — Display Compositor ─────────────────────────────────
+out_staging/system/ui_daemon: system/display/main.swift system/display/splash.swift out_staging/fb_helper.o
+	@mkdir -p out_staging/system
+	@swiftc -O -static-executable \
+		system/display/main.swift system/display/splash.swift out_staging/fb_helper.o \
 		-o out_staging/system/ui_daemon
 
 # ── ui_test — Setup / Welcome app ────────────────────────────────

+ 7 - 7
arkos/README.md

@@ -38,7 +38,8 @@ See [ArkOS: Comprehensive System Architecture](arkos_architecture_guide.md) for
 ```bash
 cd arkos/
 make build    # Compiles everything, generates disk images
-make run      # Launches QEMU with the built images
+make run      # Launches QEMU with the built images (BIOS Mode)
+make run-uefi # Launches QEMU in UEFI Mode
 make clean    # Removes all build artifacts
 ```
 
@@ -83,25 +84,24 @@ All images are generated in `finished/`:
 ```
 arkos/
 ├── boot/                    # Bootloader source & configs
-│   ├── source/              # Assembly source (bootloader.asm, stage2.asm)
+│   ├── source/              # Assembly source (bootloader.asm, stage2.asm) and C source (bootloader.c)
 │   │   └── animationframes/ # Pre-generated boot animation frames
 │   ├── initramfs.img        # Base initramfs image
 │   └── *.ark                # Boot configuration files
 ├── frameworks/              # OS frameworks (Swift, DRM, SwiftUI)
-├── hardware/                # Hardware abstraction layer (future)
 ├── kernel/                  # Linux kernel source + prebuilt bzImage
 ├── prebuilts/               # Prebuilt toolchains
 │   └── clang/               # LLVM/Clang 22 toolchain
 ├── system/                  # Core system components
 │   ├── init.c               # PID 1 init process (Verified Boot)
-│   ├── swift_splash.swift   # Native Swift framebuffer splash
+│   ├── display/             # Display compositor (ui_daemon) and boot animation
 │   ├── sha256.c/h           # SHA256 implementation for signing
 │   └── fb_helper.c          # Framebuffer ioctl helper
 ├── vendor/                  # Vendor-specific files
 │   ├── verify/              # Verified Boot keys & signing tools
 │   ├── mirror/              # Mirror configuration
 │   └── Widewine/            # DRM (Widevine) integration
-├── arkrt/                   # ArkOS runtime (future)
+├── arkrt/                   # ArkOS runtime monolithic daemon
 ├── Makefile                 # Top-level build entry point
 └── finished/                # Build output (generated)
 ```
@@ -111,10 +111,10 @@ arkos/
 ArkOS implements a custom Verified Boot chain:
 
 1. The build system reads the signing key from `vendor/verify/securebuild.ark`
-2. `sign.py` computes `SHA256(KEY + swift_splash_binary)` → `signature.bin`
+2. `sign.py` computes `SHA256(KEY + arkrt_binary)` → `signature.bin`
 3. At boot, `init.c` recomputes the hash and compares against `signature.bin`
 4. **Mismatch → Kernel Panic** (system halts with security warning)
-5. **Match → Boot continues** into the Swift splash screen
+5. **Match → Boot continues** into the `arkrt` daemon and UI layer
 
 > ⚠️ Never commit your real signing key to a public repository. Use `vendor/verify/key.py` to generate new keys.
 

+ 41 - 17
arkos/arkos_architecture_guide.md

@@ -14,7 +14,7 @@ graph TD
     B -->|Modesetting & Quiet Console| C[Linux Kernel]
     C -->|Launches PID 1| D[init.c]
     D -->|Quiet Verified Boot Check| E[arkrt Daemon]
-    E -->|Isolated fork & execve| F[swift_splash UI]
+    E -->|Isolated fork & execve| F[ui_daemon]
     F -->|Unix Domain Socket IPC| E
 ```
 
@@ -115,9 +115,9 @@ Communication between the isolated UI and `arkrt` uses a strict binary packet st
 
 ---
 
-## 5. Isolated Main User UI (`swift_splash.swift`)
+## 5. Isolated Display Compositor (`ui_daemon`)
 
-The user interface layer is decoupled from the service framework, operating as an isolated process with restricted privileges to prevent UI faults from crashing the kernel.
+The user interface layer is decoupled from the service framework, operating as an isolated process with restricted privileges to prevent UI faults from crashing the kernel. `ui_daemon` replaces the former `swift_splash` binary and now acts as the primary display compositor. It initializes the framebuffer, draws the boot animation, and acts as a socket-based display server for other UI apps.
 
 ### Double-Buffered Rendering
 - Opens the system framebuffer `/dev/fb0`.
@@ -154,7 +154,7 @@ The ArkOS repository contains a mix of fully implemented core systems and placeh
 ### System Initialization & Core Daemon
 - **`system/`** [Status: Fully Implemented]
   - **`init.c`**: The PID 1 init process. It is responsible for mounting virtual filesystems (`/proc`, `/sys`, `/dev`), computing the SHA-256 hash of the `arkrt` binary, and comparing it against the embedded `ARK_KEY` signature. Upon successful cryptographic verification, it forks and executes `arkrt`.
-  - **`swift_splash.swift`**: The isolated UI process that acts as the visual layer during initialization. It maps the `/dev/fb0` framebuffer into user space via `fb_helper.c` and performs double-buffered software rendering using custom anti-aliasing algorithms to draw shapes.
+  - **`ui_daemon`**: The isolated UI compositor process that acts as the visual layer during initialization and beyond. It maps the `/dev/fb0` framebuffer into user space via `fb_helper.c` and performs double-buffered software rendering.
   - **`sysroot/`**: The basic skeleton of the root filesystem (`/etc`, `/usr`, `/lib`, `/sbin`) populated during the build stage.
   - **`services/` & `install/`** [Status: Unimplemented Placeholder]: Currently empty directories reserved for future system service configuration files and an eventual OS installer application.
 - **`arkrt/`** [Status: Fully Implemented]
@@ -166,17 +166,11 @@ The ArkOS repository contains a mix of fully implemented core systems and placeh
   - **`SwiftUIFramework/` (`ark_ui_basic`)** [Status: Partially Implemented]: A ground-up port and modification of OpenSwiftUI. It acts as the primary declarative UI framework for ArkOS. 
     - **Current Integration:** The framework successfully compiles within the `out_staging` directory using incremental caching (`--scratch-path`). The type-erasure and protocol constraints have been resolved to prevent compiler crashes during cross-module optimization. However, it is not yet dynamically linked or actively utilized by the system applications or the overarching Desktop Environment shell.
   - **`DRM/`** [Status: Unimplemented Placeholder]: The skeletal structure for a Digital Rights Management client and daemon intended for secure media playback.
-- **`packages/`** [Status: Unimplemented Placeholder]
-  - **`sysApps/`**: Contains empty subdirectories (`Browser`, `Calculator`, `Calender`, `Clock`, `Files`, `Gallery`, `Messages`, `Phone`) which act as placeholders for the core suite of ArkOS applications.
-  - **`UI/`**: The designated location for the Window Manager and Desktop Environment shell that will eventually consume the `ark_ui_basic` framework.
-
-### Vendor Verification & Hardware Abstraction
+### Vendor Verification
 - **`vendor/`** [Status: Partially Implemented]
   - **`verify/`**: Contains Python scripts (`sign.py`, `key.py`) and C headers (`sha256.c`) used dynamically during the build process to cryptographically sign the `arkrt` executable, ensuring the chain of trust established in `init.c`.
   - **`mirror/` & `OS_INFO`**: Files specifying OS update mirror endpoints and metadata strings identifying the OS build version.
   - **`Widewine/`** [Status: Unimplemented Placeholder]: Contains a mocked `drm.ark` file reserved for future Widevine DRM binary blobs.
-- **`hardware/`** [Status: Unimplemented Placeholder]
-  - An empty directory reserved for specialized hardware abstraction layers (HAL) and third-party drivers that fall outside the purview of the mainline kernel.
 
 ### Build Orchestration & Image Assembly
 - **`tools/`** [Status: Fully Implemented]
@@ -269,7 +263,7 @@ Output: The kernel populates these directories. No text is printed to stdout to
 
 #### Cryptographic Signature Verification
 ```c
-#define ARK_KEY "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+#define ARK_KEY "e3b0c44298fc1c149afbf4c899*************************8"
 
 int verify_arkrt() {
     FILE *f = fopen("/sbin/arkrt", "rb");
@@ -310,8 +304,8 @@ int main() {
 
 ---
 
-### 7.3. The Isolated UI: `swift_splash.swift`
-`swift_splash.swift` is executed separately and is entirely responsible for drawing pixels to the screen using double-buffered memory arrays.
+### 7.3. The Isolated UI Daemon: `ui_daemon`
+`ui_daemon` (`main.swift` and `splash.swift`) is executed separately and is entirely responsible for drawing pixels to the screen using double-buffered memory arrays. It is started by `arkrt` as the primary display compositor.
 
 #### Framebuffer Memory Mapping
 ```swift
@@ -457,13 +451,43 @@ system("xorriso -as mkisofs -R -J -b boot/grub/i386-pc/eltorito.img -no-emul-boo
        "-boot-load-size 4 -boot-info-table -o finished/arkos.iso out_staging/");
 ```
 **Execution & Output:**
-After all binaries (`init`, `arkrt`, `swift_splash`) are placed in `out_staging`, `xorriso` wraps the entire directory into an ISO-9660 filesystem image. It targets `eltorito.img` to ensure the CD image is natively bootable by a legacy BIOS or UEFI compatibility layer. Output: `arkos.iso` in the `finished/` directory.
+After all binaries (`init`, `arkrt`, `ui_daemon`) are placed in `out_staging`, `xorriso` wraps the entire directory into an ISO-9660 filesystem image. It targets `eltorito.img` to ensure the CD image is natively bootable by a legacy BIOS or UEFI compatibility layer. Output: `arkos.iso` in the `finished/` directory.
+
+---
+
+## 7.6. Make Targets and Build System Execution
+The build system in ArkOS is managed via a top-level `Makefile` which automates execution. 
+
+#### `make build`
+```makefile
+build:
+	@$(MAKE) --no-print-directory -C $(TOOLS)
+	@$(TOOLS)/build $(ARKOS)
+```
+**Execution & Output:**
+This target compiles the `tools/build.c` orchestrator and executes it. `build.c` takes over the process, compiliing `init.c`, `arkrt`, `ui_daemon`, Bootloaders, and the SwiftUI framework. It copies the necessary components into `out_staging` and generates the final images in `finished/`.
+
+#### `make run`
+```makefile
+run:
+	@qemu-system-x86_64 -m 2048 -smp 2 -drive file=finished/boot.img...
+```
+**Execution & Output:**
+Executes ArkOS in QEMU via Legacy BIOS mode. It provisions 2GB of RAM and 2 CPUs. It maps `boot.img`, `sys.img`, and `vend.img` as virtio disks. It sets up networking via user-mode TCP/IP stack (`virtio-net-pci`) and graphical output via `virtio-vga`.
+
+#### `make run-uefi`
+```makefile
+run-uefi:
+	@qemu-system-x86_64 -bios /usr/share/edk2/x64/OVMF.4m.fd -m 2048 ... -device virtio-vga,xres=1080,yres=1900
+```
+**Execution & Output:**
+Similar to `make run`, but injects the `OVMF.4m.fd` firmware to simulate a UEFI motherboard. It also enforces a custom display resolution (`1080x1900`) dynamically passed to the virtio VGA adapter to test UEFI graphics capabilities and adaptive UI rendering.
 
 
 
 ---
 
-## 7.6. UEFI Bootloader: `bootloader.c`
+## 7.7. UEFI Bootloader: `bootloader.c`
 While the Legacy BIOS boot relies on 16-bit assembly (`bootloader.asm`), the modern UEFI bootloader is written entirely in C (`bootloader.c`). It leverages the Extensible Firmware Interface (EFI) API to interact directly with the motherboard's firmware in 32-bit or 64-bit protected/long mode right from the start.
 
 #### Graphics Initialization (GOP) & Initial Display
@@ -536,7 +560,7 @@ Before starting the kernel, the bootloader injects boot parameters directly into
 
 ---
 
-## 7.7. Architectural Comparison: Legacy BIOS vs. UEFI Boot Flow
+## 7.8. Architectural Comparison: Legacy BIOS vs. UEFI Boot Flow
 
 | Feature | Legacy BIOS (`bootloader.asm`) | UEFI (`bootloader.c`) |
 |---------|--------------------------------|------------------------|

+ 3 - 3
arkos/arkrt/ServiceManager.swift

@@ -225,7 +225,7 @@ class ServiceManager {
     // ── Service Lifecycle ─────────────────────────────────────────
 
     /// Starts a single service by name. Forks a child process, redirects
-    /// I/O to /dev/console, and exec's the service binary.
+    /// I/O to /dev/ttyS0, and exec's the service binary.
     func startService(name: String) {
         guard var service = services[name] else {
             LogManager.log("ServiceManager: Unknown service '\(name)'", level: .error)
@@ -247,8 +247,8 @@ class ServiceManager {
         let pid = fork()
         if pid == 0 {
             // ── Child Process ──
-            // Redirect stdout/stderr to /dev/console for visibility
-            let consoleFd = open("/dev/console", O_RDWR)
+            // Redirect stdout/stderr to /dev/ttyS0 for visibility
+            let consoleFd = open("/dev/ttyS0", O_RDWR)
             if consoleFd >= 0 {
                 dup2(consoleFd, 1)
                 dup2(consoleFd, 2)

+ 67 - 77
arkos/arkrt/main.swift

@@ -3,9 +3,9 @@ import Foundation
 import Glibc
 #endif
 
-// ═══════════════════════════════════════════════════════════════════
+// -
 //  ArkOS Runtime Daemon (arkrt)
-// ═══════════════════════════════════════════════════════════════════
+// -
 //  The primary system daemon, running as PID 2 (spawned by init).
 //  Responsible for:
 //
@@ -18,16 +18,16 @@ import Glibc
 //
 //  Boot Sequence:
 //    init (PID 1)
-//      └─ arkrt (PID 2)
-//           ├─ IPC Server (thread)
-//           ├─ NetworkService (thread)
-//           ├─ display service (child process)
-//           ├─ swift_splash (child process — temporary)
-//           └─ ui_test (child process — launched by ServiceManager)
+//      - arkrt (PID 2)
+//           - 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 ────────────────────────────────
+// - Phase 1: System Initialization -
 
 LogManager.log("arkrt: ArkOS Runtime Daemon starting...")
 LogManager.log("arkrt: PID=\(getpid()), UID=\(getuid())")
@@ -38,107 +38,82 @@ let totalRAM = ResourceController.getTotalMemory() / 1024 / 1024
 let initialRSS = ResourceController.checkMemoryUsage() / 1024
 LogManager.log("arkrt: System: \(cpuCores) CPU cores, \(totalRAM) MB RAM, RSS=\(initialRSS) KB")
 
-// ── Phase 2: Mount System Partitions ──────────────────────────────
+// - Phase 2: Mount System Partitions -
 
 LogManager.log("arkrt: Mounting system partitions...")
+if let items = try? FileManager.default.contentsOfDirectory(atPath: "/dev") {
+    LogManager.log("arkrt: /dev contents: \(items.joined(separator: ", "))")
+}
 
 /// Mount a block device to a mount point. Creates the directory if needed.
-func mountPartition(device: String, mountPoint: String, fsType: String) {
+func mountPartition(devices: [String], mountPoint: String, fsType: String) {
     mkdir(mountPoint, 0o755)
 
-    let result = mount(device, mountPoint, fsType, 0, nil)
-    if result == 0 {
-        LogManager.log("arkrt: Mounted \(device) → \(mountPoint) (\(fsType))")
-    } else {
-        LogManager.log("arkrt: Failed to mount \(device) → \(mountPoint): \(String(cString: strerror(errno)))", level: .warn)
+    for device in devices {
+        // Wait up to 3 seconds for the device to appear
+        var waited = 0
+        if fsType != "tmpfs" {
+            while access(device, F_OK) != 0 && waited < 30 {
+                usleep(100_000) // 100ms
+                waited += 1
+            }
+        }
+        
+        if fsType == "tmpfs" || access(device, F_OK) == 0 {
+            let result = mount(device, mountPoint, fsType, 0, nil)
+            if result == 0 {
+                LogManager.log("arkrt: Mounted \(device) → \(mountPoint) (\(fsType))")
+                return
+            }
+        }
     }
+    LogManager.log("arkrt: Failed to mount any device to \(mountPoint)", level: .warn)
 }
 
 // Mount tmpfs for runtime state
-mountPartition(device: "tmpfs", mountPoint: "/run", fsType: "tmpfs")
-mountPartition(device: "tmpfs", mountPoint: "/tmp", fsType: "tmpfs")
+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)
-// In QEMU, the system image is on the second disk (/dev/sdb)
-// and vendor is on the third disk (/dev/sdc)
-mountPartition(device: "/dev/sdb", mountPoint: "/system", fsType: "ext4")
-mountPartition(device: "/dev/sdc", mountPoint: "/vendor", fsType: "ext4")
+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 ───────────────────────────────
+// - Phase 3: Network Configuration -
 
 LogManager.log("arkrt: Configuring network interfaces...")
 NetworkService.shared.configureInterfaces()
 NetworkService.shared.startMonitoring()
 
-// ── Phase 4: IPC Server ───────────────────────────────────────────
+// - Phase 4: IPC Server -
 
 LogManager.log("arkrt: Starting IPC server...")
 var server = IPCServer()
 server.start()
 
-// ── Phase 5: Service Discovery & Startup ──────────────────────────
-
-LogManager.log("arkrt: Starting system services...")
-ServiceManager.shared.startAllServices()
-
-// ── Phase 6: Boot Splash Animation ────────────────────────────────
-
-/// Spawns the boot splash animation in an isolated child process.
-/// The splash exits on its own after the animation completes (~3.8s).
-func spawnSplash() -> pid_t {
-    LogManager.log("arkrt: Launching boot splash (/swift_splash)...")
-    let pid = fork()
-    if pid == 0 {
-        // ── Child Process ──
-        let consoleFd = open("/dev/console", O_RDWR)
-        if consoleFd >= 0 {
-            dup2(consoleFd, 1)
-            dup2(consoleFd, 2)
-            if consoleFd > 2 { close(consoleFd) }
-        }
-
-        let path = "/swift_splash"
-        let cArg0 = strdup(path)
-        let argv: [UnsafeMutablePointer<CChar>?] = [cArg0, nil]
+// - Phase 5: Service Discovery -
+// We wait to start services until the splash completes so ui_daemon
+// doesn't fight over the framebuffer.
 
-        let env0 = strdup("PATH=/bin:/usr/bin:/sbin:/system")
-        let env1 = strdup("HOME=/")
-        let env2 = strdup("TERM=linux")
-        let envp: [UnsafeMutablePointer<CChar>?] = [env0, env1, env2, nil]
+// Boot splash animation has been moved into the ui_daemon service
 
-        execve(path, argv, envp)
+// - Phase 7: Main Monitoring Loop -
 
-        // execve only returns on failure
-        print("arkrt: Failed to execute /swift_splash")
-        _exit(1)
-    }
-    return pid
-}
-
-// Start the splash animation
-var splashPid = spawnSplash()
-
-// ── Phase 7: Main Monitoring Loop ─────────────────────────────────
+LogManager.log("arkrt: Starting system services...")
+ServiceManager.shared.startAllServices()
 
-LogManager.log("arkrt: Entering main monitoring loop...")
+var lastResolution: String = ""
 
 ResourceController.executeOnCorePool {
     while true {
-        // Check if the splash animation has completed
-        if splashPid > 0 {
-            var status: Int32 = 0
-            let result = waitpid(splashPid, &status, WNOHANG)
-            if result == splashPid {
-                LogManager.log("arkrt: Boot splash completed")
-                splashPid = -1
-            }
-        }
-
         // Monitor all managed services for crashes
         ServiceManager.shared.monitorServices()
 
@@ -148,12 +123,27 @@ ResourceController.executeOnCorePool {
             LogManager.log("arkrt: HIGH MEMORY WARNING: \(ram / 1024 / 1024) MB RSS", level: .warn)
         }
 
+        // 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).trimmingCharacters(in: .whitespacesAndNewlines)
+                if lastResolution != "" && currentRes != lastResolution {
+                    LogManager.log("arkrt: Resolution changed from \(lastResolution) to \(currentRes). Restarting display service...")
+                    ServiceManager.shared.stopService(name: "display")
+                    ServiceManager.shared.startService(name: "display")
+                }
+                lastResolution = currentRes
+            }
+            fclose(fp)
+        }
+
         // Log heartbeat every ~60 iterations (2 min)
         sleep(2)
     }
 }
 
-// ── Keep Main Thread Alive ────────────────────────────────────────
+// - Keep Main Thread Alive -
 
 // The main thread must remain alive to service Foundation dispatch
 // queues (used by IPC, network monitor, and service manager).

+ 21 - 10
arkos/boot/source/bootloader.c

@@ -122,26 +122,29 @@ static EFI_STATUS read_file_from_esp(
     UINTN file_size = file_info->FileSize;
     uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
 
-    // 6. Allocate buffer for file contents
-    VOID *buffer = NULL;
+    // 6. Allocate buffer for file contents using AllocatePages for large buffers
+    UINTN num_pages = (file_size + 4095) / 4096;
+    EFI_PHYSICAL_ADDRESS phys_buffer = 0;
     status = uefi_call_wrapper(
-        SystemTable->BootServices->AllocatePool,
-        3,
+        SystemTable->BootServices->AllocatePages,
+        4,
+        AllocateAnyPages,
         EfiLoaderData,
-        file_size,
-        &buffer
+        num_pages,
+        &phys_buffer
     );
     if (EFI_ERROR(status)) {
         uefi_call_wrapper(file->Close, 1, file);
         uefi_call_wrapper(root->Close, 1, root);
         return status;
     }
+    VOID *buffer = (VOID *)(UINTN)phys_buffer;
 
     // 7. Read file contents
     UINTN read_size = file_size;
     status = uefi_call_wrapper(file->Read, 3, file, &read_size, buffer);
     if (EFI_ERROR(status) || read_size != file_size) {
-        uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, buffer);
+        uefi_call_wrapper(SystemTable->BootServices->FreePages, 2, phys_buffer, num_pages);
         uefi_call_wrapper(file->Close, 1, file);
         uefi_call_wrapper(root->Close, 1, root);
         return EFI_DEVICE_ERROR;
@@ -249,11 +252,19 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
         VOID *anim_buffer = NULL;
         UINTN anim_size = 0;
         status = read_file_from_esp(ImageHandle, SystemTable, L"\\EFI\\BOOT\\animation.bin", &anim_buffer, &anim_size);
-        if (!EFI_ERROR(status)) {
+        if (EFI_ERROR(status)) {
+            EFI_GRAPHICS_OUTPUT_BLT_PIXEL red = {0, 0, 255, 0};
+            uefi_call_wrapper(gop->Blt, 10, gop, &red, EfiBltVideoFill, 0, 0, center_x + 97, center_y + 97, 16, 16, 0);
+            uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 3000000); // 3 seconds
+        } else {
             UINTN num_frames = 60;
             UINTN expected_size = num_frames * anim_width * anim_height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
             
-            if (anim_size >= expected_size) {
+            if (anim_size < expected_size) {
+                EFI_GRAPHICS_OUTPUT_BLT_PIXEL green = {0, 255, 0, 0};
+                uefi_call_wrapper(gop->Blt, 10, gop, &green, EfiBltVideoFill, 0, 0, center_x + 97, center_y + 97, 16, 16, 0);
+                uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 3000000); // 3 seconds
+            } else {
                 // Clear the white dot to black first
                 EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
                 uefi_call_wrapper(
@@ -288,7 +299,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
                     uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 16666);
                 }
             }
-            uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, anim_buffer);
+            uefi_call_wrapper(SystemTable->BootServices->FreePages, 2, (EFI_PHYSICAL_ADDRESS)(UINTN)anim_buffer, (anim_size + 4095) / 4096);
         }
     }
 

+ 247 - 0
arkos/boot/source/bootloader.c.orig

@@ -0,0 +1,247 @@
+#include <efi.h>
+#include <efilib.h>
+
+// Simulated hardware secure key
+#define HARDWARE_SECURE_KEY                                                    \
+  "ARK-OS-9aaafa37077ee91e5df2f47a8e9e1564beecde1cc13b279f51d915bf8c746eb4"
+
+EFI_STATUS check_os_signature(EFI_HANDLE ImageHandle,
+                              EFI_SYSTEM_TABLE *SystemTable) {
+  // Conceptual hardware verified boot check
+  int has_key = 1;
+  int match = 1;
+
+  if (has_key) {
+    if (match) {
+      return EFI_SUCCESS;
+    } else {
+      return EFI_SECURITY_VIOLATION;
+    }
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+EFI_STATUS load_drm_module() {
+  // Conceptual DRM module loading
+  return EFI_SUCCESS;
+}
+
+static EFI_STATUS read_file_from_esp(EFI_HANDLE ImageHandle,
+                                     EFI_SYSTEM_TABLE *SystemTable,
+                                     CHAR16 *FileName, VOID **BufferOut,
+                                     UINTN *SizeOut) {
+  EFI_STATUS status;
+  EFI_LOADED_IMAGE *loaded_image = NULL;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs = NULL;
+  EFI_FILE_HANDLE root = NULL;
+  EFI_FILE_HANDLE file = NULL;
+
+  // 1. Get the LoadedImage protocol for the current bootloader
+  status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3,
+                             ImageHandle, &LoadedImageProtocol,
+                             (VOID **)&loaded_image);
+  if (EFI_ERROR(status))
+    return status;
+
+  // 2. Open the SimpleFileSystem protocol on the device handle of the loaded
+  // image
+  status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3,
+                             loaded_image->DeviceHandle, &FileSystemProtocol,
+                             (VOID **)&fs);
+  if (EFI_ERROR(status))
+    return status;
+
+  // 3. Open the volume
+  status = uefi_call_wrapper(fs->OpenVolume, 2, fs, &root);
+  if (EFI_ERROR(status))
+    return status;
+
+  // 4. Open the file
+  status = uefi_call_wrapper(root->Open, 5, root, &file, FileName,
+                             EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR(status)) {
+    uefi_call_wrapper(root->Close, 1, root);
+    return status;
+  }
+
+  // 5. Get file info to determine size
+  EFI_FILE_INFO *file_info = NULL;
+  UINTN info_size = 0;
+  status = uefi_call_wrapper(file->GetInfo, 4, file, &GenericFileInfo,
+                             &info_size, NULL);
+  if (status == EFI_BUFFER_TOO_SMALL) {
+    status = uefi_call_wrapper(SystemTable->BootServices->AllocatePool, 3,
+                               EfiLoaderData, info_size, (VOID **)&file_info);
+    if (EFI_ERROR(status)) {
+      uefi_call_wrapper(file->Close, 1, file);
+      uefi_call_wrapper(root->Close, 1, root);
+      return status;
+    }
+
+    status = uefi_call_wrapper(file->GetInfo, 4, file, &GenericFileInfo,
+                               &info_size, (VOID *)file_info);
+  }
+
+  if (EFI_ERROR(status)) {
+    if (file_info)
+      uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
+    uefi_call_wrapper(file->Close, 1, file);
+    uefi_call_wrapper(root->Close, 1, root);
+    return status;
+  }
+
+  UINTN file_size = file_info->FileSize;
+  uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
+
+  // 6. Allocate buffer for file contents using AllocatePages for large buffers
+  UINTN num_pages = (file_size + 4095) / 4096;
+  EFI_PHYSICAL_ADDRESS phys_buffer = 0;
+  status = uefi_call_wrapper(SystemTable->BootServices->AllocatePages, 4,
+                             AllocateAnyPages, EfiLoaderData, num_pages,
+                             &phys_buffer);
+  if (EFI_ERROR(status)) {
+    uefi_call_wrapper(file->Close, 1, file);
+    uefi_call_wrapper(root->Close, 1, root);
+    return status;
+  }
+  VOID *buffer = (VOID *)(UINTN)phys_buffer;
+
+  // 7. Read file contents
+  UINTN read_size = file_size;
+  status = uefi_call_wrapper(file->Read, 3, file, &read_size, buffer);
+  if (EFI_ERROR(status) || read_size != file_size) {
+    uefi_call_wrapper(SystemTable->BootServices->FreePages, 2, phys_buffer,
+                      num_pages);
+    uefi_call_wrapper(file->Close, 1, file);
+    uefi_call_wrapper(root->Close, 1, root);
+    return EFI_DEVICE_ERROR;
+  }
+
+  // 8. Clean up and return
+  uefi_call_wrapper(file->Close, 1, file);
+  uefi_call_wrapper(root->Close, 1, root);
+
+  *BufferOut = buffer;
+  *SizeOut = file_size;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
+  InitializeLib(ImageHandle, SystemTable);
+  EFI_STATUS status;
+
+  // 1. Locate the Graphics Output Protocol (GOP)
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
+  EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+  status = uefi_call_wrapper(SystemTable->BootServices->LocateProtocol, 3,
+                             &gop_guid, NULL, (VOID **)&gop);
+
+  UINTN center_x = 0;
+  UINTN center_y = 0;
+  UINTN anim_width = 200;
+  UINTN anim_height = 200;
+
+  // 2. Clear screen to black and display the white dot
+  if (!EFI_ERROR(status) && gop) {
+    EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
+    uefi_call_wrapper(gop->Blt, 10, gop, &black, EfiBltVideoFill, 0, 0, 0, 0,
+                      gop->Mode->Info->HorizontalResolution,
+                      gop->Mode->Info->VerticalResolution, 0);
+
+    center_x = (gop->Mode->Info->HorizontalResolution - anim_width) / 2;
+    center_y = (gop->Mode->Info->VerticalResolution - anim_height) / 2;
+
+    // Draw a 6x6 pixel white dot in the center of the 200x200 region
+    EFI_GRAPHICS_OUTPUT_BLT_PIXEL white = {255, 255, 255, 0};
+    uefi_call_wrapper(gop->Blt, 10, gop, &white, EfiBltVideoFill, 0, 0,
+                      center_x + 97, center_y + 97, 6, 6, 0);
+  }
+
+  // 3. Perform OS Key signature check and load DRM
+  status = check_os_signature(ImageHandle, SystemTable);
+  if (EFI_ERROR(status)) {
+    return status;
+  }
+  load_drm_module();
+
+  // 4. Resolve path and load the kernel image (bzImage)
+  EFI_LOADED_IMAGE *loaded_image = NULL;
+  status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3,
+                             ImageHandle, &LoadedImageProtocol,
+                             (VOID **)&loaded_image);
+  if (EFI_ERROR(status))
+    return status;
+
+  EFI_DEVICE_PATH *kernel_path =
+      FileDevicePath(loaded_image->DeviceHandle, L"\\EFI\\BOOT\\bzImage");
+  if (kernel_path == NULL)
+    return EFI_OUT_OF_RESOURCES;
+
+  EFI_HANDLE kernel_img = NULL;
+  status = uefi_call_wrapper(SystemTable->BootServices->LoadImage, 6, FALSE,
+                             ImageHandle, kernel_path, NULL, 0, &kernel_img);
+  if (EFI_ERROR(status))
+    return status;
+
+  // 5. Play the boot animation (expanding nucleus) from ESP
+  if (gop) {
+    VOID *anim_buffer = NULL;
+    UINTN anim_size = 0;
+    status = read_file_from_esp(ImageHandle, SystemTable,
+                                L"\\EFI\\BOOT\\animation.bin", &anim_buffer,
+                                &anim_size);
+    if (!EFI_ERROR(status)) {
+      UINTN num_frames = 60;
+      UINTN expected_size = num_frames * anim_width * anim_height *
+                            sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+
+      if (anim_size >= expected_size) {
+        // Clear the white dot to black first
+        EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
+        uefi_call_wrapper(gop->Blt, 10, gop, &black, EfiBltVideoFill, 0, 0, 0,
+                          0, gop->Mode->Info->HorizontalResolution,
+                          gop->Mode->Info->VerticalResolution, 0);
+
+        EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frames =
+            (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)anim_buffer;
+        for (UINTN f = 0; f < num_frames; f++) {
+          EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frame =
+              &frames[f * anim_width * anim_height];
+
+          uefi_call_wrapper(gop->Blt, 10, gop, frame, EfiBltBufferToVideo, 0, 0,
+                            center_x, center_y, anim_width, anim_height,
+                            anim_width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+          uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 16666);
+        }
+      }
+      uefi_call_wrapper(SystemTable->BootServices->FreePages, 2,
+                        (EFI_PHYSICAL_ADDRESS)(UINTN)anim_buffer,
+                        (anim_size + 4095) / 4096);
+    }
+  }
+
+  // 6. Set command line options for the kernel
+  EFI_LOADED_IMAGE *kernel_loaded_image = NULL;
+  status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3,
+                             kernel_img, &LoadedImageProtocol,
+                             (VOID **)&kernel_loaded_image);
+  if (EFI_ERROR(status))
+    return status;
+
+  CHAR16 *cmd_line =
+      L"initrd=\\EFI\\BOOT\\initramfs.img console=ttyS0 loglevel=0 logo.nologo "
+      L"init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0";
+  kernel_loaded_image->LoadOptions = cmd_line;
+  kernel_loaded_image->LoadOptionsSize =
+      (StrLen(cmd_line) + 1) * sizeof(CHAR16);
+
+  // 7. Start the kernel
+  UINTN exit_data_size = 0;
+  CHAR16 *exit_data = NULL;
+  status = uefi_call_wrapper(SystemTable->BootServices->StartImage, 3,
+                             kernel_img, &exit_data_size, &exit_data);
+
+  return status;
+}

+ 51 - 0
arkos/boot/source/bootloader.c.rej

@@ -0,0 +1,51 @@
+--- boot/source/bootloader.c
++++ boot/source/bootloader.c
+@@ -231,10 +231,14 @@
+         &LoadedImageProtocol,
+         (VOID **)&loaded_image
+     );
+-    if (EFI_ERROR(status)) return status;
++    if (EFI_ERROR(status)) {
++        Print(L"HandleProtocol LoadedImage error: %r\n", status);
++        uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 5000000);
++        return status;
++    }
+ 
+     EFI_DEVICE_PATH *kernel_path = FileDevicePath(loaded_image->DeviceHandle, L"\\EFI\\BOOT\\bzImage");
+-    if (kernel_path == NULL) return EFI_OUT_OF_RESOURCES;
++    if (kernel_path == NULL) { Print(L"Kernel path null\n"); return EFI_OUT_OF_RESOURCES; }
+ 
+     EFI_HANDLE kernel_img = NULL;
+     status = uefi_call_wrapper(
+@@ -247,7 +251,11 @@
+         0,
+         &kernel_img
+     );
+-    if (EFI_ERROR(status)) return status;
++    if (EFI_ERROR(status)) {
++        Print(L"LoadImage kernel error: %r\n", status);
++        uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 5000000);
++        return status;
++    }
+ 
+     // 5. Play the boot animation (expanding nucleus) from ESP
+     if (gop) {
+@@ -254,6 +262,9 @@
+         VOID *anim_buffer = NULL;
+         UINTN anim_size = 0;
+         status = read_file_from_esp(ImageHandle, SystemTable, L"\\EFI\\BOOT\\animation.bin", &anim_buffer, &anim_size);
++        if (EFI_ERROR(status)) {
++            Print(L"read_file_from_esp error: %r\n", status);
++        }
+         if (!EFI_ERROR(status)) {
+             UINTN num_frames = 60;
+             UINTN expected_size = num_frames * anim_width * anim_height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+@@ -293,6 +304,8 @@
+             }
+             uefi_call_wrapper(SystemTable->BootServices->FreePages, 2, (EFI_PHYSICAL_ADDRESS)(UINTN)anim_buffer, (anim_size + 4095) / 4096);
+         }
++    } else {
++        Print(L"GOP is NULL!\n");
+     }
+ 
+     // 6. Set command line options for the kernel

+ 1 - 1
arkos/boot/source/stage2.asm

@@ -329,7 +329,7 @@ animation_lba:        dd 0
 animation_size_sectors: dd 0
 lfb_addr:             dd 0
 screen_pitch:         dd 0
-cmd_line: db "console=tty0 loglevel=0 logo.nologo init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0", 0
+cmd_line: db "console=ttyS0 loglevel=0 logo.nologo init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0", 0
 
 align 4
 dap:

+ 81 - 14
arkos/frameworks/ArkGraphics/ArkGraphics.swift

@@ -3,9 +3,9 @@ import Foundation
 import Glibc
 #endif
 
-// ═══════════════════════════════════════════════════════════════════
+// -
 //  ArkGraphics — Display Client Library
-// ═══════════════════════════════════════════════════════════════════
+// -
 //  Client-side library that connects to the ArkOS Display Daemon
 //  via /dev/display.sock and sends rendering commands.
 //
@@ -20,9 +20,9 @@ import Glibc
 //    gfx.drawLine(x1: 10, y1: 10, x2: 200, y2: 200, r: 255, g: 255, b: 255)
 //    gfx.pan()  // Present to screen
 //
-// ═══════════════════════════════════════════════════════════════════
+// -
 
-// ── Wire Protocol ─────────────────────────────────────────────────
+// - Wire Protocol -
 
 /// Packed command structure sent to the display daemon.
 /// Total size: 21 bytes (1 + 4*4 + 4*1).
@@ -38,10 +38,14 @@ private struct DisplayCommand {
     var a: UInt8         // Alpha (0–255, unused by framebuffer)
 }
 
-// ── Graphics Client ───────────────────────────────────────────────
+// - Graphics Client -
 
 /// Client-side handle to the display daemon. Manages the socket
 /// connection and provides high-level drawing primitives.
+// C bridge to bypass varargs issues in Swift's ioctl binding
+@_silgen_name("ioctl")
+func ioctl_fb(_ fd: Int32, _ request: UInt, _ info: UnsafeMutableRawPointer) -> Int32
+
 public class ArkGraphics {
     /// File descriptor for the Unix domain socket connection.
     private var fd: Int32 = -1
@@ -52,13 +56,57 @@ public class ArkGraphics {
     /// Maximum connection retry attempts on initialization.
     private let maxRetries = 10
 
-    /// Delay between retry attempts (microseconds).
     private let retryDelay: useconds_t = 500_000 // 500ms
 
+    public var screenWidth: Int = 1024
+    public var screenHeight: Int = 768
+
     /// Creates a new graphics client and connects to the display daemon.
     /// Retries up to 10 times with 500ms delay (total 5s) to allow the
     /// daemon time to start during boot.
     public init() {
+        // Query real resolution from fb0
+        let fb_fd = open("/dev/fb0", O_RDONLY)
+        if fb_fd >= 0 {
+            // Memory layout of fb_var_screeninfo (ABI compatible with Linux)
+            struct fb_var_screeninfo {
+                var xres: UInt32 = 0
+                var yres: UInt32 = 0
+                var xres_virtual: UInt32 = 0
+                var yres_virtual: UInt32 = 0
+                var xoffset: UInt32 = 0
+                var yoffset: UInt32 = 0
+                var bits_per_pixel: UInt32 = 0
+                var grayscale: UInt32 = 0
+                var red: (UInt32, UInt32, UInt32) = (0,0,0)
+                var green: (UInt32, UInt32, UInt32) = (0,0,0)
+                var blue: (UInt32, UInt32, UInt32) = (0,0,0)
+                var transp: (UInt32, UInt32, UInt32) = (0,0,0)
+                var nonstd: UInt32 = 0
+                var activate: UInt32 = 0
+                var height: UInt32 = 0
+                var width: UInt32 = 0
+                var accel_flags: UInt32 = 0
+                var pixclock: UInt32 = 0
+                var left_margin: UInt32 = 0
+                var right_margin: UInt32 = 0
+                var upper_margin: UInt32 = 0
+                var lower_margin: UInt32 = 0
+                var hsync_len: UInt32 = 0
+                var vsync_len: UInt32 = 0
+                var sync: UInt32 = 0
+                var vmode: UInt32 = 0
+                var reserved: (UInt32, UInt32, UInt32, UInt32, UInt32, UInt32) = (0, 0, 0, 0, 0, 0)
+            }
+            var vinfo = fb_var_screeninfo()
+            let FBIOGET_VSCREENINFO: UInt = 0x4600
+            if ioctl_fb(fb_fd, FBIOGET_VSCREENINFO, &vinfo) >= 0 {
+                self.screenWidth = Int(vinfo.xres)
+                self.screenHeight = Int(vinfo.yres)
+            }
+            close(fb_fd)
+        }
+
         for attempt in 1...maxRetries {
             if tryConnect() {
                 return
@@ -74,7 +122,7 @@ public class ArkGraphics {
         if fd >= 0 { close(fd) }
     }
 
-    // ── Connection Management ─────────────────────────────────────
+    // - Connection Management -
 
     /// Attempts to connect to the display daemon socket.
     /// Returns true on success, false on failure.
@@ -114,7 +162,7 @@ public class ArkGraphics {
         return fd >= 0
     }
 
-    // ── Rendering Commands ────────────────────────────────────────
+    // - Rendering Commands -
 
     /// Fills a rectangle with a solid RGB color.
     ///
@@ -180,18 +228,37 @@ public class ArkGraphics {
         fillRectRGB(x: x + w - thickness, y: y, w: thickness, h: h, r: r, g: g, b: b)
     }
 
-    // ── Internal Transport ────────────────────────────────────────
+    // - Internal Transport -
 
     /// Sends a packed command struct to the display daemon.
     private func sendCommand(_ cmd: DisplayCommand) {
         guard fd >= 0 else { return }
 
-        var mutableCmd = cmd
-        withUnsafeBytes(of: &mutableCmd) { bytes in
+        var buffer = [UInt8](repeating: 0, count: 21)
+        buffer[0] = cmd.cmd
+        
+        var x = cmd.x
+        var y = cmd.y
+        var w = cmd.w
+        var h = cmd.h
+        
+        buffer.withUnsafeMutableBufferPointer { ptr in
+            guard let baseAddress = ptr.baseAddress else { return }
+            memcpy(baseAddress + 1, &x, 4)
+            memcpy(baseAddress + 5, &y, 4)
+            memcpy(baseAddress + 9, &w, 4)
+            memcpy(baseAddress + 13, &h, 4)
+        }
+        
+        buffer[17] = cmd.r
+        buffer[18] = cmd.g
+        buffer[19] = cmd.b
+        buffer[20] = cmd.a
+
+        buffer.withUnsafeBufferPointer { ptr in
             var totalWritten = 0
-            while totalWritten < bytes.count {
-                let written = write(fd, bytes.baseAddress! + totalWritten,
-                                    bytes.count - totalWritten)
+            while totalWritten < 21 {
+                let written = write(fd, ptr.baseAddress! + totalWritten, 21 - totalWritten)
                 if written <= 0 { break }
                 totalWritten += written
             }

+ 9 - 9
arkos/frameworks/SwiftUI/Sources/ui_test/main.swift

@@ -56,26 +56,26 @@ struct UITestApp {
 
         let graphics = ArkGraphics()
 
-        // 1. Sleek Background (Dark Gradient Approximation - just dark grey for now)
-        graphics.fillRectRGB(x: 0, y: 0, w: 1024, h: 768, r: 30, g: 30, b: 35)
+        // 1. Bright White Background so we know it's not a black screen!
+        graphics.fillRectRGB(x: 0, y: 0, w: 1024, h: 768, r: 255, g: 255, b: 255)
 
-        // 2. Draw "Get started" button (sleek rounded look simulation)
+        // 2. Draw "Get started" button (Bright Blue)
         let btn1W = 280
         let btn1H = 60
         let btn1X = (1024 - btn1W) / 2
         let btn1Y = 300
-        graphics.fillRectRGB(x: btn1X, y: btn1Y, w: btn1W, h: btn1H, r: 0, g: 120, b: 215)
+        graphics.fillRectRGB(x: btn1X, y: btn1Y, w: btn1W, h: btn1H, r: 0, g: 122, b: 255)
         
-        // 3. Draw "Start ->" button (sleek secondary button)
+        // 3. Draw "Start ->" button (Green)
         let btn2W = 280
         let btn2H = 60
         let btn2X = (1024 - btn2W) / 2
         let btn2Y = 400
-        graphics.fillRectRGB(x: btn2X, y: btn2Y, w: btn2W, h: btn2H, r: 50, g: 50, b: 60)
+        graphics.fillRectRGB(x: btn2X, y: btn2Y, w: btn2W, h: btn2H, r: 52, g: 199, b: 89)
 
-        // Draw Text!
-        drawText(graphics, "Get started", x: btn1X + 45, y: btn1Y + 18, size: 3, r: 255, g: 255, b: 255)
-        drawText(graphics, "Start ->", x: btn2X + 65, y: btn2Y + 18, size: 3, r: 255, g: 255, b: 255)
+        // Draw Text! (Black text)
+        drawText(graphics, "Get started", x: btn1X + 45, y: btn1Y + 18, size: 3, r: 0, g: 0, b: 0)
+        drawText(graphics, "Start ->", x: btn2X + 65, y: btn2Y + 18, size: 3, r: 0, g: 0, b: 0)
 
         graphics.pan()
         print("ui_test: UI Layout mapped and sent to Display Daemon.")

+ 0 - 0
arkos/ovmf.log


+ 18 - 0
arkos/run_qemu.sh

@@ -0,0 +1,18 @@
+#!/bin/bash
+qemu-system-x86_64 \
+    -drive if=pflash,format=raw,readonly=on,file=/usr/share/ovmf/OVMF.fd \
+    -m 2048 \
+    -cpu host \
+    -enable-kvm \
+    -drive file=finished/boot.img,format=raw,index=0,media=disk \
+    -drive file=finished/sys.img,format=raw,index=1,media=disk \
+    -drive file=finished/vend.img,format=raw,index=2,media=disk \
+    -serial stdio \
+    -vga virtio \
+    -monitor unix:qemu-monitor.sock,server,nowait \
+    -display none &
+QEMU_PID=$!
+sleep 5
+echo "screendump qemu-screen.png" | nc -U qemu-monitor.sock
+sleep 1
+kill $QEMU_PID

+ 12 - 12
arkos/system/apps/ui_test.swift

@@ -133,20 +133,20 @@ func drawText(_ graphics: ArkGraphics, _ text: String,
 
 // ── Screen Constants ──────────────────────────────────────────────
 
-let SCREEN_W = 1024
-let SCREEN_H = 768
+// Dynamic resolution uses graphics.screenWidth and graphics.screenHeight
 
 // ── Status Bar ────────────────────────────────────────────────────
 
 /// Draws a thin status bar at the top of the screen showing
 /// system info (OS name, time placeholder, network status).
 func drawStatusBar(_ graphics: ArkGraphics) {
+    let screenW = graphics.screenWidth
     // Status bar background (dark translucent)
-    graphics.fillRectRGB(x: 0, y: 0, w: SCREEN_W, h: 28,
+    graphics.fillRectRGB(x: 0, y: 0, w: screenW, h: 28,
                          r: 20, g: 20, b: 25)
 
     // Separator line
-    graphics.fillRectRGB(x: 0, y: 28, w: SCREEN_W, h: 1,
+    graphics.fillRectRGB(x: 0, y: 28, w: screenW, h: 1,
                          r: 60, g: 60, b: 70)
 
     // OS name (left side)
@@ -154,7 +154,7 @@ func drawStatusBar(_ graphics: ArkGraphics) {
              r: 180, g: 180, b: 200)
 
     // Network status indicator (right side)
-    drawText(graphics, "10.0.2.15", x: SCREEN_W - 180, y: 8, size: 2,
+    drawText(graphics, "10.0.2.15", x: screenW - 180, y: 8, size: 2,
              r: 120, g: 200, b: 120)
 }
 
@@ -190,7 +190,7 @@ struct SetupApp {
         // Subtle gradient effect (lighter at top)
         for i in 0..<100 {
             let intensity = UInt8(max(0, 35 - i / 3))
-            graphics.fillRectRGB(x: 0, y: i, w: SCREEN_W, h: 1,
+            graphics.fillRectRGB(x: 0, y: i, w: graphics.screenWidth, h: 1,
                                  r: intensity, g: intensity, b: intensity + 5)
         }
 
@@ -199,18 +199,18 @@ struct SetupApp {
 
         // ── 3. Welcome Text ───────────────────────────────────────
         drawText(graphics, "Welcome to ArkOS",
-                 x: (SCREEN_W - 16 * 6 * 3) / 2, y: 200, size: 3,
+                 x: (graphics.screenWidth - 16 * 6 * 3) / 2, y: 200, size: 3,
                  r: 240, g: 240, b: 245)
 
         // Subtitle
-        drawText(graphics, "Your OS is ready",
-                 x: (SCREEN_W - 16 * 6 * 2) / 2, y: 250, size: 2,
+        drawText(graphics, "The Modern Display Stack",
+                 x: (graphics.screenWidth - 16 * 6 * 2) / 2, y: 250, size: 2,
                  r: 140, g: 140, b: 160)
 
         // ── 4. "Get started" Button ───────────────────────────────
         let btn1W = 280
         let btn1H = 54
-        let btn1X = (SCREEN_W - btn1W) / 2
+        let btn1X = (graphics.screenWidth - btn1W) / 2
         let btn1Y = 340
 
         // Button background (accent blue)
@@ -228,7 +228,7 @@ struct SetupApp {
         // ── 5. "Start ->" Button ──────────────────────────────────
         let btn2W = 280
         let btn2H = 54
-        let btn2X = (SCREEN_W - btn2W) / 2
+        let btn2X = (graphics.screenWidth - btn2W) / 2
         let btn2Y = 420
 
         // Button background (subtle dark)
@@ -245,7 +245,7 @@ struct SetupApp {
 
         // ── 6. Version Info ───────────────────────────────────────
         drawText(graphics, "ArkOS v0.0.1",
-                 x: (SCREEN_W - 12 * 6 * 2) / 2, y: SCREEN_H - 40, size: 2,
+                 x: (graphics.screenWidth - 12 * 6 * 2) / 2, y: graphics.screenHeight - 40, size: 2,
                  r: 80, g: 80, b: 100)
 
         // ── 7. Present to Screen ──────────────────────────────────

+ 9 - 2
arkos/system/core/init.c

@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
@@ -188,13 +189,19 @@ int main(void) {
 
     /*
      * Phase 4: Hide kernel boot messages and prepare display
+     * - Set terminal to KD_GRAPHICS to prevent fbcon from interfering
      * - Set terminal background to black
      * - Clear the screen
      * - Hide the cursor
      * This prevents the white flash between kernel boot and splash screen.
      */
-    printf("\033[0;40m\033[2J\033[H\033[?25l");
-    fflush(stdout);
+    int tty_fd = open("/dev/tty0", O_RDWR);
+    if (tty_fd >= 0) {
+        /* Clear screen and hide cursor on the physical display */
+        write(tty_fd, "\033[0;40m\033[2J\033[H\033[?25l", 20);
+        ioctl(tty_fd, 0x4B3A, 1); /* KDSETMODE, KD_GRAPHICS */
+        close(tty_fd);
+    }
 
     /*
      * Phase 5: Verified Boot

+ 21 - 23
arkos/system/display/main.swift

@@ -3,9 +3,9 @@ import Foundation
 import Glibc
 #endif
 
-// ═══════════════════════════════════════════════════════════════════
+// -
 //  ArkOS Display Daemon (ui_daemon)
-// ═══════════════════════════════════════════════════════════════════
+// -
 //  The display compositor daemon that owns the Linux framebuffer
 //  (/dev/fb0) and exposes a Unix domain socket for rendering commands.
 //
@@ -26,9 +26,9 @@ import Glibc
 //    [r: UInt8][g: UInt8][b: UInt8][a: UInt8]
 //    Total: 21 bytes per command
 //
-// ═══════════════════════════════════════════════════════════════════
+// -
 
-// ── Framebuffer Structure Definitions ─────────────────────────────
+// - Framebuffer Structure Definitions -
 // These mirror the Linux kernel's fb_var_screeninfo and fb_fix_screeninfo
 // structures. They must exactly match the kernel ABI for ioctl calls.
 
@@ -87,7 +87,7 @@ struct fb_fix_screeninfo {
     var reserved: (UInt16, UInt16, UInt16) = (0, 0, 0)
 }
 
-// ── C Bridge Functions (defined in fb_helper.c) ───────────────────
+// - C Bridge Functions (defined in fb_helper.c) -
 
 @_silgen_name("get_vinfo")
 func get_vinfo(_ fd: Int32, _ vinfo: UnsafeMutableRawPointer) -> Int32
@@ -104,7 +104,7 @@ func set_vinfo(_ fd: Int32, _ vinfo: UnsafeMutableRawPointer) -> Int32
 @_silgen_name("blank_display")
 func blank_display(_ fd: Int32, _ mode: Int32) -> Int32
 
-// ── Command Constants ─────────────────────────────────────────────
+// - Command Constants -
 
 /// Display protocol command identifiers.
 private enum DisplayCmd: UInt8 {
@@ -113,7 +113,7 @@ private enum DisplayCmd: UInt8 {
     case clear    = 3  // Clear the entire screen to a color
 }
 
-// ── Framebuffer State ─────────────────────────────────────────────
+// - Framebuffer State -
 
 /// Global framebuffer state, initialized once at startup.
 var fbp: UnsafeMutablePointer<UInt8>!  // Memory-mapped framebuffer pointer
@@ -125,7 +125,7 @@ var fbFd: Int32 = -1                    // /dev/fb0 file descriptor
 var vinfo = fb_var_screeninfo()         // Current video mode info
 var screenSize: Int = 0                 // Total framebuffer size in bytes
 
-// ── Drawing Primitives ────────────────────────────────────────────
+// - Drawing Primitives -
 
 /// Fills a rectangle in the framebuffer with the specified RGB color.
 /// Coordinates are clamped to screen bounds to prevent buffer overflows.
@@ -161,7 +161,7 @@ func clearScreen(r: UInt8, g: UInt8, b: UInt8) {
     }
 }
 
-// ── Framebuffer Initialization ────────────────────────────────────
+// - Framebuffer Initialization -
 
 /// Opens /dev/fb0, queries the video mode, and maps the framebuffer
 /// into process memory. Returns true on success.
@@ -196,24 +196,18 @@ func initFramebuffer() -> Bool {
 
     print("ui_daemon: Framebuffer: \(scrW)x\(scrH) @ \(bpp * 8)bpp, line=\(lineLen), size=\(screenSize)")
 
-    // Map the framebuffer into our address space
-    let fb_ptr = mmap(nil, screenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fbFd, 0)
-    if fb_ptr == MAP_FAILED {
-        print("ui_daemon: mmap failed: \(String(cString: strerror(errno)))")
-        close(fbFd)
-        return false
-    }
-    fbp = fb_ptr!.bindMemory(to: UInt8.self, capacity: screenSize)
+    // Allocate back buffer instead of mmap
+    fbp = UnsafeMutablePointer<UInt8>.allocate(capacity: screenSize)
 
-    // Clear screen to black
     clearScreen(r: 0, g: 0, b: 0)
-    _ = pan_display(fbFd, &vinfo)
+    lseek(fbFd, 0, SEEK_SET)
+    write(fbFd, fbp, screenSize)
 
     print("ui_daemon: Framebuffer initialized successfully")
     return true
 }
 
-// ── Socket Server ─────────────────────────────────────────────────
+// - Socket Server -
 
 /// Starts the display server socket, accepting client connections
 /// and processing rendering commands.
@@ -265,7 +259,7 @@ func startServer() {
     }
 }
 
-// ── Client Command Handler ────────────────────────────────────────
+// - Client Command Handler -
 
 /// Reads and processes rendering commands from a single client connection.
 /// Command format: 21 bytes packed (cmd + x + y + w + h + r + g + b + a).
@@ -309,7 +303,8 @@ func handleClient(_ clientFd: Int32) {
 
         case .pan:
             // Page flip — present the current buffer to screen
-            _ = pan_display(fbFd, &vinfo)
+            lseek(fbFd, 0, SEEK_SET)
+            write(fbFd, fbp, screenSize)
 
         case .clear:
             // Clear screen to the specified color
@@ -321,11 +316,14 @@ func handleClient(_ clientFd: Int32) {
     }
 }
 
-// ── Entry Point ───────────────────────────────────────────────────
+// - Entry Point -
 
 print("ui_daemon: ArkOS Display Daemon starting...")
 
 if initFramebuffer() {
+    print("ui_daemon: Drawing boot splash...")
+    drawSwiftSplash(fbp: fbp, scrW: scrW, scrH: scrH, lineLen: lineLen, bpp: bpp)
+    print("ui_daemon: Starting compositor server...")
     startServer()
 } else {
     print("ui_daemon: FATAL — Failed to initialize framebuffer")

+ 25 - 114
arkos/system/swift_splash.swift → arkos/system/display/splash.swift

@@ -3,75 +3,11 @@ import Foundation
 import Glibc
 #endif
 
-// ── Framebuffer structs ──
 
-struct fb_bitfield {
-    var offset: UInt32 = 0
-    var length: UInt32 = 0
-    var msb_right: UInt32 = 0
-}
-
-struct fb_var_screeninfo {
-    var xres: UInt32 = 0
-    var yres: UInt32 = 0
-    var xres_virtual: UInt32 = 0
-    var yres_virtual: UInt32 = 0
-    var xoffset: UInt32 = 0
-    var yoffset: UInt32 = 0
-    var bits_per_pixel: UInt32 = 0
-    var grayscale: UInt32 = 0
-    var red: fb_bitfield = fb_bitfield()
-    var green: fb_bitfield = fb_bitfield()
-    var blue: fb_bitfield = fb_bitfield()
-    var transp: fb_bitfield = fb_bitfield()
-    var nonstd: UInt32 = 0
-    var activate: UInt32 = 0
-    var height: UInt32 = 0
-    var width: UInt32 = 0
-    var accel_flags: UInt32 = 0
-    var pixclock: UInt32 = 0
-    var left_margin: UInt32 = 0
-    var right_margin: UInt32 = 0
-    var upper_margin: UInt32 = 0
-    var lower_margin: UInt32 = 0
-    var hsync_len: UInt32 = 0
-    var vsync_len: UInt32 = 0
-    var sync: UInt32 = 0
-    var vmode: UInt32 = 0
-    var reserved: (UInt32, UInt32, UInt32, UInt32, UInt32, UInt32) = (0, 0, 0, 0, 0, 0)
-}
-
-struct fb_fix_screeninfo {
-    var id: (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8,
-             Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8) =
-        (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
-    var smem_start: UInt = 0
-    var smem_len: UInt32 = 0
-    var type: UInt32 = 0
-    var type_aux: UInt32 = 0
-    var visual: UInt32 = 0
-    var xpanstep: UInt16 = 0
-    var ypanstep: UInt16 = 0
-    var ywrapstep: UInt16 = 0
-    var line_length: UInt32 = 0
-    var mmio_start: UInt = 0
-    var mmio_len: UInt32 = 0
-    var accel: UInt32 = 0
-    var reserved: (UInt16, UInt16, UInt16) = (0, 0, 0)
-}
-
-@_silgen_name("get_vinfo")
-func get_vinfo(_ fd: Int32, _ vinfo: UnsafeMutableRawPointer) -> Int32
-
-@_silgen_name("get_finfo")
-func get_finfo(_ fd: Int32, _ finfo: UnsafeMutableRawPointer) -> Int32
-
-@_silgen_name("pan_display")
-func pan_display(_ fd: Int32, _ vinfo: UnsafeMutableRawPointer) -> Int32
 
-// ══════════════════════════════════════════════════════════════════
+// -
 //  Anti-Aliased High-Resolution Back-Buffered Renderer
-// ══════════════════════════════════════════════════════════════════
+// -
 
 let AW = 600
 let AH = 600
@@ -177,7 +113,7 @@ func blit(_ src: UnsafeMutablePointer<UInt8>,
           _ fbp: UnsafeMutablePointer<UInt8>,
           _ sx: Int, _ sy: Int,
           _ lineLen: Int, _ scrH: Int,
-          _ fd: Int32, _ vinfo: UnsafeMutableRawPointer) {
+          _ fd: Int32, _ scrSz: Int) {
     for y in 0..<AH {
         let fy = sy + y
         if fy < 0 || fy >= scrH { continue }
@@ -185,10 +121,11 @@ func blit(_ src: UnsafeMutablePointer<UInt8>,
                src + y * AW * 4,
                AW * 4)
     }
-    _ = pan_display(fd, vinfo)
+    lseek(fd, 0, SEEK_SET)
+    write(fd, fbp, scrSz)
 }
 
-// ── Isolated IPC Client (talks to arkrt daemon) ──
+// - Isolated IPC Client (talks to arkrt daemon) -
 
 func queryIPC(cmdId: UInt16, payload: String = "") -> String {
     let fd = socket(AF_UNIX, 1, 0)
@@ -253,30 +190,11 @@ func queryIPC(cmdId: UInt16, payload: String = "") -> String {
     return "INVALID_DATA"
 }
 
-// ══════════════════════════════════════════════════════════════════
+// -
 
-func drawSwiftSplash() {
-    let fd = open("/dev/fb0", O_RDWR)
-    if fd < 0 { print("Error: Cannot open /dev/fb0"); return }
-
-    var vinfo = fb_var_screeninfo()
-    if get_vinfo(fd, &vinfo) < 0 { close(fd); return }
-
-    var finfo = fb_fix_screeninfo()
-    if get_finfo(fd, &finfo) < 0 { close(fd); return }
-
-    let scrW    = Int(vinfo.xres)
-    let scrH    = Int(vinfo.yres)
-    let bpp     = Int(vinfo.bits_per_pixel) / 8
-    let lineLen = Int(finfo.line_length)
-    let scrSz   = Int(finfo.smem_len)
-
-    let fb_ptr = mmap(nil, scrSz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
-    if fb_ptr == MAP_FAILED { close(fd); return }
-    let fbp = fb_ptr!.bindMemory(to: UInt8.self, capacity: scrSz)
-
-    // ── Clear entire screen to BLACK immediately ──
-    memset(fbp, 0, scrSz)
+func drawSwiftSplash(fbp: UnsafeMutablePointer<UInt8>, scrW: Int, scrH: Int, lineLen: Int, bpp: Int) {
+    // - Clear entire screen to BLACK immediately -
+    memset(fbp, 0, scrH * lineLen)
 
     // Allocate raw pointer buffers
     let tpl  = UnsafeMutablePointer<UInt8>.allocate(capacity: ABUFSZ)  // template
@@ -286,11 +204,11 @@ func drawSwiftSplash() {
     let sx = (scrW - AW) / 2
     let sy = (scrH - AH) / 2
 
-    // ── Pre-render static nucleus template ──
+    // - Pre-render static nucleus template -
     memset(tpl, 0, ABUFSZ)
     diskAA(tpl, Double(AC), Double(AC), Double(NUC_R), 255)
 
-    // ── Phase 1: Spawn & Orbit Expansion (35 frames) ──
+    // - Phase 1: Spawn & Orbit Expansion (35 frames) -
     for frame in 0..<35 {
         memset(work, 0, ABUFSZ)
         
@@ -327,17 +245,17 @@ func drawSwiftSplash() {
             diskAA(work, ex, ey, curElR, 255)
         }
         
-        blit(work, fbp, sx, sy, lineLen, scrH, fd, &vinfo)
+        blit(work, fbp, sx, sy, lineLen, scrH, fbFd, screenSize)
         usleep(16666)
     }
 
-    // ── Pre-render static stable orbit template for Phase 2 ──
+    // - Pre-render static stable orbit template for Phase 2 -
     memset(tpl, 0, ABUFSZ)
     diskAA(tpl, Double(AC), Double(AC), Double(NUC_R), 255)
     ringAA(tpl, Double(AC), Double(AC), Double(INNER_R), RING_T, 60)
     ringAA(tpl, Double(AC), Double(AC), Double(OUTER_R), RING_T, 60)
 
-    // ── Phase 2: Stable Orbiting (150 frames ≈ 2.5 seconds at 60fps) ──
+    // - Phase 2: Stable Orbiting (150 frames ≈ 2.5 seconds at 60fps) -
     for frame in 0..<150 {
         memcpy(work, tpl, ABUFSZ)
         
@@ -357,11 +275,11 @@ func drawSwiftSplash() {
             diskAA(work, ex, ey, Double(ELEC_R), 255)
         }
         
-        blit(work, fbp, sx, sy, lineLen, scrH, fd, &vinfo)
+        blit(work, fbp, sx, sy, lineLen, scrH, fbFd, screenSize)
         usleep(16666)
     }
 
-    // ── Phase 3: Spiral Inward & Crash (30 frames) ──
+    // - Phase 3: Spiral Inward & Crash (30 frames) -
     let baseAngle = (35.0 * 0.10) + (150.0 * 0.05)
     for frame in 0..<30 {
         memset(work, 0, ABUFSZ)
@@ -398,11 +316,11 @@ func drawSwiftSplash() {
             }
         }
         
-        blit(work, fbp, sx, sy, lineLen, scrH, fd, &vinfo)
+        blit(work, fbp, sx, sy, lineLen, scrH, fbFd, screenSize)
         usleep(16666)
     }
 
-    // ── Phase 4: Flash & Fade to Black (20 frames) ──
+    // - Phase 4: Flash & Fade to Black (20 frames) -
     let finalNucG = Double(NUC_R) + 20.0
     for frame in 0..<20 {
         memset(work, 0, ABUFSZ)
@@ -412,23 +330,16 @@ func drawSwiftSplash() {
         if bright > 0 {
             diskAA(work, Double(AC), Double(AC), flashR, bright)
         }
-        blit(work, fbp, sx, sy, lineLen, scrH, fd, &vinfo)
+        blit(work, fbp, sx, sy, lineLen, scrH, fbFd, screenSize)
         usleep(16666)
     }
 
-    // ── Clear to BLACK ──
-    memset(fbp, 0, scrSz)
-    _ = pan_display(fd, &vinfo)
+    // - Clear to BLACK -
+    memset(fbp, 0, screenSize)
+    lseek(fbFd, 0, SEEK_SET)
+    write(fbFd, fbp, screenSize)
 
     tpl.deallocate()
     work.deallocate()
-    munmap(fb_ptr, scrSz)
-    close(fd)
-
-    // Hand over control to ui_test (via ui_daemon) by just hanging here silently
-    while true {
-        usleep(500_000)
-    }
+    // Done with splash
 }
-
-drawSwiftSplash()

+ 0 - 1
arkos/test.swift

@@ -1 +0,0 @@
-import ark.ui.basic

BIN
tools/build


+ 1 - 1
tools/build.c

@@ -373,7 +373,7 @@ int main(int argc, char *argv[]) {
              initramfs_ext);
     run(cmd);
 
-    snprintf(cmd, sizeof(cmd), "cd %s && zcat %s | cpio -id 2>/dev/null",
+    snprintf(cmd, sizeof(cmd), "cd %s && zcat %s | cpio -id --no-preserve-owner 2>/dev/null",
              initramfs_ext, base_initramfs);
     run(cmd);