Microkernel thing OS experiment (Zig ⚡)
1const common = @import("root.zig"); 2const paging = common.mm.paging; 3const std = @import("std"); 4const elf = std.elf; 5const log = std.log.scoped(.elf_loader); 6 7// Load root task, return the entry point 8pub fn loadRootTask() !usize { 9 const root_task = common.init_data.root_task; 10 const hdr = blk: { 11 const hdr: *elf.Elf64_Ehdr = @ptrCast(root_task); 12 break :blk elf.Header.init(hdr.*, .little); 13 }; 14 var iter = hdr.iterateProgramHeadersBuffer(root_task); 15 while (try iter.next()) |entry| { 16 if ((entry.p_type != elf.PT_LOAD) or (entry.p_memsz == 0)) continue; 17 18 // 1. Allocate pages to back this allocation 19 const real_vaddr = std.mem.alignBackward(usize, entry.p_vaddr, std.heap.pageSize()); 20 const vaddr_shift = entry.p_vaddr - real_vaddr; 21 const memsz_pages = std.mem.alignForward(usize, vaddr_shift + entry.p_memsz, std.heap.pageSize()); 22 23 log.debug("Allocating 0x{x} bytes (0x{x} real) to 0x{x:0>16} from offset 0x{x}", .{ entry.p_filesz, memsz_pages, entry.p_vaddr, entry.p_offset }); 24 25 const page_backing = try common.init_data.bootmem.allocPhys(memsz_pages); 26 try paging.mapPhys(.{ 27 .vaddr = real_vaddr, 28 .paddr = page_backing, 29 .size = memsz_pages, 30 .memory_type = .MemoryWriteBack, 31 .perms = .{ 32 .executable = entry.p_flags & elf.PF_X > 0, 33 .writable = entry.p_flags & elf.PF_W > 0, 34 .userspace_accessible = true, 35 }, 36 }); 37 38 // 2. Copy filesz bytes from offset to this new page 39 const dst = common.mm.physToHHDM([*]u8, page_backing + vaddr_shift); 40 const dst_slice = dst[0..entry.p_filesz]; 41 42 const src_slice = root_task[entry.p_offset..][0..entry.p_filesz]; 43 @memcpy(dst_slice, src_slice); 44 45 // 3. Add memsz - filesz zeroes 46 const zero_slice = dst[entry.p_filesz..entry.p_memsz]; 47 @memset(zero_slice, 0); 48 } 49 50 // Return the entry point 51 return hdr.entry; 52}