const std = @import("std");
const Fs = @import("fs.zig");
const term = @import("term.zig");
const Disk = @import("disk.zig");
const RawPartition = @import("partitions").Partition;
const Partition = @import("partition.zig");
extern const __partition_offset: usize;
export fn _extended_entry(drive: u8, raw_partition: *RawPartition, idx: u8) linksection(".entry") callconv(.C) noreturn {
main(drive, raw_partition, idx) catch |err| @panic(@errorName(err));
@panic("failed to load next stages");
}
fn main(drive: u8, raw_partition: *RawPartition, idx: u8) !void {
enable_a20();
enable_unreal_mode();
term.print("[+] enter extended bootloader\r\n", .{});
term.print("[+] boot args:\r\n- drive: 0x{X:0>2}\r\n- partition: {any}\r\n- index: {}\r\n", .{ drive, raw_partition, idx });
__partition_offset = @ptrToInt(raw_partition);
var disk = Disk.new(drive);
var partition = Partition.from(&disk, raw_partition);
var fs = Fs.from(&partition, 0x7C00);
var boot = try fs.root().open("APP.BIN");
try boot.read(@intToPtr([*]u8, 0x100000)[0..boot.size]);
term.print("[+] switching to bootstrap\r\n", .{});
asm volatile ("jmp _code_16");
@panic("failed extended bootloader\r\n");
}
pub fn panic(static: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
term.fail("[-] PANIC: {s}", .{static});
}
fn enable_a20() void {
asm volatile (
\\.intel_syntax noprefix
\\in al, 0x92
\\test al, 2
\\jnz after
\\or al, 2
\\and al, 0xFE
\\out 0x92, al
\\after:
\\.att_syntax prefix
::: "al");
}
const Segment = packed struct {
limit_lo: u16 = 0,
base_lo: u24 = 0,
accessed: bool = false,
readwrite: bool = false,
grows_down: bool = false,
executable: bool = false,
normal: bool = false,
ring: u2 = 0,
present: bool = false,
limit_hi: u4 = 0,
reserved: bool = false,
long_mode: bool = false,
protected_mode: bool = false,
large: bool = false,
base_hi: u8 = 0,
};
const Descriptor = extern struct {
size: u16 align(1),
gdt: u64 align(1),
};
const gdt = [3]Segment{
.{},
.{ .limit_lo = 0xFFFF, .limit_hi = 0, .base_lo = 0, .base_hi = 0, .readwrite = true, .grows_down = false, .executable = true, .normal = true, .ring = 0, .present = true, .large = false },
.{ .limit_lo = 0xFFFF, .limit_hi = 0xF, .base_lo = 0, .base_hi = 0, .readwrite = true, .grows_down = false, .executable = false, .normal = true, .ring = 0, .present = true, .large = true },
};
export var descriptor = Descriptor{
.size = @sizeOf(@TypeOf(gdt)),
.gdt = undefined,
};
fn enable_unreal_mode() void {
descriptor.gdt = @ptrToInt(&gdt);
asm volatile (
\\.intel_syntax noprefix
\\push ds
\\lgdt [esi]
\\mov eax, cr0
\\or al, 1
\\mov cr0, eax
\\.att_syntax prefix
\\jmp $0x08, $pmode
\\.intel_syntax noprefix
\\pmode:
\\mov bx, 0x10
\\mov ds, bx
\\and al, ~1
\\mov cr0, eax
\\.att_syntax prefix
\\jmp $0x00, $unreal
\\.intel_syntax noprefix
\\unreal:
\\pop ds
\\.att_syntax prefix
:
: [desc] "{esi}" (&descriptor),
: "eax", "bx"
);
}