hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/boot/limine.zig
blob: 914aca8d597d264beec4adf2f65fda2f87e4a6a2 (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Limine scans the loaded image for these magic numbers, BaseRevision is 
// a handshake, essentially we ask limine for rev 3, and if it supports it, 
// limine zeros it out
pub const BaseRevision = extern struct {
    magic0: u64 = 0xf9562b2d5c95a6c8,
    magic1: u64 = 0x6a7b384944536bdc,
    revision: u64,

    pub fn init(revision: u64) BaseRevision {
        return .{ .revision = revision };
    }
};

// bracketing markers, they are pretty optional but when we add proper 
// limine requests, having these here comes handy
pub const RequestsStartMarker = extern struct {
    m0: u64 = 0xf6b8f4b39de7d1ae,
    m1: u64 = 0xfab91a6940fcb9cf,
    m2: u64 = 0x785c6ed015d3e316,
    m3: u64 = 0x181e920a7852b9d9,
};

pub const RequestsEndMarker = extern struct {
    m0: u64 = 0xadc0e0531bb10d03,
    m1: u64 = 0x9572709f31764c62,
};

// every request id starts with this common magic, then two request specific
// words, bootloader scans .limine_requests for these and fills in `response`
fn requestId(a: u64, b: u64) [4]u64 {
    return .{ 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, a, b };
}

// this comes from the limine spec
// you can see it in the header files
pub const Framebuffer = extern struct {
    address: [*]u8,
    width: u64,
    height: u64,
    pitch: u64, // bytes per row (not always width*bpp/8)
    bpp: u16, // bits per pixel
    memory_model: u8, // 1 = RGB
    red_mask_size: u8,
    red_mask_shift: u8,
    green_mask_size: u8,
    green_mask_shift: u8,
    blue_mask_size: u8,
    blue_mask_shift: u8,
    // 7 bytes of padding land here (extern-struct alignment before edid_size)
    edid_size: u64,
    edid: ?*anyopaque,
    // response revision 1 and up, unused for now:
    mode_count: u64,
    modes: ?*anyopaque,
};

pub const FramebufferResponse = extern struct {
    revision: u64,
    framebuffer_count: u64,
    framebuffers: ?[*]*Framebuffer,
};

pub const FramebufferRequest = extern struct {
    id: [4]u64 = requestId(0x9d5827dcd881dd75, 0xa3148604f6fab11b),
    revision: u64 = 0,
    response: ?*FramebufferResponse = null,
};

// HHDM = higher-half direct map, limine linearly maps ALL of physical memory
// starting at `offset`, so any physical address p is reachable at p + offset
// This is how we touch physical frames without setting up our own page tables
// and this is how my hypothetical future girlfriend should touch my pointer
pub const HhdmResponse = extern struct {
    revision: u64,
    offset: u64,
};

pub const HhdmRequest = extern struct {
    id: [4]u64 = requestId(0x48dcf1cb8ad2b852, 0x63984e959a98244b),
    revision: u64 = 0,
    response: ?*HhdmResponse = null,
};

// what each region of physical memory is
// only `usable` (0) is ours to hand out freely
// the rest belongs to firmware and other stingy shits
pub const MemoryType = enum(u64) {
    usable = 0,
    reserved = 1,
    acpi_reclaimable = 2,
    acpi_nvs = 3,
    bad = 4,
    bootloader_reclaimable = 5,
    kernel_and_modules = 6,
    framebuffer = 7,
    _,
};

pub const MemoryMapEntry = extern struct {
    base: u64,
    length: u64,
    type: MemoryType,
};

// NOTE: `entries` is an array of POINTERS to entries, not the entries inline
// NOTE: i will forget this
pub const MemoryMapResponse = extern struct {
    revision: u64,
    entry_count: u64,
    entries: ?[*]*MemoryMapEntry,
};

pub const MemoryMapRequest = extern struct {
    id: [4]u64 = requestId(0x67cf3d9d378a806f, 0xe304acdfc50c3c62),
    revision: u64 = 0,
    response: ?*MemoryMapResponse = null,
};