booting into the kernel
This commit is contained in:
+44
-4
@@ -1,8 +1,48 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
const danos = @import("danos");
|
||||
const BootInfo = danos.BootInfo;
|
||||
|
||||
pub fn main() !void {
|
||||
/// The calling convention used to enter the kernel. Pinned to SysV explicitly:
|
||||
/// the bootloader is built for the UEFI target, whose C convention is Microsoft
|
||||
/// x64 (first argument in RCX), while the kernel is SysV (first argument in
|
||||
/// RDI). Both sides reference this so the `boot_info` pointer lands in the
|
||||
/// register the other expects. `danos.kernel_abi` re-exports it to the loader.
|
||||
pub const kernel_abi = danos.kernel_abi;
|
||||
|
||||
}
|
||||
/// Kernel entry point. The bootloader jumps here after `ExitBootServices` with a
|
||||
/// pointer to the handoff data. There is no runtime, no stack unwinding, and no
|
||||
/// caller to return to, so this never returns.
|
||||
export fn _start(boot_info: *const BootInfo) callconv(kernel_abi) noreturn {
|
||||
kmain(boot_info);
|
||||
}
|
||||
|
||||
fn kmain(boot_info: *const BootInfo) noreturn {
|
||||
// Paint the whole screen so it is visually obvious the kernel took over.
|
||||
// We honour `pitch` because it can exceed `width * 4`.
|
||||
const fb = boot_info.framebuffer;
|
||||
const base: [*]volatile u8 = @ptrFromInt(fb.base);
|
||||
var y: u32 = 0;
|
||||
while (y < fb.height) : (y += 1) {
|
||||
const row: [*]volatile u32 = @ptrCast(@alignCast(base + y * fb.pitch));
|
||||
var x: u32 = 0;
|
||||
while (x < fb.width) : (x += 1) row[x] = 0x0033_66cc;
|
||||
}
|
||||
|
||||
hang();
|
||||
}
|
||||
|
||||
/// Stop the CPU. `hlt` in a loop parks the core at near-zero power until the
|
||||
/// next interrupt; we loop because `hlt` returns when one arrives.
|
||||
fn hang() noreturn {
|
||||
while (true) asm volatile ("hlt");
|
||||
}
|
||||
|
||||
/// Freestanding has no OS to receive a panic, so override std's default panic
|
||||
/// handler to simply halt. (Later this can print to the framebuffer/serial.)
|
||||
pub const panic = std.debug.FullPanic(struct {
|
||||
fn panic(msg: []const u8, first_trace_addr: ?usize) noreturn {
|
||||
_ = msg;
|
||||
_ = first_trace_addr;
|
||||
hang();
|
||||
}
|
||||
}.panic);
|
||||
|
||||
Reference in New Issue
Block a user