arkos_architecture_guide.md 35 KB

ArkOS: Comprehensive System Architecture & Implementation Guide

This guide documents the technical details of the ArkOS system boot flow, signature verification pipeline, the arkrt monolithic system services framework, the isolated Main User UI (swift_splash), and the Unix Domain Socket IPC communication layer.


1. System Boot Flow

The ArkOS boot sequence traverses multiple stages of execution, beginning with the boot sector and ending with the isolated user space application:

graph TD
    A[Bootloader Sector 1] -->|Loads Stage 2| B[Stage 2 Bootloader]
    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[ui_daemon]
    F -->|Unix Domain Socket IPC| E

Stage 1: Bootloader Sector 1

  • File: bootloader.asm
  • Purpose: A standard 512-byte x86 Master Boot Record (MBR) loaded by the BIOS at address 0x7C00. It initializes segment registers, sets up a temporary stack, and loads the larger Stage 2 bootloader from disk sectors into memory before transferring control.

Stage 2: Bootloader Stage 2

  • File: stage2.asm
  • Purpose: Initializes protected mode, sets up the Global Descriptor Table (GDT), configures VESA BIOS Extensions (VBE) for graphics modesetting, and passes control to the Linux kernel.
  • Boot Parameters: Configured with console=tty0 logo.nologo quiet to prevent the kernel from dumping device detection and mode initialization text, ensuring a seamless visual transition to the screen clear.

Stage 3: Userspace Initialization (PID 1)

  • File: init.c
  • Purpose: Executed by the Linux kernel as the first userspace process (PID 1).
    • Mounts virtual filesystems: /proc, /sys, and /dev (via mount syscalls).
    • Performs a quiet signature verification of the arkrt daemon executable.
    • Spawns the arkrt process via fork() and execve().
    • Enters a loop waiting for the daemon. If the daemon crashes, it hangs to prevent a kernel panic.

2. Verified Boot Signature Check

ArkOS enforces a secure verified boot mechanism for its user space services.

Signature Key & Generation

  • Compiler/Signer: build.c / sign.py
  • Mechanism:
    • During compilation, build.c compiles the arkrt binary.
    • The signing tool hashes the compiled arkrt executable using SHA-256.
    • It encrypts/signs the hash using the Verified Boot secure build key to generate signature.bin.
    • The hardcoded verification key ARK-OS-... is injected directly into init.c as a macro ARK_KEY.

Verification Step (Inside init.c)

  • Before launching /arkrt, init.c reads the contents of /arkrt and computes its SHA-256 checksum.
  • It compares the checksum against the signature verification key.
  • If the signature is correct, it prints [OK] (silenced to keep the boot quiet) and executes the daemon. If it fails, the boot sequence halts.

3. The arkrt Monolithic System Service Framework

The arkrt service manager acts as the core system daemon of ArkOS, running as a privileged background process.

  • Component Location: arkrt/
  • Core Architecture Components:

Kernel & Hardware Bridge (KernelBridge.swift)

  • Memory Tracking: Calls the Linux getrusage API with 0 (RUSAGE_SELF) to read the resident set size (ru_maxrss) dynamically and verify that idle consumption does not cross the 2.0 GB RAM cap.
  • Resource Controller: Enforces thread execution boundaries on the 2-core CPU configuration by dispatching async operations to a designated, restricted thread pool.
  • Log Manager: Manages an in-memory, non-blocking circular buffer of system logs. Features a thread-safe lock-free mechanism to allow logging from concurrent threads.
  • Power Management: Scans /sys/class/power_supply dynamically to locate the battery subsystem node (e.g. BAT0, BAT1), parses the capacity percentage file, and triggers system shutdown via a wrapper calling the Linux C symbol reboot with LINUX_REBOOT_CMD_POWER_OFF (0x4321fedc).
  • Network Interface Manager: Scans /sys/class/net to query interface names, and queries getifaddrs from libc to dynamically parse IPv4 address buffers of active networks (filtering out loopback devices).

