diff options
| author | Bobby <[email protected]> | 2026-02-24 09:29:01 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-02-24 09:29:01 +0530 |
| commit | f3513909b8c02cd2d9723c4e908abedefb54d1fd (patch) | |
| tree | 87daac051c2dcf4d6dbe10f16c38957d9b8f6a57 | |
| parent | 60f4c2824c63cef87fea0227ed7229268d1b2931 (diff) | |
| download | akiba-f3513909b8c02cd2d9723c4e908abedefb54d1fd.tar.xz akiba-f3513909b8c02cd2d9723c4e908abedefb54d1fd.zip | |
feat: Implement Mirai kernel with boot parameter handling and framebuffer support
| -rw-r--r-- | mirai/kernel/boot.zig | 92 | ||||
| -rw-r--r-- | mirai/kernel/mirai.zig | 133 |
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(); +} |
