Compare commits

..

No commits in common. "5f2e19904d1f2d4cf41df41b1227888b5898480b" and "2e9292be6e7903c924449d5b7e2e0d4b46edc6c7" have entirely different histories.

7 changed files with 179 additions and 114 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

11
.gitignore vendored
View file

@ -1,6 +1,9 @@
.zig-cache/ # Zig
zig-out/ zig-*
.zig-*
.envrc # Nix
.direnv/ result*
# Misc
.direnv

View file

@ -1,31 +1,32 @@
const std = @import("std"); const std = @import("std");
pub fn build(b: *std.Build) void { 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 = b.resolveTargetQuery(.{ const target = b.resolveTargetQuery(.{
.cpu_arch = std.Target.Cpu.Arch.x86, .cpu_arch = std.Target.Cpu.Arch.x86,
.ofmt = std.Target.ObjectFormat.elf,
.abi = std.Target.Abi.none, .abi = std.Target.Abi.none,
.os_tag = std.Target.Os.Tag.freestanding, .os_tag = std.Target.Os.Tag.freestanding,
.cpu_features_sub = std.Target.x86.featureSet(&.{ .cpu_features_sub = disabled_features,
.mmx, .cpu_features_add = enabled_features,
.sse,
.sse2,
.avx,
.avx2,
}),
.cpu_features_add = std.Target.x86.featureSet(&.{
.soft_float,
}),
}); });
const optimize = b.standardOptimizeOption(.{});
const kernel = b.addExecutable(.{ const kernel = b.addExecutable(.{
.name = "kernel", .name = "kernel.elf",
.root_module = b.createModule(.{ .root_module = b.createModule(.{
.target = target,
.optimize = optimize,
.root_source_file = b.path("src/main.zig"), .root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = .ReleaseFast,
.code_model = .kernel,
}), }),
}); });
kernel.setLinkerScript(b.path("kernel.ld")); kernel.setLinkerScript(b.path("kernel.ld"));
@ -41,4 +42,3 @@ pub fn build(b: *std.Build) void {
const run = b.step("run", "Run QEMU"); const run = b.step("run", "Run QEMU");
run.dependOn(&qemu.step); run.dependOn(&qemu.step);
} }

6
flake.lock generated
View file