Unix Domain Socket IPC (IPC.swift)

  • Binds a Unix Domain Socket at /dev/arkrt.sock using static handlers.
  • Listens for connections in a concurrent dispatch queue managed by the Resource Controller thread pool.
  • Enforces an autoreleasepool block around connection cycles on Linux to guarantee that intermediate structures allocated during socket operations are immediately reclaimed.

Command Router (CommandRouter.swift)

  • Interprets and processes requests from the UI using a zero-copy parsing structure.
  • Matches and extracts parameters via UnsafeRawBufferPointer to route request codes to their corresponding Swift namespace handlers under the ark.system API layer.

4. IPC Binary Protocol Specification

Communication between the isolated UI and arkrt uses a strict binary packet structure. This eliminates JSON/string serialization parsing overhead and ensures high performance.

Packet Frame Layout

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       Command ID (2 Bytes)    |      Payload Length (4 Bytes)  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Payload Data (N Bytes)                  |
|                               ...                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1. Command ID (UInt16): The numeric code representing the system call command (sent big-endian).
  2. Payload Length (UInt32): The size of the payload following the header in bytes (sent big-endian).
  3. Payload Data: Raw UTF-8 bytes of the parameter or returned data.

Supported Command ID Reference

Command ID Command Name Description Response Format
101 CMD_GET_TIME Retrieve system formatted time UTF-8 String (e.g., Jul 5, 2026 at 10:12:00 AM)
102 CMD_GET_IP Query active interface IP UTF-8 String (e.g., 10.0.2.15 / 127.0.0.1)
103 CMD_GET_BATTERY Query battery level percentage UTF-8 String (e.g., 98%)
104 CMD_GET_BLUETOOTH Query Bluetooth device status UTF-8 String (ACTIVE or INACTIVE)
105 CMD_SHUTDOWN Shutdown the OS UTF-8 String (SHUTTING_DOWN)
106 CMD_DUMP_LOGS Retrieve circular buffer logs Newline-separated UTF-8 Log String

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. 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.
  • Maps the screen memory to userspace using a shared pointer (mmap).
  • Pre-allocates a global renderBuffer which serves as the back-buffer for all drawing operations (including shapes, text, and UI components).
  • Draws anti-aliased geometries and high-resolution text directly into renderBuffer first, then calls a custom memcpy to synchronize the back-buffer to the screen framebuffer. This entirely eliminates visual stutter, vertical tearing, and mouse pointer artifacting.

High-Resolution AA Algorithms

  • Filled Disk AA (diskAA): Draws a filled circle at a coordinate $(cx, cy)$ with radius $r$. It computes pixel distances and applies linear opacity interpolation on the edges: $$\alpha = r_{\text{outer}} - d$$ Ensuring smooth, anti-aliased circular corners.
  • Ring AA (ringAA): Draws a hollow outline of a circle by evaluating whether the pixel falls on the inner or outer border limits, interpolating transparency symmetrically around the center radius.

C-Based Optimized 4K Typography

  • High-resolution text scaling (up to 6x, e.g. 192x192 pixels per character) is supported via a custom font generation pipeline (tools/font_gen.py).
  • Rather than overloading the Swift compiler with massive array literals (which leads to Out-Of-Memory/Timeout build failures), the font data is generated as an optimized static C array (ArkFontRobotoBoldData.c).
  • Swift directly links and accesses this C-array memory without copying, enabling ultra-fast, zero-overhead font mapping at crisp 4K resolutions.

Isolated IPC Query Loop

Once the splash screen animation completes, the UI launches an IPC client:

  • Connects to the Unix socket /dev/arkrt.sock.
  • Sends binary header requests for system statistics.
  • Parses the incoming response payloads zero-copy using UnsafeRawBufferPointer.
  • Prints the formatted statistics onto the screen's canvas.

6. Comprehensive File Tree & Implementation Status

