Microkernel thing OS experiment (Zig ⚡)
1const common = @import("root.zig");
2const arch = @import("arch");
3const paging = common.mm.paging;
4const std = @import("std");
5const elf = std.elf;
6const log = std.log.scoped(.elf_loader);
7
8// Load root task, return the entry point
9pub fn loadRootTask(context: *arch.mm.paging.Context) !usize {
10 const root_task = common.init_data.root_task;
11 const hdr = blk: {
12 const hdr: *elf.Elf64_Ehdr = @ptrCast(root_task);
13 break :blk elf.Header.init(hdr.*, .little);
14 };
15 var iter = hdr.iterateProgramHeadersBuffer(root_task);
16 while (try iter.next()) |entry| {
17 if ((entry.p_type != elf.PT_LOAD) or (entry.p_memsz == 0)) continue;
18
19 // 1. Allocate pages to back this allocation
20 const real_vaddr = std.mem.alignBackward(usize, entry.p_vaddr, std.heap.pageSize());
21 const vaddr_shift = entry.p_vaddr - real_vaddr;
22 const memsz_pages = std.mem.alignForward(usize, vaddr_shift + entry.p_memsz, std.heap.pageSize());
23
24 const page_backing = try common.init_data.bootmem.allocPhys(memsz_pages);
25 try paging.mapPhys(.{
26 .vaddr = real_vaddr,
27 .paddr = page_backing,
28 .size = memsz_pages,
29 .memory_type = .MemoryWriteBack,
30 .perms = .{
31 .x = entry.p_flags & elf.PF_X > 0,
32 .w = entry.p_flags & elf.PF_W > 0,
33 .u = true,
34 },
35 .context = context,
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}