blob: 933065ca2feb57540aa9cb79c959a47b674040e1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
const std = @import("std");
const limine = @import("limine.zig");
const serial = @import("serial.zig");
const framebuffer = @import("framebuffer.zig");
const gdt = @import("gdt.zig");
const idt = @import("idt.zig");
const pmm = @import("pmm.zig");
const heap = @import("heap.zig");
// We need a panic handler otherwise zig won't be happy,
// std usually formats a message through std.Io.Writer which
// emits SSE instructions which I haven't enabled. Ours
// dumps the message to serial, then halts.
pub const panic = std.debug.FullPanic(struct {
fn halt(msg: []const u8, _: ?usize) noreturn {
serial.init();
serial.write("\r\n!!! uhhhh engine kaput : ");
serial.write(msg);
serial.write("\r\n");
while (true) asm volatile ("hlt");
}
}.halt);
// Check `linker.ld`
export var base_revision: limine.BaseRevision linksection(".limine_requests") = limine.BaseRevision.init(3);
export var requests_start: limine.RequestsStartMarker linksection(".limine_requests_start") = .{};
export var requests_end: limine.RequestsEndMarker linksection(".limine_requests_end") = .{};
// the loader fills these before we run so we read them through volatile pointers or
// the optimizer assumes they're still the null we initialized them to
export var hhdm_request: limine.HhdmRequest linksection(".limine_requests") = .{};
export var memmap_request: limine.MemoryMapRequest linksection(".limine_requests") = .{};
// ENTRY(_start)
export fn _start() callconv(.c) noreturn {
serial.init();
serial.write("if you see this, it means revel didn't shit the bed\r\n");
gdt.load();
idt.init();
serial.write("gdt + idt loaded\r\n");
// HHDM + memory map -> physical frame allocator -> kernel heap
const hhdm_req: *volatile limine.HhdmRequest = &hhdm_request;
const memmap_req: *volatile limine.MemoryMapRequest = &memmap_request;
const hhdm = hhdm_req.response orelse @panic("limine gave us no HHDM");
const memmap = memmap_req.response orelse @panic("limine gave us no memory map");
pmm.init(hhdm, memmap);
pmm.dump(memmap);
heap.init();
// NOTE: this is a sanity check
// two allocations should be distinct and non-overlapping,
// and a freed frame should come straight back on the next alloc.
const a = pmm.alloc().?;
const b = pmm.alloc().?;
serial.write("pmm test: a=");
serial.writeHex(a);
serial.write(" b=");
serial.writeHex(b);
serial.write("\r\n");
pmm.free(a);
const c = pmm.alloc().?;
serial.write("pmm test: freed a, realloc=");
serial.writeHex(c);
serial.write(if (c == a) " (reused, good)\r\n" else " (mismatch!)\r\n");
pmm.free(b);
pmm.free(c);
if (framebuffer.get()) |screen| {
// XOR texture
var y: usize = 0;
while (y < screen.height) : (y += 1) {
var x: usize = 0;
while (x < screen.width) : (x += 1) {
const v: u32 = @intCast((x ^ y) & 0xFF);
framebuffer.putpixel(screen, x, y, (v << 16) | (v << 8) | v);
}
}
serial.write("drew to the framebuffer\r\n");
} else {
serial.write("limine was a piece of shit.\r\n");
}
while (true) asm volatile ("hlt");
}
|