The ArkOS repository contains a mix of fully implemented core systems and placeholder directories reserved for future user space applications, UI elements, and hardware abstraction layers. The following section maps out each component, detailing its operational mechanics and current integration status without visual markers.

Boot & Kernel Operations

  • boot/ [Status: Fully Implemented]
    • Mechanics: This directory controls the initial power-on sequence. It contains bootloader.asm and stage2.asm for x86 architecture boot processes, alongside bootloader.c for UEFI systems. The loaders initialize memory, set up the Global Descriptor Table (GDT), and transition the system into protected mode before handing execution over to the Linux kernel. It also contains rules for packing the initramfs.
    • animationframes/: Houses the pre-rendered binary frames (frame_000.bin to frame_099.bin) used specifically for the Atom boot animation sequence executed during stage transitions.
  • kernel/ [Status: Fully Implemented]
    • Mechanics: Contains the Linux kernel source tree. This kernel has been heavily patched and configured strictly for ArkOS to support specialized IPC, customized display framebuffer handling, and rigid resource control restrictions that tie into arkrt.

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.
    • 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]
    • Mechanics: The central monolithic Ark Runtime daemon. Written in Swift, it contains KernelBridge.swift for hardware telemetry (reading /sys/class/power_supply and network interfaces), IPC.swift for binding the /dev/arkrt.sock Unix domain socket, and CommandRouter.swift for interpreting binary protocol payloads from user space. It effectively orchestrates process management, memory tracking, and all privileged operations.

Frameworks & UI Architecture

  • frameworks/

    • Swift/ [Status: Fully Implemented]: Contains the precompiled Swift runtime and standard libraries required for statically linking Swift code in environments where dynamic loading is either restricted or unavailable.
    • 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.

      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.

Build Orchestration & Image Assembly

  • tools/ [Status: Fully Implemented]
    • Mechanics: Contains the build.c orchestrator. This highly customized C program manages the compilation pipeline. It utilizes incremental compilation techniques (cp -ur) and Swift Package Manager's caching layers to assemble the Swift UI framework rapidly. It ultimately packs the rootfs, kernel, and initial ramdisk into standard .img files.
  • out_staging/ [Status: Fully Implemented]
    • Mechanics: The scratchpad directory generated dynamically during the make build cycle. All intermediate object files, static libraries, and .swift_build artifacts are housed here before final assembly.
  • finished/ [Status: Fully Implemented]
    • Mechanics: The final output destination where the bootable disk images (sys.img, vend.img, boot.img) are deployed, ready to be flashed to physical media or booted in an emulator.

7. Deep Dive: Line-by-Line Code Execution & Output Analysis

This section explores the fundamental lines of code orchestrating ArkOS, examining what each block executes, its interactions with the kernel, and the exact outputs produced at runtime.

7.1. Stage 1 Bootloader: bootloader.asm

The Stage 1 bootloader operates in 16-bit real mode. It is precisely 512 bytes, residing in the Master Boot Record (MBR).

Segment Initialization & Stack Setup

[BITS 16]
[ORG 0x7C00]

start:
    cli                     ; Disable interrupts while setting up segments
    xor ax, ax              ; Zero out AX register
    mov ds, ax              ; Data Segment = 0
    mov es, ax              ; Extra Segment = 0
    mov ss, ax              ; Stack Segment = 0
    mov sp, 0x7C00          ; Stack pointer starts at 0x7C00 (grows downwards)
    sti                     ; Re-enable interrupts

Execution & Output: When the BIOS hands over control, it jumps to 0x7C00. The cli command disables interrupts to prevent the CPU from handling hardware events while memory boundaries are undefined. Setting DS, ES, and SS to zero ensures all memory addressing is absolute relative to 0x0000. The stack pointer is placed exactly at 0x7C00 (right below our bootloader code) so stack push operations won't overwrite the bootloader. Output: Silent memory configuration.

Disk Reading (INT 13h)

