Microkernel thing OS experiment (Zig ⚡)
1const limine = @import("limine");
2const std = @import("std");
3const arch = @import("root.zig");
4const common = @import("common");
5const log = std.log.scoped(.aarch64_init);
6
7pub const limine_requests = struct {
8 // export var start_marker: limine.RequestsStartMarker linksection(".limine_reqs_start") = .{};
9 // export var end_marker: limine.RequestsEndMarker linksection(".limine_reqs_end") = .{};
10
11 pub export var base_revision: limine.BaseRevision = .{ .revision = 3 };
12 pub export var framebuffer: limine.FramebufferRequest = .{};
13 pub export var hhdm: limine.HhdmRequest = .{};
14 pub export var memmap: limine.MemoryMapRequest = .{};
15 pub export var rsdp_req: limine.RsdpRequest = .{};
16 pub export var dtb_req: limine.DtbRequest = .{};
17 pub export var modules: limine.ModuleRequest = .{};
18 pub export var mp: limine.SmpMpFeature.MpRequest = .{};
19};
20
21pub fn bsp_init() callconv(.c) noreturn {
22 if (limine_requests.framebuffer.response) |fb_response| {
23 if (fb_response.framebuffer_count > 0) {
24 const fb = common.aux.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
25 common.init_data.framebuffer = fb;
26 @memset(fb.address[0..64], 0xFF);
27 }
28 }
29 arch.instructions.die();
30 // Don't optimize away the limine requests
31 inline for (@typeInfo(limine_requests).@"struct".decls) |decl| {
32 std.mem.doNotOptimizeAway(&@field(limine_requests, decl.name));
33 }
34
35 // If the base revision isn't supported, we can't boot
36 if (!limine_requests.base_revision.isSupported()) {
37 @branchHint(.cold);
38 arch.instructions.die();
39 }
40
41 // Die if we don't have a memory map or Higher Half Direct Mapping
42 if (limine_requests.memmap.response == null) {
43 @branchHint(.cold);
44 arch.instructions.die();
45 }
46
47 if (limine_requests.hhdm.response == null) {
48 @branchHint(.cold);
49 arch.instructions.die();
50 }
51 const hhdm_offset = limine_requests.hhdm.response.?.offset;
52 common.init_data.hhdm_slide = hhdm_offset;
53
54 // Add in a framebuffer if found
55 initConsole();
56
57 // Add in ACPI/dtb if found
58 initHwDesc();
59
60 // Set up the temporary Physical Memory Allocator
61 common.mm.bootmem.init();
62
63 // Attach the root task
64 if (limine_requests.modules.response) |module_response| {
65 if (module_response.module_count > 0) {
66 const mod = module_response.modules.?[0];
67 const mod_addr: [*]align(4096) u8 = @ptrCast(mod.address);
68 const mod_size = mod.size;
69 log.info("Loading root task with {s} @ {*}", .{ mod.path, mod.address });
70 common.init_data.root_task = mod_addr[0..mod_size];
71 }
72 } else {
73 @branchHint(.unlikely);
74 @panic("No root task found!");
75 }
76
77 log.info("Nothing else to do!", .{});
78
79 arch.instructions.die();
80}
81
82fn initConsole() void {
83 if (limine_requests.framebuffer.response) |fb_response| {
84 if (fb_response.framebuffer_count > 0) {
85 const fb = common.aux.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
86 common.init_data.framebuffer = fb;
87 // At this point, log becomes usable
88 common.init_data.console = console.Console.from_font(fb, console.DefaultFont);
89 }
90 }
91}
92
93fn initHwDesc() void {
94 if (limine_requests.dtb_req.response) |dtb_response| {
95 common.init_data.hardware_description = .{ .dtb = dtb_response.dtb_ptr };
96 }
97 if (limine_requests.rsdp_req.response) |rsdp_response| {
98 common.init_data.hardware_description = .{ .acpi_rsdp = rsdp_response.address };
99 }
100}