summaryrefslogtreecommitdiff
path: root/x86-bare-metal/mbr-disk-lba/zmbr.zig
diff options
context:
space:
mode:
Diffstat (limited to 'x86-bare-metal/mbr-disk-lba/zmbr.zig')
-rw-r--r--x86-bare-metal/mbr-disk-lba/zmbr.zig66
1 files changed, 66 insertions, 0 deletions
diff --git a/x86-bare-metal/mbr-disk-lba/zmbr.zig b/x86-bare-metal/mbr-disk-lba/zmbr.zig
new file mode 100644
index 0000000..e5b06ea
--- /dev/null
+++ b/x86-bare-metal/mbr-disk-lba/zmbr.zig
@@ -0,0 +1,66 @@
+// Frambuffer limits.
+const COLS = 80;
+const ROWS = 25;
+
+// Frambuffer cursor.
+var col: u16 = 0;
+var row: u16 = 0;
+
+// Frambuffer.
+const fb: []u16 = @as([*]u16, @ptrFromInt(0xB8000))[0 .. COLS * ROWS];
+
+/// Clear screen (all black).
+fn clear_screen() void {
+ for (fb) |*ch| {
+ ch.* = 0;
+ }
+}
+
+/// Draw string to current cursor position.
+fn puts(str: []const u8) void {
+ // Each framebuffer entry in text mode is 16bit wide.
+ // [15] blink
+ // [14:12] bg color (3 bit)
+ // [11: 8] fg color (4 bit)
+ // [ 7: 0] ascii character
+ // https://en.wikipedia.org/wiki/VGA_text_mode
+ for (str) |ch| {
+ if (ch == '\n') {
+ col = 0;
+ row += 1;
+ } else {
+ const pos = (row * COLS + col);
+ // bg - black; fg - white;
+ fb[pos] = @as(u16, 15) << 8 | ch;
+ col += 1;
+ }
+ if (col == COLS) {
+ row += 1;
+ if (row == ROWS) {
+ row = 0;
+ }
+ }
+ }
+}
+
+// kmain should be "callconv(.naked)", once issue is fixed.
+// https://github.com/ziglang/zig/issues/18183
+export fn kmain() noreturn {
+ clear_screen();
+
+ // Print first bytes of LBA block 1 we loaded from disk (sector 2).
+ const lba1: []const u8 = @as([*]const u8, @ptrFromInt(0x7e00))[0..4];
+ puts("lba1: ");
+ puts(lba1);
+ puts("\n");
+
+ // Print first bytes of LBA block 2 we loaded from disk (sector 3).
+ const lba2: []const u8 = @as([*]const u8, @ptrFromInt(0x8000))[0..4];
+ puts("lba2: ");
+ puts(lba2);
+ puts("\n");
+
+ while (true) {
+ asm volatile ("hlt");
+ }
+}