load_stage2:
    mov ah, 0x02            ; BIOS Read Sector function
    mov al, 16              ; Number of sectors to read (16 sectors = 8KB)
    mov ch, 0               ; Cylinder 0
    mov cl, 2               ; Sector 2 (Sector 1 is this MBR)
    mov dh, 0               ; Head 0
    mov dl, [boot_drive]    ; Drive number passed by BIOS
    mov bx, 0x7E00          ; Buffer address (directly after MBR in memory)
    int 0x13                ; Call BIOS disk interrupt
    jc disk_error           ; Jump to error handler if carry flag is set

Execution & Output: The bootloader uses BIOS interrupt 0x13 to read from the disk. It reads the subsequent 16 sectors into 0x7E00 (the memory region immediately following 0x7C00 + 512 bytes). If the disk read fails, the CPU sets the Carry Flag (jc), triggering a halt. Output: Loads the Stage 2 bootloader into RAM.

Transition to Protected Mode

    cli                     ; Disable interrupts for mode switch
    lgdt [gdt_descriptor]   ; Load Global Descriptor Table

    mov eax, cr0
    or eax, 0x1             ; Set Protected Environment (PE) bit in CR0
    mov cr0, eax

    jmp 0x08:protected_mode ; Far jump to flush instruction pipeline

Execution & Output: Interrupts are disabled permanently for the remainder of the bootloader. The lgdt instruction loads a flat memory model mapping 4GB of addressable space. By setting the first bit of Control Register 0 (CR0), the CPU switches from 16-bit real mode to 32-bit protected mode. A far jump jmp 0x08: is required to flush the CPU's prefetch queue and set the Code Segment (CS) to 0x08 (defined in the GDT). Output: CPU transforms into 32-bit mode.


7.2. System Initialization: init.c

As the first userspace process spawned by the Linux kernel (PID 1), init.c sets up the virtual filesystems and performs cryptographic verification of the arkrt daemon.

Mounting Virtual Filesystems

#include <sys/mount.h>
#include <stdio.h>
#include <unistd.h>

void setup_fs() {
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);
    mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);
}

Execution & Output: The mount() syscalls interact directly with the VFS (Virtual File System) layer of the Linux kernel.

  • /proc exposes kernel structures and process states.
  • /sys exposes hardware tree telemetry (battery, network).
  • /dev exposes device nodes (/dev/fb0, /dev/urandom). Output: The kernel populates these directories. No text is printed to stdout to maintain the quiet boot sequence.

Cryptographic Signature Verification

#define ARK_KEY "e3b0c44298fc1c149afbf4c899*************************8"

int verify_arkrt() {
    FILE *f = fopen("/sbin/arkrt", "rb");
    if (!f) return -1;
    
    // ... SHA-256 computation over file chunks ...
    char hash_out[65];
    compute_sha256(f, hash_out);
    
    if (strncmp(hash_out, ARK_KEY, 64) == 0) {
        return 1; // Valid
    }
    return 0; // Invalid
}

Execution & Output: The process opens /sbin/arkrt in binary mode. It streams the file through a SHA-256 block hashing function. The resulting hash string is compared directly against ARK_KEY (which is dynamically injected during the build.c compilation phase).

  • If valid, the function returns 1.
  • If invalid, init goes into an infinite while(1) { sleep(1); } loop to prevent a kernel panic while blocking system execution. Output: A quiet halt if tampering is detected.

Daemon Fork and Exec

int main() {
    setup_fs();
    if (verify_arkrt()) {
        pid_t pid = fork();
        if (pid == 0) {
            char *args[] = {"/sbin/arkrt", NULL};
            execve(args[0], args, NULL);
        }
    }
    while(1) pause();
    return 0;
}

Execution & Output: fork() duplicates the init process. The child process (pid == 0) uses execve() to replace its memory space entirely with the arkrt executable. The parent init process goes to sleep forever using pause(), acting as a silent reaper for zombie processes. Output: arkrt begins execution as PID 2.


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

