blob: e5b06ea0dca11c96eee0192be0b4ee59ac401ee7 (
plain) (
blame)
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
|
// 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");
}
}
|