diff --git a/.envrc b/.envrc deleted file mode 100644 index 8392d15..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9d4506d..30eaa82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ -# Zig -zig-* -.zig-* +.zig-cache/ +zig-out/ -# Nix -result* +.envrc +.direnv/ -# Misc -.direnv diff --git a/build.zig b/build.zig index e256efa..3a4f63b 100644 --- a/build.zig +++ b/build.zig @@ -1,32 +1,31 @@ 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)); - +pub fn build(b: *std.Build) void { const target = b.resolveTargetQuery(.{ .cpu_arch = std.Target.Cpu.Arch.x86, + .ofmt = std.Target.ObjectFormat.elf, .abi = std.Target.Abi.none, .os_tag = std.Target.Os.Tag.freestanding, - .cpu_features_sub = disabled_features, - .cpu_features_add = enabled_features, + .cpu_features_sub = std.Target.x86.featureSet(&.{ + .mmx, + .sse, + .sse2, + .avx, + .avx2, + }), + .cpu_features_add = std.Target.x86.featureSet(&.{ + .soft_float, + }), }); + const optimize = b.standardOptimizeOption(.{}); + const kernel = b.addExecutable(.{ - .name = "kernel.elf", + .name = "kernel", .root_module = b.createModule(.{ - .root_source_file = b.path("src/main.zig"), .target = target, - .optimize = .ReleaseFast, - .code_model = .kernel, + .optimize = optimize, + .root_source_file = b.path("src/main.zig"), }), }); kernel.setLinkerScript(b.path("kernel.ld")); @@ -42,3 +41,4 @@ pub fn build(b: *std.Build) !void { const run = b.step("run", "Run QEMU"); run.dependOn(&qemu.step); } + diff --git a/flake.lock b/flake.lock index bbb64ca..d680c26 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1762363567, - "narHash": "sha256-YRqMDEtSMbitIMj+JLpheSz0pwEr0Rmy5mC7myl17xs=", + "lastModified": 1757745802, + "narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ae814fd3904b621d8ab97418f1d0f2eb0d3716f4", + "rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1", "type": "github" }, "original": { diff --git a/src/Console.zig b/src/Console.zig index 6b75378..0825e73 100644 --- a/src/Console.zig +++ b/src/Console.zig @@ -119,29 +119,22 @@ const Writer = struct { console: *Self, interface: std.Io.Writer, - fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { - const self: *@This() = @fieldParentPtr("interface", io_w); + fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + _ = splat; - try self.puts(io_w.buffered()); - io_w.end = 0; + const self: *@This() = @alignCast(@fieldParentPtr("interface", w)); - for (data[0..data.len - 1]) |bytes| { - try self.puts(bytes); + const buffered = w.buffered(); + if (buffered.len != 0) { + self.console.puts(buffered); + return w.consume(buffered.len); } - const pattern = data[data.len - 1]; - for (0..splat) |_| { - try self.puts(pattern); - } - - return std.Io.Writer.countSplat(data, splat); - } - - fn puts(self: *@This(), data: []const u8) std.Io.Writer.Error!void { - self.console.puts(data); + self.console.puts(data[0]); + return data[0].len; } }; -pub fn writer(self: *Self, buffer: []u8) Writer { +fn writer(self: *Self, buffer: []u8) Writer { return .{ .console = self, .interface = .{ @@ -154,10 +147,7 @@ pub fn writer(self: *Self, buffer: []u8) Writer { } pub fn printf(self: *Self, comptime format: []const u8, args: anytype) void { - var buffer: [1024]u8 = undefined; - var w = self.writer(&buffer); - const io_w = &w.interface; - io_w.print(format, args) catch unreachable; - io_w.flush() catch unreachable; + var w = self.writer(&.{}); + w.interface.print(format, args) catch unreachable; } diff --git a/src/main.zig b/src/main.zig index dd4f020..727bbc9 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,23 +1,21 @@ const lazy = @import("utils/Lazy.zig").lazy; const Console = @import("Console.zig"); -const MultibootInfo = @import("multiboot.zig").Info; - -const MultibootHeader = packed struct { - magic: i32, - flags: i32, - checksum: i32, - padding: u32, -}; 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, + padding: u32 = 0, +}; + export var mutliboot: MultibootHeader align(4) linksection(".multiboot") = .{ - .magic = MAGIC, .flags = FLAGS, .checksum = -(MAGIC + FLAGS), - .padding = 0, }; var stack_bytes: [16 * 1024]u8 align(16) linksection(".bss") = undefined; @@ -26,8 +24,6 @@ export fn _start() callconv(.naked) noreturn { asm volatile ( \\ movl %[stack_top], %%esp \\ movl %%esp, %%ebp - \\ push %%ebx - \\ push %%eax \\ call %[kmain:P] : : [stack_top] "i" (@as([*]align(16) u8, @ptrCast(&stack_bytes)) + @sizeOf(@TypeOf(stack_bytes))), @@ -37,23 +33,13 @@ export fn _start() callconv(.naked) noreturn { var console = lazy(Console, .init); -fn kmain(magic: u32, info: *const MultibootInfo) callconv(.c) void { - std.debug.assert(magic == MAGIC); +fn kmain() callconv(.c) void { + std.log.info("This is an info message", .{}); + std.log.debug("This is a debug message!", .{}); + std.log.warn("This is a warning message!", .{}); + std.log.err("This is an error message!", .{}); - std.log.info("{any}", .{info}); - - if (info.isValid(.boot_loader_name)) { - std.log.info("Booted by {s}", .{info.boot_loader_name}); - } - if (info.isValid(.cmdline)) { - std.log.info("Booted with cmdline \"{s}\"", .{info.cmdline}); - } - - hang(); -} - -fn hang() noreturn { - while (true) asm volatile ("hlt"); + @panic("Uh oh"); } const std = @import("std"); @@ -65,7 +51,7 @@ fn kpanic(msg: []const u8, first_trace_addr: ?usize) noreturn { std.log.err("PANIC: {s}", .{msg}); - hang(); + while (true) {} } pub const std_options = std.Options{ @@ -87,11 +73,13 @@ fn klog( .info => Console.ConsoleColor.light_blue, .debug => Console.ConsoleColor.light_green, }; - c.putChar('['); - c.setColor(color, Console.ConsoleColor.black); - c.puts(level.asText()); - c.resetColor(); + { + c.setColor(color, Console.ConsoleColor.black); + defer c.resetColor(); + + c.puts(level.asText()); + } c.putChar(']'); c.putChar(' '); @@ -102,3 +90,4 @@ fn klog( c.printf(format ++ "\n", args); } + diff --git a/src/multiboot.zig b/src/multiboot.zig index 9863d22..d30a255 100644 --- a/src/multiboot.zig +++ b/src/multiboot.zig @@ -1,96 +1,56 @@ -const std = @import("std"); - -const BootModule = packed struct { - start: u32, - end: u32, - string: ?[*:0]u8, - reserved: u32, +pub const Info = extern struct { + flags: c_uint, + mem_lower: c_uint, + mem_upper: c_uint, + boot_device: c_uint, + cmdline: c_uint, + mods_count: c_uint, + mods_addr: c_uint, + u: extern union { + aout_sym: extern struct { + tabsize: c_uint, + strsize: c_uint, + addr: c_uint, + reserved: c_uint, + }, + elf_sec: extern struct { + num: c_uint, + size: c_uint, + addr: c_uint, + shndx: c_uint, + }, + }, + mmap_length: c_uint, + mmap_addr: c_uint, + drives_length: c_uint, + drives_addr: c_uint, + config_table: c_uint, + boot_loader_name: c_uint, + apm_table: c_uint, + vbe_control_info: c_uint, + vbe_move_info: c_uint, + vbe_mode: c_ushort, + vbe_interface_seg: c_ushort, + vbe_interface_off: c_ushort, + vbe_interface_len: c_ushort, + framebuffer_addr: c_ulonglong, + framebuffer_pitch: c_uint, + framebuffer_width: c_uint, + framebuffer_height: c_uint, + framebuffer_bpp: u8, + framebuffer_type: u8, + unnamed_0: extern union { + unnamed_0: extern struct { + framebuffer_palette_addr: c_uint, + framebuffer_palette_num_colors: c_ushort, + }, + unnamed_1: extern struct { + framebuffer_red_field_position: u8, + framebuffer_red_mask_size: u8, + framebuffer_green_field_position: u8, + framebuffer_green_mask_size: u8, + framebuffer_blue_field_position: u8, + framebuffer_blue_mask_size: u8, + }, + }, }; - -pub const Info = packed struct { - flags: std.bit_set.IntegerBitSet(32), - mem_lower: u32, - mem_upper: u32, - boot_device: packed struct { - part3: u8, - part2: u8, - part1: u8, - drive: u8, - }, - cmdline: [*:0]u8, - mods_count: u32, - mods_addr: [*]BootModule, - u: packed union { - aout_sym: packed struct { - tabsize: u32, - strsize: u32, - addr: u32, - reserved: u32, - }, - elf_sec: packed struct { - num: u32, - size: u32, - addr: u32, - shndx: u32, - }, - }, - mmap_length: u32, - mmap_addr: u32, - drives_length: u32, - drives_addr: u32, - config_table: u32, - boot_loader_name: [*:0]u8, - apm_table: u32, - vbe: packed struct { - control_info: u32, - move_info: u32, - mode: u16, - interface_seg: u16, - interface_off: u16, - interface_len: u16, - }, - framebuffer: packed struct { - addr: u64, - pitch: u32, - width: u32, - height: u32, - bpp: u8, - type: u8, - color_info: packed union { - indexed_color: packed struct { - framebuffer_palette_addr: u32, - framebuffer_palette_num_colors: u16, - }, - rgb_color: packed struct { - framebuffer_red_field_position: u8, - framebuffer_red_mask_size: u8, - framebuffer_green_field_position: u8, - framebuffer_green_mask_size: u8, - framebuffer_blue_field_position: u8, - framebuffer_blue_mask_size: u8, - }, - }, - }, - - const Self = @This(); - - pub fn isValid(self: *const Self, comptime field: std.meta.FieldEnum(Self)) bool { - return switch (field) { - .flags => true, - .mem_lower, .mem_upper => self.flags.isSet(0), - .boot_device => self.flags.isSet(1), - .cmdline => self.flags.isSet(2), - .mods_count, .mods_addr => self.flags.isSet(3), - // TODO: .u => either 4 or 5 - .mmap_length, .mmap_addr => self.flags.isSet(6), - .drives_length, .drives_addr => self.flags.isSet(7), - .config_table => self.flags.isSet(8), - .boot_loader_name => self.flags.isSet(9), - .apm_table => self.flags.isSet(10), - .vbe => self.flags.isSet(11), - .framebuffer => self.flags.isSet(12), - else => false, - }; - } -}; -