diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/boot.zig | 23 | ||||
| -rw-r--r-- | boot/framebuffer.zig | 26 | ||||
| -rw-r--r-- | boot/limine.zig | 41 | ||||
| -rw-r--r-- | boot/serial.zig | 6 |
4 files changed, 90 insertions, 6 deletions
diff --git a/boot/boot.zig b/boot/boot.zig index a7822af..2303409 100644 --- a/boot/boot.zig +++ b/boot/boot.zig @@ -1,6 +1,7 @@ const std = @import("std"); const limine = @import("limine.zig"); const serial = @import("serial.zig"); +const framebuffer = @import("framebuffer.zig"); // We need a panic handler otherwise zig won't be happy, // std usually formats a message through std.Io.Writer which @@ -9,9 +10,9 @@ const serial = @import("serial.zig"); pub const panic = std.debug.FullPanic(struct { fn halt(msg: []const u8, _: ?usize) noreturn { serial.init(); - serial.write("\n!!! uhhhh engine kaput : "); + serial.write("\r\n!!! uhhhh engine kaput : "); serial.write(msg); - serial.write("\n"); + serial.write("\r\n"); while (true) asm volatile ("hlt"); } }.halt); @@ -24,6 +25,22 @@ export var requests_end: limine.RequestsEndMarker 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"); + serial.write("if you see this, it means revel didn't shit the bed\r\n"); + + 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"); } diff --git a/boot/framebuffer.zig b/boot/framebuffer.zig new file mode 100644 index 0000000..6518b17 --- /dev/null +++ b/boot/framebuffer.zig @@ -0,0 +1,26 @@ +// linear framebuffer type shi you feel me? +// see: https://wiki.osdev.org/Limine_Bare_Bones + +const limine = @import("limine.zig"); + +pub const Framebuffer = limine.Framebuffer; + +// the request placed in .limine_requests so the loader finds and fills it +// idk why this sounds vaguely erotic, like yeah fill me harder lol +export var request: limine.FramebufferRequest linksection(".limine_requests") = .{}; + +// the response pointer is written by Limine before we run, so read it through a +// volatile pointer or the optimizer assumes it's still null +pub fn get() ?*Framebuffer { + const req: *volatile limine.FramebufferRequest = &request; + const resp = req.response orelse return null; + if (resp.framebuffer_count == 0) return null; + return resp.framebuffers.?[0]; +} + +// assumes the usual Limine RGB 32-bpp layout im sure i wont forget about this layout +// later and i wont fuck me over +pub fn putpixel(fb: *Framebuffer, x: usize, y: usize, color: u32) void { + const pixel: *align(1) u32 = @ptrCast(fb.address + y * fb.pitch + x * 4); + pixel.* = color; +} diff --git a/boot/limine.zig b/boot/limine.zig index e9aac9c..ef08867 100644 --- a/boot/limine.zig +++ b/boot/limine.zig @@ -25,3 +25,44 @@ pub const RequestsEndMarker = extern struct { m0: u64 = 0xadc0e0531bb10d03, m1: u64 = 0x9572709f31764c62, }; + +// Every request id starts with this common magic, then two request-specific +// words. Limine scans .limine_requests for these and fills in `response`. +fn requestId(a: u64, b: u64) [4]u64 { + return .{ 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, a, b }; +} + +// --- Framebuffer feature: ask Limine for a linear framebuffer --- + +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, +}; diff --git a/boot/serial.zig b/boot/serial.zig index cd6bd13..4863864 100644 --- a/boot/serial.zig +++ b/boot/serial.zig @@ -1,6 +1,6 @@ -// This is a minimal 16550 UART driver for COM1, this is -// mainly going to be used for debugging since its really -// simple to setup. Fun fact: i was drunk when i wrote this +// This is a minimal 16550 UART driver for COM1, this is mainly going +// to be used for debugging since its really simple to setup. +// Fun fact: i was drunk when i wrote this // // see: https://wiki.osdev.org/Serial_Ports |
