const std = @import("std"); extern fn console_write(ptr: [*]const u8, len: usize) void; // Embed the Subject Zero binary export var subject_bin = @embedFile("subject.bin"); export fn ion_loader_load(path: [*:0]const u8) u64 { _ = path; console_write("[Loader] Parsing ELF\n", 21); // Verify ELF Magic const magic = subject_bin[0..4]; if (magic[0] != 0x7F or magic[1] != 'E' or magic[2] != 'L' or magic[3] != 'F') { console_write("[Loader] ERROR: Invalid ELF magic\n", 35); return 0; } // Parse ELF64 Header const e_entry = read_u64_le(subject_bin[0x18..0x20]); const e_phoff = read_u64_le(subject_bin[0x20..0x28]); const e_phentsize = read_u16_le(subject_bin[0x36..0x38]); const e_phnum = read_u16_le(subject_bin[0x38..0x3a]); console_write("[Loader] Entry: 0x", 18); print_hex(e_entry); console_write("\n[Loader] Loading ", 17); print_hex(e_phnum); console_write(" segments\n", 10); // Load each PT_LOAD segment var i: usize = 0; while (i < e_phnum) : (i += 1) { const ph_offset = e_phoff + (i * e_phentsize); const p_type = read_u32_le(subject_bin[ph_offset .. ph_offset + 4]); if (p_type == 1) { // PT_LOAD const p_offset = read_u64_le(subject_bin[ph_offset + 8 .. ph_offset + 16]); const p_vaddr = read_u64_le(subject_bin[ph_offset + 16 .. ph_offset + 24]); const p_filesz = read_u64_le(subject_bin[ph_offset + 32 .. ph_offset + 40]); const p_memsz = read_u64_le(subject_bin[ph_offset + 40 .. ph_offset + 48]); const dest = @as([*]u8, @ptrFromInt(p_vaddr)); // Copy file content if (p_filesz > 0) { const src = subject_bin[p_offset .. p_offset + p_filesz]; @memcpy(dest[0..p_filesz], src); } // Zero BSS (memsz > filesz) if (p_memsz > p_filesz) { @memset(dest[p_filesz..p_memsz], 0); } } } console_write("[Loader] ELF loaded successfully\n", 33); return e_entry; } fn read_u16_le(bytes: []const u8) u16 { return @as(u16, bytes[0]) | (@as(u16, bytes[1]) << 8); } fn read_u32_le(bytes: []const u8) u32 { return @as(u32, bytes[0]) | (@as(u32, bytes[1]) << 8) | (@as(u32, bytes[2]) << 16) | (@as(u32, bytes[3]) << 24); } fn read_u64_le(bytes: []const u8) u64 { var result: u64 = 0; var j: usize = 0; while (j < 8) : (j += 1) { result |= @as(u64, bytes[j]) << @intCast(j * 8); } return result; } fn print_hex(value: u64) void { const hex_chars = "0123456789ABCDEF"; var buf: [16]u8 = undefined; var i: usize = 0; while (i < 16) : (i += 1) { const shift: u6 = @intCast((15 - i) * 4); const nibble = (value >> shift) & 0xF; buf[i] = hex_chars[nibble]; } console_write(&buf, 16); } export fn launch_subject() void { const target_addr = ion_loader_load("/sysro/bin/subject"); console_write("[Loader] Jumping...\n", 20); const entry = @as(*const fn () void, @ptrFromInt(target_addr)); entry(); } pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { console_write("[Loader] PANIC: ", 16); console_write(msg.ptr, msg.len); console_write("\n", 1); while (true) {} }