From 7addcc4ca56f0a130e5acec88475fc78c76ce471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Krzy=C5=BCanowski?= Date: Thu, 22 Aug 2024 23:57:22 +0200 Subject: [PATCH] Initial commit, not yet working --- .gitignore | 2 ++ build.zig | 36 +++++++++++++++++++++ src/console.zig | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ src/grub.cfg | 3 ++ src/linker.ld | 26 +++++++++++++++ src/main.zig | 32 +++++++++++++++++++ 6 files changed, 183 insertions(+) create mode 100644 .gitignore create mode 100644 build.zig create mode 100644 src/console.zig create mode 100644 src/grub.cfg create mode 100644 src/linker.ld create mode 100644 src/main.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dca1103 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +zig-out/ +.zig-cache/ diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..24cff05 --- /dev/null +++ b/build.zig @@ -0,0 +1,36 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + var disabled_features = std.Target.Cpu.Feature.Set.empty; + var enabled_features = std.Target.Cpu.Feature.Set.empty; + + disabled_features.addFeature(@intFromEnum(std.Target.x86.Feature.mmx)); + disabled_features.addFeature(@intFromEnum(std.Target.x86.Feature.sse)); + disabled_features.addFeature(@intFromEnum(std.Target.x86.Feature.sse2)); + disabled_features.addFeature(@intFromEnum(std.Target.x86.Feature.avx)); + disabled_features.addFeature(@intFromEnum(std.Target.x86.Feature.avx2)); + enabled_features.addFeature(@intFromEnum(std.Target.x86.Feature.soft_float)); + + const target_query = std.Target.Query{ + .cpu_arch = std.Target.Cpu.Arch.x86, + .os_tag = std.Target.Os.Tag.freestanding, + .abi = std.Target.Abi.none, + .cpu_features_sub = disabled_features, + .cpu_features_add = enabled_features, + }; + const optimize = b.standardOptimizeOption(.{}); + + const kernel = b.addExecutable(.{ + .name = "kernel.elf", + .root_source_file = b.path("src/main.zig"), + .target = b.resolveTargetQuery(target_query), + .optimize = optimize, + .code_model = .kernel, + }); + + kernel.setLinkerScript(b.path("src/linker.ld")); + b.installArtifact(kernel); + + const kernel_step = b.step("kernel", "Build the kernel"); + kernel_step.dependOn(&kernel.step); +} diff --git a/src/console.zig b/src/console.zig new file mode 100644 index 0000000..0b331ca --- /dev/null +++ b/src/console.zig @@ -0,0 +1,84 @@ +const fmt = @import("std").fmt; +const Writer = @import("std").io.Writer; + +const VGA_WIDTH = 80; +const VGA_HEIGHT = 25; +const VGA_SIZE = VGA_WIDTH * VGA_HEIGHT; + +pub const ConsoleColors = enum(u8) { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + LightMagenta = 13, + LightBrown = 14, + White = 15, +}; + +var row: usize = 0; +var column: usize = 0; +var color = vgaEntryColor(ConsoleColors.LightGray, ConsoleColors.Black); +var buffer = @as([*]volatile u16, @ptrFromInt(0xB8000)); + +fn vgaEntryColor(fg: ConsoleColors, bg: ConsoleColors) u8 { + return @intFromEnum(fg) | (@intFromEnum(bg) << 4); +} + +fn vgaEntry(uc: u8, new_color: u8) u16 { + const c: u16 = new_color; + + return uc | (c << 8); +} + +pub fn initialize() void { + clear(); +} + +pub fn setColor(new_color: u8) void { + color = new_color; +} + +pub fn clear() void { + @memset(buffer[0..VGA_SIZE], vgaEntry(' ', color)); +} + +pub fn putCharAt(c: u8, new_color: u8, x: usize, y: usize) void { + const index = y * VGA_WIDTH + x; + buffer[index] = vgaEntry(c, new_color); +} + +pub fn putChar(c: u8) void { + putCharAt(c, color, column, row); + column += 1; + if (column == VGA_WIDTH) { + column = 0; + row += 1; + if (row == VGA_HEIGHT) + row = 0; + } +} + +pub fn puts(data: []const u8) void { + for (data) |c| + putChar(c); +} + +pub const writer = Writer(void, error{}, callback){ .context = {} }; + +fn callback(_: void, string: []const u8) error{}!usize { + puts(string); + return string.len; +} + +pub fn printf(comptime format: []const u8, args: anytype) void { + fmt.format(writer, format, args) catch unreachable; +} diff --git a/src/grub.cfg b/src/grub.cfg new file mode 100644 index 0000000..2164e64 --- /dev/null +++ b/src/grub.cfg @@ -0,0 +1,3 @@ +menuentry "Zig Bare Bones" { + multiboot /boot/kernel.elf +} \ No newline at end of file diff --git a/src/linker.ld b/src/linker.ld new file mode 100644 index 0000000..ec475c8 --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,26 @@ +ENTRY(_start) + +SECTIONS { + . = 1M; + + .multiboot { + KEEP(*(.multiboot)) + } + + .text : ALIGN(4K) { + *(.text) + } + + .rodata : ALIGN(4K) { + *(.rodata) + } + + .data : ALIGN(4K) { + *(.data) + } + + .bss : ALIGN(4K) { + *(COMMON) + *(.bss) + } +} diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..aa00104 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,32 @@ +const console = @import("console.zig"); + +const ALIGN = 1 << 0; +const MEMINFO = 1 << 1; +const MAGIC = 0x1BADB002; +const FLAGS = ALIGN | MEMINFO; + +const MultibootHeader = packed struct { + magic: i32 = MAGIC, + flags: i32, + checksum: i32, +}; + +export var multiboot align(4) linksection(".multiboot") = MultibootHeader{ + .flags = FLAGS, + .checksum = -(MAGIC + FLAGS), +}; + +export var stack_bytes: [16 * 1024]u8 align(16) linksection(".bss") = undefined; +const stack_bytes_slice = stack_bytes[0..]; + +export fn _start() callconv(.Naked) noreturn { + @call(.auto, kmain, .{}); + //kmain(); + + while (true) {} +} + +fn kmain() void { + console.initialize(); + console.puts("Hello world!"); +}