let fd = open("/dev/fb0", O_RDWR)
var vinfo = fb_var_screeninfo()
get_vinfo(fd, &vinfo)
var finfo = fb_fix_screeninfo()
get_finfo(fd, &finfo)

let scrSz = Int(finfo.smem_len)
let fb_ptr = mmap(nil, scrSz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
let fbp = fb_ptr!.bindMemory(to: UInt8.self, capacity: scrSz)

Execution & Output: The UI opens the raw Linux framebuffer (/dev/fb0). It uses ioctl via get_vinfo and get_finfo to query the screen resolution (e.g., 1920x1080) and bytes-per-pixel (usually 4 bytes/32-bit). mmap maps the physical GPU memory directly into the Swift process's RAM. Output: fbp becomes a mutable array where modifying an index directly changes a pixel's color on the physical monitor.

Double Buffering & Anti-Aliased Rendering

let work = UnsafeMutablePointer<UInt8>.allocate(capacity: ABUFSZ)
memset(work, 0, ABUFSZ)

// ... calculate circle positions (ex, ey) ...
diskAA(work, ex, ey, curElR, 255)

blit(work, fbp, sx, sy, lineLen, scrH, fd, &vinfo)
usleep(16666)

Execution & Output: Instead of writing to fbp directly (which causes screen tearing), it allocates a work buffer. It uses memset to clear it to black. The diskAA function iterates over the bounded box of the circle and calculates the Euclidean distance to the center. If the pixel is on the edge, it applies an alpha blend: alpha = 1.0 - (distance - inner_radius) The blit function copies the work buffer to fbp via memcpy. usleep(16666) halts execution for 16.6 milliseconds to enforce a strict 60 FPS framerate. Output: Smooth, tearing-free animations.

Phase 1: Spawn & Orbit Expansion

for frame in 0..<35 {
    let t = Double(frame) / 34.0
    let easeOut = 1.0 - pow(1.0 - t, 3.0)
    let curInnerR = Double(INNER_R) * easeOut
    // ... drawing logic ...
}

Execution & Output: The splash screen uses a cubic ease-out mathematical formula (1.0 - (1.0 - t)^3). As frame goes from 0 to 34, t goes from 0.0 to 1.0. The radius of the orbits expands rapidly at first, then slows down smoothly as it reaches its final INNER_R size. Output: Visual ring expansion.

Phase 3: Spiral Inward & Crash

for frame in 0..<30 {
    let t = Double(frame) / 29.0
    let easeIn = t * t
    let curInner = Double(INNER_R) * (1.0 - easeIn)
    // ... drawing logic ...
}

Execution & Output: Uses a quadratic ease-in formula (t^2). The orbit radius collapses inward slowly at first, then accelerates rapidly until it crashes into the central nucleus NUC_R. Output: Electrons collapse inward.

Unix Domain Socket IPC Query

let ip = queryIPC(cmdId: 102)
let battery = queryIPC(cmdId: 103)
let sysTime = queryIPC(cmdId: 101)

print("  - Interface IP  : \(ip)")

Execution & Output: Once the splash finishes, the UI queries the arkrt daemon. queryIPC opens /dev/arkrt.sock and constructs a 6-byte binary payload (2 bytes command ID, 4 bytes payload length = 0). It sends this to arkrt and waits for a response. arkrt responds with a UTF-8 string payload. The UI extracts this and prints it natively over the framebuffer canvas via VT100 terminal emulation.


7.4. Runtime Telemetry: KernelBridge.swift

KernelBridge.swift resides inside arkrt. It handles all hardware-level queries by reading the Linux /sys tree.

Battery Level Polling

func getBattery() -> String {
    let batPath = "/sys/class/power_supply/BAT0/capacity"
    guard let fd = fopen(batPath, "r") else { return "N/A" }
    var buffer = [CChar](repeating: 0, count: 8)
    fgets(&buffer, 8, fd)
    fclose(fd)
    let str = String(cString: buffer).trimmingCharacters(in: .whitespacesAndNewlines)
    return str + "%"
}

Execution & Output: The kernel automatically updates the /sys/class/power_supply/BAT0/capacity file with the hardware battery level integer. The Swift function uses standard C library functions (fopen, fgets) to read up to 8 characters. It trims the trailing newline inserted by the kernel and appends a % sign. Output: e.g., 98%.

IP Address Interrogation

func getIP() -> String {
    var interfaces: UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&interfaces) == 0 else { return "UNKNOWN" }
    
    var current = interfaces
    var ipStr = "UNKNOWN"
    
    while let iface = current {
        let name = String(cString: iface.pointee.ifa_name)
        let family = iface.pointee.ifa_addr.pointee.sa_family
        
        if family == UInt8(AF_INET) && name != "lo" {
            var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
            getnameinfo(iface.pointee.ifa_addr, socklen_t(MemoryLayout<sockaddr_in>.size), 
                        &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST)
            ipStr = String(cString: hostname)
            break
        }
        current = iface.pointee.ifa_next
    }
    freeifaddrs(interfaces)
    return ipStr
}

Execution & Output: The POSIX getifaddrs function populates a linked list of network interfaces. The loop iterates through ifa_next. It filters for IPv4 (AF_INET) and ignores the loopback interface (lo). It then uses getnameinfo to translate the raw binary sockaddr struct into a human-readable IP dotted-decimal string. freeifaddrs is strictly called to prevent memory leaks in the daemon. Output: e.g., 192.168.1.100.


7.5. Build Orchestrator: build.c

The tools/build.c file is the master compiler orchestrator, written in C for absolute portability across host build environments.

Staging & Swift Compilation

system("mkdir -p out_staging/system/frameworks out_staging/boot out_staging/.swift_build");

char swift_cmd[1024];
snprintf(swift_cmd, sizeof(swift_cmd),
         "cd frameworks/SwiftUIFramework && swift build -c release "
         "--scratch-path ../../out_staging/.swift_build");
system(swift_cmd);

Execution & Output: First, build.c guarantees the existence of output directories via mkdir -p. Next, it formats a shell string via snprintf. The critical flag --scratch-path forces the Swift Package Manager to store all its build caches, dependency clones (like OpenCombine, swift-syntax), and .o object files in out_staging/.swift_build rather than polluting the frameworks/ source tree. Output: A clean, incremental build process that drastically reduces sequential build times.

ISO Generation

system("xorriso -as mkisofs -R -J -b boot/grub/i386-pc/eltorito.img -no-emul-boot "
       "-boot-load-size 4 -boot-info-table -o finished/arkos.iso out_staging/");

Execution & Output: 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

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

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

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.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

EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
uefi_call_wrapper(SystemTable->BootServices->LocateProtocol, 3, &gop_guid, NULL, (VOID **)&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);

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);

Execution & Output: Unlike Legacy BIOS which uses INT 10h VESA modesetting, UEFI uses BootServices->LocateProtocol to find the EFI_GRAPHICS_OUTPUT_PROTOCOL (GOP). The Blt (Block Image Transfer) function is called via the uefi_call_wrapper macro (necessary for ABI compatibility between GCC and UEFI calling conventions). It first floods the screen with EfiBltVideoFill using black pixels, then calculates the exact center offset and draws a 6x6 pixel solid white dot. Output: A pitch-black screen with a crisp white dot in the exact center.

Filesystem Abstraction & Loading the Kernel

EFI_LOADED_IMAGE *loaded_image = NULL;
uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3, ImageHandle, 
                  &LoadedImageProtocol, (VOID **)&loaded_image);

EFI_DEVICE_PATH *kernel_path = FileDevicePath(loaded_image->DeviceHandle, L"\\EFI\\BOOT\\bzImage");
EFI_HANDLE kernel_img = NULL;
uefi_call_wrapper(SystemTable->BootServices->LoadImage, 6, FALSE, ImageHandle, 
                  kernel_path, NULL, 0, &kernel_img);

