From bee7416b081c79418f558070c501707e5a4fe55d Mon Sep 17 00:00:00 2001 From: Edward Dean Date: Wed, 17 Apr 2019 17:40:26 +0100 Subject: [PATCH] Feature/hello world kernel land, closes #3 (#4) * prints hello world * Builds with the zig build system --- .gitignore | 5 +- README.md | 5 ++ build.zig | 43 ++++++++++++++++ link.ld | 23 +++++++++ src/kernel/kmain.zig | 118 +++++++++++++++++++++++++++++++++++++++++++ src/kernel/start.asm | 10 ++++ src/kernel/start.s | 9 ++++ 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 README.md create mode 100644 build.zig create mode 100644 link.ld create mode 100644 src/kernel/kmain.zig create mode 100644 src/kernel/start.asm create mode 100644 src/kernel/start.s diff --git a/.gitignore b/.gitignore index 18e9d69..849a50a 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,7 @@ *.bin # Intellij -.idea/ \ No newline at end of file +.idea/ + +# Zig +zig-cache/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b09249f --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +Compile: zig build-exe kmain.zig -target i386-freestanding --linker-script link.ld + +Run: qemu-system-i386 -kernel kmain -curses + +To exit qemu: Esc + 2, type `quit` \ No newline at end of file diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..c97c285 --- /dev/null +++ b/build.zig @@ -0,0 +1,43 @@ +// Zig version: 0.4.0 + +const Builder = @import("std").build.Builder; +const builtin = @import("builtin"); +const Array = @import("std").ArrayList; + +pub fn build(b: *Builder) void { + const kernel_out_dir = "bin/kernel"; + const kernel_src = "src/kernel/"; + + var kernel = b.addExecutable("pluto.elf", kernel_src ++ "kmain.zig"); + //kernel.addAssemblyFile(kernel_src ++ "start.s"); + + kernel.setOutputDir(kernel_out_dir); + kernel.setBuildMode(b.standardReleaseOptions()); + kernel.setTarget(builtin.Arch.i386, builtin.Os.freestanding, builtin.Abi.gnu); + kernel.setLinkerScriptPath("link.ld"); + + const run_objcopy = b.addSystemCommand([][]const u8 { + "objcopy", "-O", "binary", "-S", kernel.getOutputPath(), kernel_out_dir ++ "/pluto.bin", + }); + run_objcopy.step.dependOn(&kernel.step); + + b.default_step.dependOn(&run_objcopy.step); + + const run_qemu = b.addSystemCommand([][]const u8 { + "qemu-system-i386", + "-display", "curses", + "-kernel", kernel.getOutputPath(), + }); + + const run_qemu_debug = b.addSystemCommand([][]const u8 { + "qemu-system-i386", + "-display", "curses", + "-kernel", kernel.getOutputPath(), + "-s", "-S", + }); + + run_qemu.step.dependOn(&kernel.step); + //run_qemu_debug.step.dependOn(&kernel.step); + + b.default_step.dependOn(&run_qemu.step); +} \ No newline at end of file diff --git a/link.ld b/link.ld new file mode 100644 index 0000000..85aca9f --- /dev/null +++ b/link.ld @@ -0,0 +1,23 @@ +ENTRY(_start) + +SECTIONS { + . = 1M; + + .text : ALIGN(4K) { + KEEP(*(.multiboot)) + *(.text) + } + + .rodata : ALIGN(4K) { + *(.rodata) + } + + .data : ALIGN(4K) { + *(.data) + } + + .bss : ALIGN(4K) { + *(COMMON) + *(.bss) + } +} \ No newline at end of file diff --git a/src/kernel/kmain.zig b/src/kernel/kmain.zig new file mode 100644 index 0000000..fdeeee1 --- /dev/null +++ b/src/kernel/kmain.zig @@ -0,0 +1,118 @@ +// +// kmain +// Zig version: +// Author: DrDeano +// Date: 2019-03-30 +// +const builtin = @import("builtin"); + +const MultiBoot = packed struct { + magic: i32, + flags: i32, + checksum: i32, +}; + +const ALIGN = 1 << 0; +const MEMINFO = 1 << 1; +const MAGIC = 0x1BADB002; +const FLAGS = ALIGN | MEMINFO; + +export var multiboot align(4) linksection(".multiboot") = MultiBoot { + .magic = MAGIC, + .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 nakedcc fn _start() noreturn { + @newStackCall(stack_bytes_slice, kmain); + while (true) {} +} + +pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { + @setCold(true); + terminal.write("KERNEL PANIC: "); + terminal.write(msg); + while (true) {} +} + +fn kmain() void { + terminal.initialize(); + terminal.write("Hello, kernel World!"); +} + +// Hardware text mode color constants +const VGA_COLOUR = enum(u8) { + VGA_COLOUR_BLACK, + VGA_COLOUR_BLUE, + VGA_COLOUR_GREEN, + VGA_COLOUR_CYAN, + VGA_COLOUR_RED, + VGA_COLOUR_MAGENTA, + VGA_COLOUR_BROWN, + VGA_COLOUR_LIGHT_GREY, + VGA_COLOUR_DARK_GREY, + VGA_COLOUR_LIGHT_BLUE, + VGA_COLOUR_LIGHT_GREEN, + VGA_COLOUR_LIGHT_CYAN, + VGA_COLOUR_LIGHT_RED, + VGA_COLOUR_LIGHT_MAGENTA, + VGA_COLOUR_LIGHT_BROWN, + VGA_COLOUR_WHITE, +}; + +fn vga_entry_colour(fg: VGA_COLOUR, bg: VGA_COLOUR) u8 { + return @enumToInt(fg) | (@enumToInt(bg) << 4); +} + +fn vga_entry(uc: u8, colour: u8) u16 { + return u16(uc) | (u16(colour) << 8); +} + +const VGA_WIDTH = 80; +const VGA_HEIGHT = 25; + +const terminal = struct { + var row = usize(0); + var column = usize(0); + var colour = vga_entry_colour(VGA_COLOUR.VGA_COLOUR_LIGHT_GREY, VGA_COLOUR.VGA_COLOUR_BLACK); + + const buffer = @intToPtr([*]volatile u16, 0xB8000); + + fn initialize() void { + var y = usize(0); + while (y < VGA_HEIGHT) : (y += 1) { + var x = usize(0); + while (x < VGA_WIDTH) : (x += 1) { + putCharAt(' ', colour, x, y); + } + } + } + + fn setColour(new_colour: u8) void { + colour = new_colour; + } + + fn putCharAt(c: u8, new_colour: u8, x: usize, y: usize) void { + const index = y * VGA_WIDTH + x; + buffer[index] = vga_entry(c, new_colour); + } + + fn putChar(c: u8) void { + putCharAt(c, colour, column, row); + column += 1; + if (column == VGA_WIDTH) { + column = 0; + row += 1; + if (row == VGA_HEIGHT) + row = 0; + } + } + + fn write(data: []const u8) void { + for (data) |c| + putChar(c); + } +}; \ No newline at end of file diff --git a/src/kernel/start.asm b/src/kernel/start.asm new file mode 100644 index 0000000..30dfe29 --- /dev/null +++ b/src/kernel/start.asm @@ -0,0 +1,10 @@ + [bits 32] + [section .text] + + [extern kernel_main] +start: + call kernel_main +halt: + cli + hlt + jmp halt diff --git a/src/kernel/start.s b/src/kernel/start.s new file mode 100644 index 0000000..1018b7a --- /dev/null +++ b/src/kernel/start.s @@ -0,0 +1,9 @@ +.global _start +.type _start, @function + +_start: + call kmain +halt: + cli + hlt + jmp halt \ No newline at end of file