@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1757745802, "lastModified": 1762363567,
"narHash": "sha256-hLEO2TPj55KcUFUU1vgtHE9UEIOjRcH/4QbmfHNF820=", "narHash": "sha256-YRqMDEtSMbitIMj+JLpheSz0pwEr0Rmy5mC7myl17xs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1", "rev": "ae814fd3904b621d8ab97418f1d0f2eb0d3716f4",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -119,22 +119,29 @@ const Writer = struct {
console: *Self, console: *Self,
interface: std.Io.Writer, interface: std.Io.Writer,
fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize {
_ = splat; const self: *@This() = @fieldParentPtr("interface", io_w);
const self: *@This() = @alignCast(@fieldParentPtr("interface", w)); try self.puts(io_w.buffered());
io_w.end = 0;
const buffered = w.buffered(); for (data[0..data.len - 1]) |bytes| {
if (buffered.len != 0) { try self.puts(bytes);
self.console.puts(buffered);
return w.consume(buffered.len);
} }
self.console.puts(data[0]); const pattern = data[data.len - 1];
return data[0].len; 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);
} }
}; };
fn writer(self: *Self, buffer: []u8) Writer { pub fn writer(self: *Self, buffer: []u8) Writer {
return .{ return .{
.console = self, .console = self,
.interface = .{ .interface = .{
@ -147,7 +154,10 @@ fn writer(self: *Self, buffer: []u8) Writer {
} }
pub fn printf(self: *Self, comptime format: []const u8, args: anytype) void { pub fn printf(self: *Self, comptime format: []const u8, args: anytype) void {
var w = self.writer(&.{}); var buffer: [1024]u8 = undefined;
w.interface.print(format, args) catch unreachable; var w = self.writer(&buffer);
const io_w = &w.interface;
io_w.print(format, args) catch unreachable;
io_w.flush() catch unreachable;
} }

View file

@ -1,21 +1,23 @@
const lazy = @import("utils/Lazy.zig").lazy; const lazy = @import("utils/Lazy.zig").lazy;
const Console = @import("Console.zig"); 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 ALIGN = 1 << 0;
const MEMINFO = 1 << 1; const MEMINFO = 1 << 1;
const MAGIC = 0x1BADB002; const MAGIC = 0x1BADB002;
const FLAGS = ALIGN | MEMINFO; 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") = .{ export var mutliboot: MultibootHeader align(4) linksection(".multiboot") = .{
.magic = MAGIC,
.flags = FLAGS, .flags = FLAGS,
.checksum = -(MAGIC + FLAGS), .checksum = -(MAGIC + FLAGS),
.padding = 0,
}; };
var stack_bytes: [16 * 1024]u8 align(16) linksection(".bss") = undefined; var stack_bytes: [16 * 1024]u8 align(16) linksection(".bss") = undefined;
@ -24,6 +26,8 @@ export fn _start() callconv(.naked) noreturn {
asm volatile ( asm volatile (
\\ movl %[stack_top], %%esp \\ movl %[stack_top], %%esp
\\ movl %%esp, %%ebp \\ movl %%esp, %%ebp
\\ push %%ebx
\\ push %%eax
\\ call %[kmain:P] \\ call %[kmain:P]
: :
: [stack_top] "i" (@as([*]align(16) u8, @ptrCast(&stack_bytes)) + @sizeOf(@TypeOf(stack_bytes))), : [stack_top] "i" (@as([*]align(16) u8, @ptrCast(&stack_bytes)) + @sizeOf(@TypeOf(stack_bytes))),
@ -33,13 +37,23 @@ export fn _start() callconv(.naked) noreturn {
var console = lazy(Console, .init); var console = lazy(Console, .init);
fn kmain() callconv(.c) void { fn kmain(magic: u32, info: *const MultibootInfo) callconv(.c) void {
std.log.info("This is an info message", .{}); std.debug.assert(magic == MAGIC);
std.log.debug("This is a debug message!", .{});
std.log.warn("This is a warning message!", .{});
std.log.err("This is an error message!", .{});
@panic("Uh oh"); 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");
} }
const std = @import("std"); const std = @import("std");
@ -51,7 +65,7 @@ fn kpanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
std.log.err("PANIC: {s}", .{msg}); std.log.err("PANIC: {s}", .{msg});
while (true) {} hang();
} }
pub const std_options = std.Options{ pub const std_options = std.Options{
@ -73,13 +87,11 @@ fn klog(
.info => Console.ConsoleColor.light_blue, .info => Console.ConsoleColor.light_blue,
.debug => Console.ConsoleColor.light_green, .debug => Console.ConsoleColor.light_green,
}; };
c.putChar('[');
{
c.setColor(color, Console.ConsoleColor.black);
defer c.resetColor();
c.puts(level.asText()); c.putChar('[');
} c.setColor(color, Console.ConsoleColor.black);
c.puts(level.asText());
c.resetColor();
c.putChar(']'); c.putChar(']');
c.putChar(' '); c.putChar(' ');
@ -90,4 +102,3 @@ fn klog(
c.printf(format ++ "\n", args); c.printf(format ++ "\n", args);
} }

View file

@ -1,56 +1,96 @@
pub const Info = extern struct { const std = @import("std");
flags: c_uint,
mem_lower: c_uint, const BootModule = packed struct {
mem_upper: c_uint, start: u32,
boot_device: c_uint, end: u32,
cmdline: c_uint, string: ?[*:0]u8,
mods_count: c_uint, reserved: u32,
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,
};
}
};