Execution & Output: In BIOS mode, sectors are blindly read off the disk using INT 13h. In UEFI, the firmware natively understands FAT32 filesystems (the EFI System Partition / ESP). The bootloader queries the LoadedImageProtocol to find out which drive it booted from (loaded_image->DeviceHandle). It constructs a Unicode path \EFI\BOOT\bzImage and asks the motherboard to load the Linux kernel executable into RAM using LoadImage. Output: The kernel is silently staged in memory.

ESP File Reading: read_file_from_esp Helper

status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3, 
                           loaded_image->DeviceHandle, &FileSystemProtocol, (VOID **)&fs);
status = uefi_call_wrapper(fs->OpenVolume, 2, fs, &root);
status = uefi_call_wrapper(root->Open, 5, root, &file, FileName, EFI_FILE_MODE_READ, 0);

Execution & Output: To read arbitrary files (like the animation payload), the bootloader relies on EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. It opens the root volume of the USB drive/disk, and then traverses the filesystem to open \EFI\BOOT\animation.bin. It then dynamically allocates a buffer using BootServices->AllocatePool and reads the raw bytes. Output: A populated memory pointer containing binary file data.

The Boot Animation Loop

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);
}

Execution & Output: The UEFI loader plays the exact same Atom boot animation as the UI, but it must do it before the OS loads. It iterates over the pre-rendered 200x200 pixel arrays in animation.bin. Using EfiBltBufferToVideo, it blasts each frame directly to the GPU framebuffer. BootServices->Stall(16666) halts CPU execution for 16.6 milliseconds (yielding ~60 FPS). Output: Smooth, hardware-accelerated boot sequence animation playing over the white dot.

Kernel Command Line & Execution Handoff

CHAR16 *cmd_line = L"initrd=\\EFI\\BOOT\\initramfs.img console=ttyS0 console=tty0 loglevel=0 logo.nologo 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);

uefi_call_wrapper(SystemTable->BootServices->StartImage, 3, kernel_img, &exit_data_size, &exit_data);

Execution & Output: Before starting the kernel, the bootloader injects boot parameters directly into the kernel's UEFI struct (LoadOptions). It sets loglevel=0, quiet, and logo.nologo to guarantee the kernel doesn't spit out terminal text over the beautiful boot animation. Finally, StartImage executes the kernel, causing the UEFI firmware to permanently yield control to Linux. Output: Transition to the Linux Kernel (init.c).


7.8. Architectural Comparison: Legacy BIOS vs. UEFI Boot Flow

Feature Legacy BIOS (bootloader.asm) UEFI (bootloader.c)
Execution Mode Boots in 16-bit Real Mode. Must manually configure GDT and perform a Far Jump to enter 32-bit Protected Mode. Boots directly in 32-bit or 64-bit Protected/Long mode (depending on the motherboard). No GDT hacking required.
Disk I/O Blindly reads raw disk sectors (LBA) using BIOS INT 13h interrupts. Has no concept of files or folders. Natively understands FAT32 formatting. Uses EFI_SIMPLE_FILE_SYSTEM_PROTOCOL to traverse directories and read specific files by string name.
Graphics Uses standard VESA BIOS Extensions (VBE) via INT 10h to request a linear framebuffer mode. Hard to standardize across GPUs. Uses EFI_GRAPHICS_OUTPUT_PROTOCOL (GOP). The firmware handles GPU abstraction, offering seamless drawing APIs like Blt.
API Integration Relies entirely on ancient, opaque BIOS hardware interrupts (e.g., INT 10h, INT 13h, INT 15h). Uses C structs and function pointers populated by the motherboard's firmware (SystemTable->BootServices).
Security None natively. Vulnerable to bootkit infections manipulating the MBR. Contains native infrastructure for Secure Boot (cryptographically verifying the kernel binary against embedded motherboard keys).