aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mirai/kernel/boot.zig92
-rw-r--r--mirai/kernel/mirai.zig133
2 files changed, 225 insertions, 0 deletions
diff --git a/mirai/kernel/boot.zig b/mirai/kernel/boot.zig
new file mode 100644
index 0000000..8d46901
--- /dev/null
+++ b/mirai/kernel/boot.zig
@@ -0,0 +1,92 @@
+//! Mirai Boot Parameters
+//!
+//! This structure matches what Hikari bootloader passes to the kernel.
+
+pub const boot_params_magic: u64 = 0x494152494D424B41; // "AKBMIRAI"
+pub const boot_params_version: u32 = 1;
+
+pub const BootParams = extern struct {
+ magic: u64,
+ version: u32,
+ size: u32,
+
+ framebuffer: FramebufferInfo,
+ memory_map: MemoryMapInfo,
+ kernel: KernelInfo,
+ acpi: AcpiInfo,
+ boot_time: u64,
+
+ reserved: [256]u8,
+
+ pub fn is_valid(self: *const BootParams) bool {
+ return self.magic == boot_params_magic and
+ self.version == boot_params_version;
+ }
+};
+
+pub const FramebufferInfo = extern struct {
+ base: u64,
+ size: u64,
+ width: u32,
+ height: u32,
+ stride: u32,
+ pixel_format: PixelFormat,
+ red_mask_size: u8,
+ red_mask_shift: u8,
+ green_mask_size: u8,
+ green_mask_shift: u8,
+ blue_mask_size: u8,
+ blue_mask_shift: u8,
+ reserved: [2]u8,
+};
+
+pub const PixelFormat = enum(u32) {
+ rgb = 0,
+ bgr = 1,
+ bitmask = 2,
+ unknown = 255,
+};
+
+pub const MemoryMapInfo = extern struct {
+ entries: u64,
+ entry_count: u32,
+ entry_size: u32,
+ descriptor_version: u32,
+ reserved: u32,
+};
+
+pub const MemoryRegion = extern struct {
+ base: u64,
+ size: u64,
+ region_type: MemoryType,
+ attributes: u64,
+};
+
+pub const MemoryType = enum(u32) {
+ usable = 0,
+ reserved = 1,
+ acpi_reclaimable = 2,
+ acpi_nvs = 3,
+ bad_memory = 4,
+ bootloader_reclaimable = 5,
+ kernel = 6,
+ framebuffer = 7,
+};
+
+pub const KernelInfo = extern struct {
+ physical_base: u64,
+ virtual_base: u64,
+ size: u64,
+ entry_point: u64,
+ pml4_address: u64,
+ physmap_base: u64,
+ physmap_size: u64,
+ stack_top: u64,
+ stack_size: u64,
+};
+
+pub const AcpiInfo = extern struct {
+ rsdp_address: u64,
+ rsdp_version: u32,
+ reserved: u32,
+};
diff --git a/mirai/kernel/mirai.zig b/mirai/kernel/mirai.zig
new file mode 100644
index 0000000..5d2bc66
--- /dev/null
+++ b/mirai/kernel/mirai.zig
@@ -0,0 +1,133 @@
+//! Mirai - AkibaOS Kernel
+//!
+//! The kernel receives boot parameters from Hikari bootloader
+//! and initializes the system.
+
+const boot = @import("boot.zig");
+
+pub export fn mirai(boot_params_ptr: *boot.BootParams) callconv(.{ .x86_64_sysv = .{} }) noreturn {
+ // Validate boot parameters
+ if (!boot_params_ptr.is_valid()) {
+ // Invalid boot params - halt with error pattern
+ if (boot_params_ptr.framebuffer.base != 0) {
+ draw_error_screen(boot_params_ptr);
+ }
+ halt();
+ }
+
+ // Draw success screen
+ draw_boot_screen(boot_params_ptr);
+
+ // Halt for now
+ halt();
+}
+
+fn draw_boot_screen(params: *boot.BootParams) void {
+ const fb = params.framebuffer;
+ const base: [*]u32 = @ptrFromInt(fb.base);
+ const stride = fb.stride;
+
+ // Clear screen to dark purple (Akiba theme)
+ const bg_color: u32 = switch (fb.pixel_format) {
+ .rgb => 0x1E0030, // RGB
+ .bgr => 0x30001E, // BGR
+ else => 0x1E0030,
+ };
+
+ var y: u32 = 0;
+ while (y < fb.height) : (y += 1) {
+ var x: u32 = 0;
+ while (x < fb.width) : (x += 1) {
+ base[y * stride + x] = bg_color;
+ }
+ }
+
+ // Draw "MIRAI" banner in cyan
+ const text_color: u32 = switch (fb.pixel_format) {
+ .rgb => 0x00FFFF, // RGB cyan
+ .bgr => 0xFFFF00, // BGR cyan
+ else => 0x00FFFF,
+ };
+
+ const banner = [_][]const u8{
+ " M M III RRRR A III ",
+ " MM MM I R R A A I ",
+ " M M M I RRRR AAAAA I ",
+ " M M I R R A A I ",
+ " M M III R R A A III ",
+ };
+
+ const start_x = (fb.width - 31 * 8) / 2;
+ const start_y = fb.height / 3;
+
+ for (banner, 0..) |line, row| {
+ for (line, 0..) |char, col| {
+ if (char != ' ') {
+ draw_block(base, stride, start_x + @as(u32, @truncate(col)) * 8, start_y + @as(u32, @truncate(row)) * 12, text_color);
+ }
+ }
+ }
+
+ // Draw "AkibaOS" subtitle
+ const subtitle = "AkibaOS Kernel Loaded Successfully";
+ const subtitle_x = (fb.width - @as(u32, @truncate(subtitle.len)) * 8) / 2;
+ const subtitle_y = start_y + 80;
+
+ for (0..subtitle.len) |i| {
+ draw_small_block(base, stride, subtitle_x + @as(u32, @truncate(i)) * 8, subtitle_y, 0xFF80C0);
+ }
+}
+
+fn draw_error_screen(params: *boot.BootParams) void {
+ const fb = params.framebuffer;
+ const base: [*]u32 = @ptrFromInt(fb.base);
+ const stride = fb.stride;
+
+ // Fill with red
+ const error_color: u32 = switch (fb.pixel_format) {
+ .rgb => 0xFF0000,
+ .bgr => 0x0000FF,
+ else => 0xFF0000,
+ };
+
+ var y: u32 = 0;
+ while (y < fb.height) : (y += 1) {
+ var x: u32 = 0;
+ while (x < fb.width) : (x += 1) {
+ base[y * stride + x] = error_color;
+ }
+ }
+}
+
+fn draw_block(base: [*]u32, stride: u32, x: u32, y: u32, color: u32) void {
+ var dy: u32 = 0;
+ while (dy < 10) : (dy += 1) {
+ var dx: u32 = 0;
+ while (dx < 6) : (dx += 1) {
+ base[(y + dy) * stride + x + dx] = color;
+ }
+ }
+}
+
+fn draw_small_block(base: [*]u32, stride: u32, x: u32, y: u32, color: u32) void {
+ var dy: u32 = 0;
+ while (dy < 2) : (dy += 1) {
+ var dx: u32 = 0;
+ while (dx < 6) : (dx += 1) {
+ base[(y + dy) * stride + x + dx] = color;
+ }
+ }
+}
+
+fn halt() noreturn {
+ while (true) {
+ asm volatile ("hlt");
+ }
+}
+
+pub fn panic(msg: []const u8, stack_trace: ?*@import("std").builtin.StackTrace, ret_addr: ?usize) noreturn {
+ _ = msg;
+ _ = stack_trace;
+ _ = ret_addr;
+ halt();
+}