Compare commits
No commits in common. "5f2e19904d1f2d4cf41df41b1227888b5898480b" and "2e9292be6e7903c924449d5b7e2e0d4b46edc6c7" have entirely different histories.
5f2e19904d
...
2e9292be6e
7 changed files with 179 additions and 114 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -1,6 +1,9 @@
|
||||||
.zig-cache/
|
# Zig
|
||||||
zig-out/
|
zig-*
|
||||||
|
.zig-*
|
||||||
|
|
||||||
.envrc
|
# Nix
|
||||||
.direnv/
|
result*
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.direnv
|
||||||
|
|
|
||||||
36
build.zig
36
build.zig
|
|
@ -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
6
flake.lock
generated
|
|
@ -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": {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
53
src/main.zig
53
src/main.zig
|
|
@ -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.putChar('[');
|
||||||
|
c.setColor(color, Console.ConsoleColor.black);
|
||||||
c.puts(level.asText());
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,67 @@
|
||||||
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 {
|
pub const Info = packed struct {
|
||||||
tabsize: c_uint,
|
flags: std.bit_set.IntegerBitSet(32),
|
||||||
strsize: c_uint,
|
mem_lower: u32,
|
||||||
addr: c_uint,
|
mem_upper: u32,
|
||||||
reserved: c_uint,
|
boot_device: packed struct {
|
||||||
|
part3: u8,
|
||||||
|
part2: u8,
|
||||||
|
part1: u8,
|
||||||
|
drive: u8,
|
||||||
},
|
},
|
||||||
elf_sec: extern struct {
|
cmdline: [*:0]u8,
|
||||||
num: c_uint,
|
mods_count: u32,
|
||||||
size: c_uint,
|
mods_addr: [*]BootModule,
|
||||||
addr: c_uint,
|
u: packed union {
|
||||||
shndx: c_uint,
|
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: c_uint,
|
mmap_length: u32,
|
||||||
mmap_addr: c_uint,
|
mmap_addr: u32,
|
||||||
drives_length: c_uint,
|
drives_length: u32,
|
||||||
drives_addr: c_uint,
|
drives_addr: u32,
|
||||||
config_table: c_uint,
|
config_table: u32,
|
||||||
boot_loader_name: c_uint,
|
boot_loader_name: [*:0]u8,
|
||||||
apm_table: c_uint,
|
apm_table: u32,
|
||||||
vbe_control_info: c_uint,
|
vbe: packed struct {
|
||||||
vbe_move_info: c_uint,
|
control_info: u32,
|
||||||
vbe_mode: c_ushort,
|
move_info: u32,
|
||||||
vbe_interface_seg: c_ushort,
|
mode: u16,
|
||||||
vbe_interface_off: c_ushort,
|
interface_seg: u16,
|
||||||
vbe_interface_len: c_ushort,
|
interface_off: u16,
|
||||||
framebuffer_addr: c_ulonglong,
|
interface_len: u16,
|
||||||
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: 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_field_position: u8,
|
||||||
framebuffer_red_mask_size: u8,
|
framebuffer_red_mask_size: u8,
|
||||||
framebuffer_green_field_position: u8,
|
framebuffer_green_field_position: u8,
|
||||||
|
|
@ -53,4 +70,27 @@ pub const Info = extern struct {
|
||||||
framebuffer_blue_mask_size: 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,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue