paging almost done, endianess problem for now

This commit is contained in:
Jack Halford 2019-08-13 22:37:05 +02:00
parent e619364f71
commit e832dede16
19 changed files with 270 additions and 137 deletions

View file

@ -24,6 +24,8 @@ slowly porting from rust.
`./qemu.sh monitor` `./qemu.sh monitor`
`./qemu.sh gdb` `./qemu.sh gdb`
### todo # Notes
- recycling allocator that wraps the bump allocator ## interrupts
`interrupt` -> `idt[n]` -> `isrN` -> `isrDispatch` -> `handlers[n]` (default `unhandled()`)

View file

@ -2,7 +2,7 @@ const Builder = @import("std").build.Builder;
const builtin = @import("builtin"); const builtin = @import("builtin");
pub fn build(b: *Builder) void { pub fn build(b: *Builder) void {
const kernel = b.addExecutable("bzImage", "src/arch/x86/main.zig"); const kernel = b.addExecutable("kernel", "src/arch/x86/main.zig");
kernel.addPackagePath("kernel", "src/index.zig"); kernel.addPackagePath("kernel", "src/index.zig");
kernel.addPackagePath("arch", "src/arch/x86/lib/index.zig"); kernel.addPackagePath("arch", "src/arch/x86/lib/index.zig");
kernel.setOutputDir("build"); kernel.setOutputDir("build");
@ -10,6 +10,7 @@ pub fn build(b: *Builder) void {
kernel.addAssemblyFile("src/arch/x86/_start.s"); kernel.addAssemblyFile("src/arch/x86/_start.s");
kernel.addAssemblyFile("src/arch/x86/gdt.s"); kernel.addAssemblyFile("src/arch/x86/gdt.s");
kernel.addAssemblyFile("src/arch/x86/isr.s"); kernel.addAssemblyFile("src/arch/x86/isr.s");
kernel.addAssemblyFile("src/arch/x86/paging.s");
kernel.setBuildMode(b.standardReleaseOptions()); kernel.setBuildMode(b.standardReleaseOptions());
kernel.setTarget(builtin.Arch.i386, builtin.Os.freestanding, builtin.Abi.none); kernel.setTarget(builtin.Arch.i386, builtin.Os.freestanding, builtin.Abi.none);

View file

@ -1,7 +1,7 @@
QEMU_SOCKET=/tmp/qemu.sock QEMU_SOCKET=/tmp/qemu.sock
QEMU_MONITOR="socat - UNIX-CONNECT:${QEMU_SOCKET}" QEMU_MONITOR="socat - UNIX-CONNECT:${QEMU_SOCKET}"
QEMU_GDB_PORT=4242 QEMU_GDB_PORT=4242
KERNEL=build/bzImage KERNEL=build/kernel
start() { start() {
sudo pkill -9 qemu sudo pkill -9 qemu
@ -10,11 +10,11 @@ start() {
-monitor unix:${QEMU_SOCKET},server,nowait \ -monitor unix:${QEMU_SOCKET},server,nowait \
-enable-kvm \ -enable-kvm \
-m 1337M \ -m 1337M \
-display curses \ -curses \
-serial mon:stdio \ -serial mon:stdio \
-append "Hello" \ -append "Hello" \
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
-kernel ${KERNEL} -kernel ${KERNEL}
# -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
# build/kernel.iso # build/kernel.iso
"$@" "$@"
} }

View file

@ -72,7 +72,7 @@ fn makeEntry(base: usize, limit: usize, access: u8, flags: u4) GDTEntry {
} }
// Fill in the GDT. // Fill in the GDT.
var gdt align(4) = []GDTEntry{ var gdt align(4) = [_]GDTEntry{
makeEntry(0, 0, 0, 0), makeEntry(0, 0, 0, 0),
makeEntry(0, 0xFFFFF, KERNEL | CODE, PROTECTED | BLOCKS_4K), makeEntry(0, 0xFFFFF, KERNEL | CODE, PROTECTED | BLOCKS_4K),
makeEntry(0, 0xFFFFF, KERNEL | DATA, PROTECTED | BLOCKS_4K), makeEntry(0, 0xFFFFF, KERNEL | DATA, PROTECTED | BLOCKS_4K),
@ -92,7 +92,7 @@ var tss = TSS{
.unused1 = 0, .unused1 = 0,
.esp0 = undefined, .esp0 = undefined,
.ss0 = KERNEL_DATA, .ss0 = KERNEL_DATA,
.unused2 = []u32{0} ** 22, .unused2 = [_]u32{0} ** 22,
.unused3 = 0, .unused3 = 0,
.iomap_base = @sizeOf(TSS), .iomap_base = @sizeOf(TSS),
}; };

View file

@ -1,4 +1,5 @@
// https://wiki.osdev.org/IDT // https://wiki.osdev.org/IDT
usingnamespace @import("../../vga.zig");
const x86 = @import("lib/index.zig"); const x86 = @import("lib/index.zig");
const interrupt = @import("interrupt.zig"); const interrupt = @import("interrupt.zig");
const gdt = @import("gdt.zig"); const gdt = @import("gdt.zig");
@ -47,12 +48,18 @@ pub fn setGate(n: u8, flags: u8, offset: extern fn () void) void {
idt[n].flags = flags; idt[n].flags = flags;
idt[n].zero = 0; idt[n].zero = 0;
idt[n].selector = gdt.KERNEL_CODE; idt[n].selector = gdt.KERNEL_CODE;
println("offset: 0x{x}", @ptrToInt(offset));
println("low : 0x{x}", idt[n].offset_low);
println("high : 0x{x}", idt[n].offset_high);
} }
//// ////
// Initialize the Interrupt Descriptor Table. // Initialize the Interrupt Descriptor Table.
// //
pub fn initialize() void { pub fn initialize() void {
// configure PIC and set ISRs
interrupt.initialize(); interrupt.initialize();
// load IDT
x86.lidt(@ptrToInt(&idtr)); x86.lidt(@ptrToInt(&idtr));
} }

View file

@ -1,5 +1,6 @@
const x86 = @import("lib/index.zig"); const x86 = @import("lib/index.zig");
const isr = @import("isr.zig"); const isr = @import("isr.zig");
const println = @import("../../vga.zig").println;
// PIC ports. // PIC ports.
const PIC1_CMD = 0x20; const PIC1_CMD = 0x20;
@ -31,11 +32,11 @@ var handlers = [_]fn () void{unhandled} ** 48;
fn unhandled() noreturn { fn unhandled() noreturn {
const n = isr.context.interrupt_n; const n = isr.context.interrupt_n;
// if (n >= IRQ_0) { if (n < IRQ_0) {
// tty.panic("unhandled IRQ number {d}", n - IRQ_0); println("unhandled exception number {d}", n);
// } else { } else {
// tty.panic("unhandled exception number {d}", n); println("unhandled IRQ number {d} (intr {d})", n - IRQ_0, n);
// } }
x86.hang(); x86.hang();
} }
@ -177,6 +178,7 @@ pub fn maskIRQ(irq: u8, mask: bool) void {
} else { } else {
x86.outb(port, old & ~(u8(1) << shift)); x86.outb(port, old & ~(u8(1) << shift));
} }
const new = x86.inb(port); // Retrieve the current mask.
} }
//// ////

View file

@ -135,24 +135,24 @@ pub fn install() void {
idt.setGate(30, idt.INTERRUPT_GATE, isr30); idt.setGate(30, idt.INTERRUPT_GATE, isr30);
idt.setGate(31, idt.INTERRUPT_GATE, isr31); idt.setGate(31, idt.INTERRUPT_GATE, isr31);
// // IRQs. // IRQs.
idt.setGate(32, idt.INTERRUPT_GATE, isr32); idt.setGate(32, idt.INTERRUPT_GATE, isr32);
idt.setGate(33, idt.INTERRUPT_GATE, isr33); idt.setGate(33, idt.INTERRUPT_GATE, isr33);
// idt.setGate(34, idt.INTERRUPT_GATE, isr34); idt.setGate(34, idt.INTERRUPT_GATE, isr34);
// idt.setGate(35, idt.INTERRUPT_GATE, isr35); idt.setGate(35, idt.INTERRUPT_GATE, isr35);
// idt.setGate(36, idt.INTERRUPT_GATE, isr36); idt.setGate(36, idt.INTERRUPT_GATE, isr36);
// idt.setGate(37, idt.INTERRUPT_GATE, isr37); idt.setGate(37, idt.INTERRUPT_GATE, isr37);
// idt.setGate(38, idt.INTERRUPT_GATE, isr38); idt.setGate(38, idt.INTERRUPT_GATE, isr38);
// idt.setGate(39, idt.INTERRUPT_GATE, isr39); idt.setGate(39, idt.INTERRUPT_GATE, isr39);
// idt.setGate(40, idt.INTERRUPT_GATE, isr40); idt.setGate(40, idt.INTERRUPT_GATE, isr40);
// idt.setGate(41, idt.INTERRUPT_GATE, isr41); idt.setGate(41, idt.INTERRUPT_GATE, isr41);
// idt.setGate(42, idt.INTERRUPT_GATE, isr42); idt.setGate(42, idt.INTERRUPT_GATE, isr42);
// idt.setGate(43, idt.INTERRUPT_GATE, isr43); idt.setGate(43, idt.INTERRUPT_GATE, isr43);
// idt.setGate(44, idt.INTERRUPT_GATE, isr44); idt.setGate(44, idt.INTERRUPT_GATE, isr44);
// idt.setGate(45, idt.INTERRUPT_GATE, isr45); idt.setGate(45, idt.INTERRUPT_GATE, isr45);
// idt.setGate(46, idt.INTERRUPT_GATE, isr46); idt.setGate(46, idt.INTERRUPT_GATE, isr46);
// idt.setGate(47, idt.INTERRUPT_GATE, isr47); idt.setGate(47, idt.INTERRUPT_GATE, isr47);
// // Syscalls. // Syscalls.
// idt.setGate(128, idt.SYSCALL_GATE, isr128); idt.setGate(128, idt.SYSCALL_GATE, isr128);
} }

View file

@ -24,6 +24,9 @@ pub inline fn hang() noreturn {
pub inline fn sti() void { pub inline fn sti() void {
asm volatile ("sti"); asm volatile ("sti");
} }
pub inline fn int3() void {
asm volatile ("int3");
}
//// ////
// Load a new Interrupt Descriptor Table. // Load a new Interrupt Descriptor Table.

View file

@ -8,7 +8,8 @@ SECTIONS {
. = 0xb8000; . = 0xb8000;
. += 80 * 25 * 2; . += 80 * 25 * 2;
. = 0x100000; /* lower half kernel */
. = 0x10000;
/* ensure that the multiboot header is at the beginning */ /* ensure that the multiboot header is at the beginning */
.multiboot : .multiboot :
@ -67,16 +68,4 @@ SECTIONS {
*(.bss .bss.*) *(.bss .bss.*)
. = ALIGN(4K); . = ALIGN(4K);
} }
/* .stab : */
/* { */
/* KEEP(*(.stab)) */
/* . = ALIGN(4K); */
/* } */
/* .stabstr : */
/* { */
/* KEEP(*(.stabstr)) */
/* . = ALIGN(4K); */
/* } */
} }

View file

@ -1,18 +1,37 @@
usingnamespace @import("kernel").main; usingnamespace @import("kernel").main;
usingnamespace @import("kernel").multiboot; usingnamespace @import("kernel").multiboot;
const console = @import("../console.zig");
const println = @import("../../vga.zig").println;
const idt = @import("idt.zig"); const idt = @import("idt.zig");
const mem = @import("mem.zig"); const memory = @import("memory.zig");
const paging = @import("paging.zig");
const gdt = @import("gdt.zig"); const gdt = @import("gdt.zig");
const x86 = @import("lib/index.zig"); const x86 = @import("lib/index.zig");
const console = @import("../console.zig");
const printf = @import("../../vga.zig").printf;
/// x86 specific intialization /// x86 specific intialization
/// first entry point (see linker.ld) /// first entry point (see linker.ld)
pub fn x86_main(info: *const MultibootInfo) void { pub fn x86_main(info: *const MultibootInfo) void {
var allocator = mem.initialize(info); // set up the physical frame allocator
memory.initialize(info);
// gdt.initialize(); println("{}", memory.allocator.allocate(1));
// println("{}", memory.allocator.allocate(1));
// println("{}", memory.allocator.allocate(1));
// println("{}", memory.allocator.allocate(1));
// setup memory segmentation
gdt.initialize();
// setup interrupts
idt.initialize(); idt.initialize();
// enable interrupts
x86.sti(); x86.sti();
// set up the virtual page mapper
paging.initialize();
// test breakpoint
// x86.int3();
} }

View file

@ -1,41 +1,43 @@
usingnamespace @import("kernel").multiboot; usingnamespace @import("kernel").multiboot;
usingnamespace @import("../../vga.zig");
const assert = @import("std").debug.assert; const assert = @import("std").debug.assert;
const vga = @import("../../vga.zig");
const std = @import("std"); const std = @import("std");
const printf = @import("../../vga.zig").printf;
pub fn initialize(info: *const MultibootInfo) bumpAllocator { pub var allocator: bumpAllocator = undefined;
pub fn initialize(info: *const MultibootInfo) void {
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0); assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0); assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
format_multibootinfo(info); format_multibootinfo(info);
return bumpAllocator.new(info); allocator = bumpAllocator.new(info);
} }
pub fn format_multibootentry(entry: *MultibootMMapEntry) void { fn format_multibootentry(entry: *MultibootMMapEntry) void {
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) { if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
vga.printf("AVAILABLE: "); print(" AVAILABLE: ");
} else { } else {
vga.printf("NOT AVAILABLE: "); print("NOT AVAILABLE: ");
} }
vga.printf("{x} ", entry.addr); print("{x} ", entry.addr);
if (entry.len / (1024 * 1024) > 0) { if (entry.len / (1024 * 1024) > 0) {
vga.printf("({} MB)\n", entry.len / (1024 * 1024)); println("({} MB)", entry.len / (1024 * 1024));
} else { } else {
vga.printf("({} kB)\n", entry.len / (1024)); println("({} kB)", entry.len / (1024));
} }
} }
pub fn format_multibootinfo(info: *const MultibootInfo) void { fn format_multibootinfo(info: *const MultibootInfo) void {
var cmdline_ptr = @intToPtr([*c]const u8, info.cmdline); var cmdline_ptr = @intToPtr([*c]const u8, info.cmdline);
var cmdline = @ptrCast([*c]const u8, cmdline_ptr); var cmdline = @ptrCast([*c]const u8, cmdline_ptr);
// var cmdline = std.cstr.toSliceConst(info.cmdline); // var cmdline = std.cstr.toSliceConst(info.cmdline);
vga.printf("lower: {x}\n", info.mem_lower); println("flags: {b}", info.flags);
vga.printf("upper: {x}\n", info.mem_upper); println("lower: {x}", info.mem_lower);
vga.printf("mmap_l: {}\n", info.mmap_length); println("upper: {x}", info.mem_upper);
vga.printf("mmap_a: {x}\n", info.mmap_addr); println("mmap_l: {}", info.mmap_length);
vga.printf("cmdline: {x}\n", cmdline_ptr); println("mmap_a: {x}", info.mmap_addr);
vga.printf("cmdline: {}\n", cmdline); println("cmdline: {x}", cmdline_ptr);
println("cmdline: {}", cmdline);
var map: usize = info.mmap_addr; var map: usize = info.mmap_addr;
while (map < info.mmap_addr + info.mmap_length) { while (map < info.mmap_addr + info.mmap_length) {
@ -47,22 +49,21 @@ pub fn format_multibootinfo(info: *const MultibootInfo) void {
// returns each available physical frame one by one in order // returns each available physical frame one by one in order
pub const bumpAllocator = struct { pub const bumpAllocator = struct {
next_free_frame: physFrame, next_free_frame: PhysFrame,
current_area: ?*MultibootMMapEntry, current_area: ?*MultibootMMapEntry,
info: *const MultibootInfo, info: *const MultibootInfo,
pub fn new(info: *const MultibootInfo) bumpAllocator { pub fn new(info: *const MultibootInfo) bumpAllocator {
const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr); const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr);
var allocator = bumpAllocator{ var allocato = bumpAllocator{
.current_area = first_area, .current_area = first_area,
.next_free_frame = physFrame.from_addr(first_area.addr), .next_free_frame = PhysFrame.from_addr(@intCast(u32, first_area.addr)),
.info = info, .info = info,
}; };
// allocator.choose_next_area(); return allocato;
return allocator;
} }
pub fn allocate(self: var, count: u64) ?physFrame { pub fn allocate(self: var, count: u32) ?PhysFrame {
if (count == 0) { if (count == 0) {
return null; return null;
} }
@ -73,10 +74,15 @@ pub const bumpAllocator = struct {
self.choose_next_area(); self.choose_next_area();
return self.allocate(count); return self.allocate(count);
} }
// <4MB identity mapped kernel, lazy trick
if (PhysFrame.start_addr(self.next_free_frame) < 0x400000) {
self.next_free_frame.number += 1;
return self.allocate(count);
}
const start_frame = self.next_free_frame; const start_frame = self.next_free_frame;
const end_frame = self.next_free_frame.add(count - 1); const end_frame = self.next_free_frame.add(count - 1);
const current_area_last_frame = physFrame.from_addr(self.current_area.?.addr + self.current_area.?.len); const current_area_last_frame = PhysFrame.from_addr(@intCast(u32, self.current_area.?.addr + self.current_area.?.len));
if (end_frame.number > current_area_last_frame.number) { if (end_frame.number > current_area_last_frame.number) {
self.choose_next_area(); self.choose_next_area();
return self.allocate(count); return self.allocate(count);
@ -86,72 +92,33 @@ pub const bumpAllocator = struct {
} }
pub fn choose_next_area(self: var) void { pub fn choose_next_area(self: var) void {
printf("choosing next area\n"); println("choosing next area");
const current = self.current_area.?; const current = self.current_area.?;
var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current)); var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current));
if (next_area >= self.info.mmap_addr + self.info.mmap_length) { if (next_area >= self.info.mmap_addr + self.info.mmap_length) {
self.current_area = null; self.current_area = null;
} else { } else {
format_multibootentry(self.current_area.?);
self.current_area = @intToPtr(*MultibootMMapEntry, next_area); self.current_area = @intToPtr(*MultibootMMapEntry, next_area);
format_multibootentry(self.current_area.?); format_multibootentry(self.current_area.?);
self.next_free_frame = physFrame.from_addr(self.current_area.?.addr); self.next_free_frame = PhysFrame.from_addr(@intCast(u32, self.current_area.?.addr));
} }
} }
}; };
pub const PAGE_SIZE = 4096; pub const PAGE_SIZE = 4096;
pub const physFrame = struct { pub const PhysFrame = struct {
number: u64, number: u32,
pub fn from_addr(addr: u64) physFrame { pub fn from_addr(addr: u32) PhysFrame {
return physFrame{ .number = @divTrunc(addr, PAGE_SIZE) }; return PhysFrame{ .number = @divTrunc(addr, PAGE_SIZE) };
} }
pub fn add(self: physFrame, count: u64) physFrame { pub fn add(self: PhysFrame, count: u32) PhysFrame {
return physFrame{ .number = self.number + count }; return PhysFrame{ .number = self.number + count };
} }
pub fn start_addr(self: physFrame) u64 { pub fn start_addr(self: PhysFrame) u32 {
return (self.number * PAGE_SIZE); return (self.number * PAGE_SIZE);
} }
}; };
const PageDirectory = packed struct {
entries: [1024]PageDirectoryEntry,
};
const PageDirectoryEntry = packed struct {
address: u21,
available: u2,
ignored: u1,
size: u1,
zero: u1,
accessed: u1,
cache_disabled: u1,
write_through: u1,
user: u1,
writeable: u1,
present: u1,
};
const PageTable = packed struct {
entries: [1024]PageTableEntry,
};
const PageTableEntry = packed struct {
address: u21,
available: u2,
global: u1,
zero: u1,
dirty: u1,
accessed: u1,
cache_disabled: u1,
write_through: u1,
user: u1,
writeable: u1,
present: u1,
};
// assert(@sizeOf(PageTableEntry) == 32);

24
src/arch/x86/paging.s Normal file
View file

@ -0,0 +1,24 @@
.type setupPaging, @function
.global setupPaging
////
// Enable the paging system.
//
// Arguments:
// phys_pd: Physical pointer to the page directory.
//
setupPaging:
mov +4(%esp), %eax // Fetch the phys_pd parameter.
mov %eax, %cr3 // Point CR3 to the page directory.
// Enable Page Size Extension and Page Global.
mov %cr4, %eax
or $0b00010000, %eax
mov %eax, %cr4
// Enable Paging.
mov %cr0, %eax
or $(1 << 31), %eax
mov %eax, %cr0
ret

89
src/arch/x86/paging.zig Normal file
View file

@ -0,0 +1,89 @@
const x86 = @import("lib/index.zig");
const allocator = @import("memory.zig").allocator;
const assert = @import("std").debug.assert;
const println = @import("../../vga.zig").println;
extern fn setupPaging(phys_pd: usize) void;
pub var mapper: Mapper = undefined;
pub const PAGE_SIZE = 4096;
pub fn initialize() void {
const empty_page = PageDirectoryEntry{};
// var p2 = allocator.allocate(1);
var p2 = [_]PageDirectoryEntry{empty_page} ** 1024;
// var p2 = [_]u32{0} ** 1024;
// identity map 0 -> 4MB
p2[0].pageTable = 0x0;
p2[0].present = true;
p2[0].read_write = true;
p2[0].huge = true;
// p2[0] = @bitReverse(u32, 0b10000011);
println("p2[0] {b}", p2[0]);
println("p2[0] {b}", @bitCast(u32, p2[0]));
// x86.hang();
// paging.s
// setupPaging(@ptrToInt(&p2));
// mapper = Mapper{
// .p2 = p2,
// };
const addr = mapper.translate(0xfffff000);
}
const builtin = @import("builtin");
const Mapper = struct {
p2: PageDirectory,
// virt to phys
pub fn translate(self: Mapper, virt: u32) ?u32 {
const map = @bitCast(VirtAddr, virt);
println("{}", builtin.endian);
println("virt {x} -> {}-{}-{x}", virt, map.page_directory, map.page_table, map.offset);
return null;
}
};
pub const VirtAddr = packed struct {
page_directory: u10,
page_table: u10,
offset: u12,
};
pub const PageDirectoryEntry = packed struct {
pageTable: u20 = 0,
available: u3 = 0,
ignored: bool = false,
huge: bool = false,
zero: bool = false,
accessed: bool = false,
cache_disabled: bool = false,
write_thru: bool = false,
supervisor: bool = false,
read_write: bool = false,
present: bool = false,
};
pub const PageTableEntry = packed struct {
addr: u20 = 0,
available: u3 = 0,
global: bool = false,
zero: bool = false,
dirty: bool = false,
accessed: bool = false,
cache_disabled: bool = false,
write_thru: bool = false,
supervisor: bool = false,
read_write: bool = false,
present: bool = false,
};
pub const PageTable = [1024]PageTableEntry;
pub const PageDirectory = [1024]PageDirectoryEntry;
comptime {
assert(@sizeOf(PageDirectoryEntry) == 4); //32 bits
assert(@sizeOf(PageTableEntry) == 4); //32 bits
}

View file

@ -33,7 +33,7 @@ pub fn keypress(char: u8) void {
} }
pub fn initialize() void { pub fn initialize() void {
vga.clear(); // vga.clear();
// vga.writeString("> ");
interrupt.registerIRQ(1, ps2.keyboard_handler); interrupt.registerIRQ(1, ps2.keyboard_handler);
vga.writeString("> ");
} }

View file

@ -9,17 +9,18 @@ const assert = @import("std").debug.assert;
// arch independant initialization // arch independant initialization
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn { export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC); assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
console.initialize();
printf("--- hello x86_main ---\n");
println("--- x86 initialization ---");
x86.x86_main(info); x86.x86_main(info);
// pagefault_test(0xfeffc000); // pagefault_test(0xfeffc000);
printf("\n--- arch indepent boot ---\n"); println("--- core initialization ---");
console.initialize();
while (true) {} while (true) {
asm volatile ("hlt");
}
} }
fn pagefault_test(addr: u32) void { fn pagefault_test(addr: u32) void {

View file

@ -13,29 +13,46 @@ pub const MULTIBOOT_BOOTLOADER_MAGIC = 0x2BADB002;
pub const MULTIBOOT_INFO_MEMORY = 0x00000001; pub const MULTIBOOT_INFO_MEMORY = 0x00000001;
// Is there a full memory map? // Is there a full memory map?
pub const MULTIBOOT_INFO_MEM_MAP = 0x00000040; pub const MULTIBOOT_INFO_MEM_MAP = 0x00000040;
// System information structure passed by the bootloader. // System information structure passed by the bootloader.
pub const MultibootInfo = packed struct { pub const MultibootInfo = packed struct {
// Multiboot info version number. // Multiboot info version number.
flags: u32, flags: u32,
// Available memory from BIOS. // Available memory from BIOS.
// present if flags[0]
mem_lower: u32, mem_lower: u32,
mem_upper: u32, mem_upper: u32,
// "root" partition. // present if flags[1]
boot_device: u32, boot_device: u32,
// Kernel command line. // present if flags[2]
cmdline: u32, cmdline: u32,
// Boot-Module list. // Boot-Module list.
mods_count: u32, mods_count: u32,
mods_addr: u32, mods_addr: u32,
// TODO: use the real types here. syms: extern union {
u: u128, // present if flags[4]
nlist: extern struct {
tabsize: u32,
strsize: u32,
addr: u32,
_reserved: u32,
},
// present if flags[5]
shdr: extern struct {
num: u32,
size: u32,
addr: u32,
shndx: u32,
},
},
// Memory Mapping buffer. // Memory Mapping buffer.
// present if flags[6]
mmap_length: u32, mmap_length: u32,
mmap_addr: u32, mmap_addr: u32,
@ -112,16 +129,22 @@ const MultibootHeader = packed struct {
magic: u32, // Must be equal to header magic number. magic: u32, // Must be equal to header magic number.
flags: u32, // Feature flags. flags: u32, // Feature flags.
checksum: u32, // Above fields plus this one must equal 0 mod 2^32. checksum: u32, // Above fields plus this one must equal 0 mod 2^32.
// following fields are used if flag bit 16 is specified
header_addr: u32 = 0,
load_addr: u32 = 0,
load_end_addr: u32 = 0,
bss_end_addr: u32 = 0,
entry_addr: u32 = 0,
}; };
// NOTE: this structure is incomplete. // NOTE: this structure is incomplete.
// Place the header at the very beginning of the binary. // Place the header at the very beginning of the binary.
export const multiboot_header align(4) linksection(".multiboot") = multiboot: { export const multiboot_header align(4) linksection(".multiboot") = multiboot: {
const MAGIC = u32(0x1BADB002); // multiboot magic const MAGIC = u32(0x1BADB002); // multiboot magic
const ALIGN = u32(1 << 0); // Align loaded modules. const ALIGN = u32(1 << 0); // Align loaded modules at 4k
const MEMINFO = u32(1 << 1); // Receive a memory map from the bootloader. const MEMINFO = u32(1 << 1); // Receive a memory map from the bootloader.
const CMDLINE = u32(1 << 2); // Receive a cmdline from the bootloader const ADDR = u32(1 << 16); // Load specific addr
const FLAGS = ALIGN | MEMINFO | CMDLINE; // Combine the flags. const FLAGS = ALIGN | MEMINFO; // Combine the flags.
break :multiboot MultibootHeader { break :multiboot MultibootHeader {
.magic = MAGIC, .magic = MAGIC,

View file

@ -2,7 +2,7 @@ const arch = @import("arch/x86/lib/index.zig");
const PCI_CONFIG_ADDRESS = 0xCF8; const PCI_CONFIG_ADDRESS = 0xCF8;
const PCI_CONFIG_DATA = 0xCFC; const PCI_CONFIG_DATA = 0xCFC;
const vga = @import("vga.zig"); usingnamespace @import("vga.zig");
pub const PciAddress = packed struct { pub const PciAddress = packed struct {
offset: u8, offset: u8,
@ -57,7 +57,7 @@ pub const PciDevice = struct {
} }
pub fn format(self: PciDevice) void { pub fn format(self: PciDevice) void {
vga.printf("{}:{}.{} {x},{x}: {x} {x}\n", self.bus, self.slot, self.function, self.class, self.subclass, self.vendor, self.device); println("{}:{}.{} {x},{x}: {x} {x}", self.bus, self.slot, self.function, self.class, self.subclass, self.vendor, self.device);
} }
pub fn access(self: PciDevice, offset: u8) void { pub fn access(self: PciDevice, offset: u8) void {

View file

@ -1,3 +1,4 @@
usingnamespace @import("vga.zig");
const x86 = @import("arch/x86/lib/index.zig"); const x86 = @import("arch/x86/lib/index.zig");
const console = @import("console.zig"); const console = @import("console.zig");
@ -84,6 +85,7 @@ fn key_isrelease(scancode: u8) bool {
pub fn keyboard_handler() void { pub fn keyboard_handler() void {
const scancode = ps2_scancode(); const scancode = ps2_scancode();
const isrelease = key_isrelease(scancode); const isrelease = key_isrelease(scancode);
println("keyboard scancode 0b{b}", scancode);
if (isrelease) { if (isrelease) {
return; return;
} }

View file

@ -56,10 +56,14 @@ pub fn disableCursor() void {
} }
const Errors = error{}; const Errors = error{};
pub fn printf(comptime format: []const u8, args: ...) void { pub fn print(comptime format: []const u8, args: ...) void {
var a = std.fmt.format({}, Errors, printCallback, format, args); var a = std.fmt.format({}, Errors, printCallback, format, args);
} }
pub fn println(comptime format: []const u8, args: ...) void {
var a = std.fmt.format({}, Errors, printCallback, format ++ "\n", args);
}
fn printCallback(context: void, string: []const u8) Errors!void { fn printCallback(context: void, string: []const u8) Errors!void {
vga.writeString(string); vga.writeString(string);
} }