From e0eda2690c1ee31a830a3d96216c5aafbd66f1f3 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Aug 2019 17:22:15 +0200 Subject: [PATCH] add support for multiboot2 the bump allocator isn't ported qemu -kernel doesn't support this --- build.zig | 2 +- grub.sh | 14 ++- qemu.sh | 21 ++-- src/arch/x86/main.zig | 2 +- src/arch/x86/mem.zig | 223 ++++++++++++++++++++---------------------- src/index.zig | 2 +- src/main.zig | 23 +++-- src/multiboot.zig | 131 ------------------------- src/vga.zig | 3 + 9 files changed, 145 insertions(+), 276 deletions(-) delete mode 100644 src/multiboot.zig diff --git a/build.zig b/build.zig index b37b877..6e2bfdd 100644 --- a/build.zig +++ b/build.zig @@ -2,7 +2,7 @@ const Builder = @import("std").build.Builder; const builtin = @import("builtin"); 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("arch", "src/arch/x86/lib/index.zig"); kernel.setOutputDir("build"); diff --git a/grub.sh b/grub.sh index 2bdd1a5..70888e9 100755 --- a/grub.sh +++ b/grub.sh @@ -5,6 +5,16 @@ exit_missing() { which xorriso || exit_missing which grub-mkrescue || exit_missing -mkdir -p build/iso/boot -cp build/bzImage build/iso/boot +mkdir -p build/iso/boot/grub +cp build/kernel build/iso/boot +>build/iso/boot/grub/grub.cfg </dev/null - fi + [ "$1" == "" ] && sudo ${QEMU_MONITOR} || echo "$1" | sudo ${QEMU_MONITOR} >/dev/null } reload() { diff --git a/src/arch/x86/main.zig b/src/arch/x86/main.zig index 5adcdf4..41863b0 100644 --- a/src/arch/x86/main.zig +++ b/src/arch/x86/main.zig @@ -9,7 +9,7 @@ const printf = @import("../../vga.zig").printf; /// x86 specific intialization /// 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); // gdt.initialize(); diff --git a/src/arch/x86/mem.zig b/src/arch/x86/mem.zig index 4c4cd9a..ab44354 100644 --- a/src/arch/x86/mem.zig +++ b/src/arch/x86/mem.zig @@ -2,17 +2,16 @@ usingnamespace @import("kernel").multiboot; const assert = @import("std").debug.assert; const vga = @import("../../vga.zig"); const std = @import("std"); -const printf = @import("../../vga.zig").printf; - -pub fn initialize(info: *const MultibootInfo) bumpAllocator { - assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0); - assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0); +const println = @import("../../vga.zig").println; +pub fn initialize(info: *const multibootInfo) void { + // assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0); + // assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0); format_multibootinfo(info); - return bumpAllocator.new(info); + // return bumpAllocator.new(info); } -pub fn format_multibootentry(entry: *MultibootMMapEntry) void { +pub fn format_multibootentry(entry: *multibootMMapEntry) void { if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) { vga.printf("AVAILABLE: "); } else { @@ -26,132 +25,118 @@ pub fn format_multibootentry(entry: *MultibootMMapEntry) void { } } -pub fn format_multibootinfo(info: *const MultibootInfo) void { - var cmdline_ptr = @intToPtr([*c]const u8, info.cmdline); - var cmdline = @ptrCast([*c]const u8, cmdline_ptr); - // var cmdline = std.cstr.toSliceConst(info.cmdline); - vga.printf("lower: {x}\n", info.mem_lower); - vga.printf("upper: {x}\n", info.mem_upper); - vga.printf("mmap_l: {}\n", info.mmap_length); - vga.printf("mmap_a: {x}\n", info.mmap_addr); - vga.printf("cmdline: {x}\n", cmdline_ptr); - vga.printf("cmdline: {}\n", cmdline); - - var map: usize = info.mmap_addr; - while (map < info.mmap_addr + info.mmap_length) { - var entry = @intToPtr(*MultibootMMapEntry, map); - format_multibootentry(entry); - map += entry.size + @sizeOf(@typeOf(entry.size)); - } +pub fn format_multibootinfo(info: *const multibootInfo) void { + println("-- multiboot2 info --"); + // println("start: {}, end {}, size {}", info.start_address(), info.end_address(), info.total_size()); } // returns each available physical frame one by one in order -pub const bumpAllocator = struct { - next_free_frame: physFrame, - current_area: ?*MultibootMMapEntry, - info: *const MultibootInfo, +// pub const bumpAllocator = struct { +// next_free_frame: physFrame, +// current_area: ?*multibootMMapEntry, +// info: *const multibootInfo, - pub fn new(info: *const MultibootInfo) bumpAllocator { - const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr); - var allocator = bumpAllocator{ - .current_area = first_area, - .next_free_frame = physFrame.from_addr(first_area.addr), - .info = info, - }; - // allocator.choose_next_area(); - return allocator; - } +// pub fn new(info: *const multibootInfo) bumpAllocator { +// const first_area = @intToPtr(*MultibootMMapEntry, info.mmap_addr); +// var allocator = bumpAllocator{ +// .current_area = first_area, +// .next_free_frame = physFrame.from_addr(first_area.addr), +// .info = info, +// }; +// // allocator.choose_next_area(); +// return allocator; +// } - pub fn allocate(self: var, count: u64) ?physFrame { - if (count == 0) { - return null; - } - if (self.current_area == null) { - return null; - } - if (self.current_area.?.type != MULTIBOOT_MEMORY_AVAILABLE) { - self.choose_next_area(); - return self.allocate(count); - } +// pub fn allocate(self: var, count: u64) ?physFrame { +// if (count == 0) { +// return null; +// } +// if (self.current_area == null) { +// return null; +// } +// if (self.current_area.?.type != MULTIBOOT_MEMORY_AVAILABLE) { +// self.choose_next_area(); +// return self.allocate(count); +// } - const start_frame = self.next_free_frame; - 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); - if (end_frame.number > current_area_last_frame.number) { - self.choose_next_area(); - return self.allocate(count); - } - self.next_free_frame.number += count; - return start_frame; - } +// const start_frame = self.next_free_frame; +// 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); +// if (end_frame.number > current_area_last_frame.number) { +// self.choose_next_area(); +// return self.allocate(count); +// } +// self.next_free_frame.number += count; +// return start_frame; +// } - pub fn choose_next_area(self: var) void { - printf("choosing next area\n"); - const current = self.current_area.?; - var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current)); - if (next_area >= self.info.mmap_addr + self.info.mmap_length) { - self.current_area = null; - } else { - format_multibootentry(self.current_area.?); - self.current_area = @intToPtr(*MultibootMMapEntry, next_area); - format_multibootentry(self.current_area.?); - self.next_free_frame = physFrame.from_addr(self.current_area.?.addr); - } - } -}; +// pub fn choose_next_area(self: var) void { +// printf("choosing next area\n"); +// const current = self.current_area.?; +// var next_area = @ptrToInt(current) + current.size + @sizeOf(@typeOf(current)); +// if (next_area >= self.info.mmap_addr + self.info.mmap_length) { +// self.current_area = null; +// } else { +// format_multibootentry(self.current_area.?); +// self.current_area = @intToPtr(*MultibootMMapEntry, next_area); +// format_multibootentry(self.current_area.?); +// self.next_free_frame = physFrame.from_addr(self.current_area.?.addr); +// } +// } +// }; -pub const PAGE_SIZE = 4096; +// pub const PAGE_SIZE = 4096; -pub const physFrame = struct { - number: u64, +// pub const physFrame = struct { +// number: u64, - pub fn from_addr(addr: u64) physFrame { - return physFrame{ .number = @divTrunc(addr, PAGE_SIZE) }; - } +// pub fn from_addr(addr: u64) physFrame { +// return physFrame{ .number = @divTrunc(addr, PAGE_SIZE) }; +// } - pub fn add(self: physFrame, count: u64) physFrame { - return physFrame{ .number = self.number + count }; - } +// pub fn add(self: physFrame, count: u64) physFrame { +// return physFrame{ .number = self.number + count }; +// } - pub fn start_addr(self: physFrame) u64 { - return (self.number * PAGE_SIZE); - } -}; +// pub fn start_addr(self: physFrame) u64 { +// return (self.number * PAGE_SIZE); +// } +// }; -const PageDirectory = packed struct { - entries: [1024]PageDirectoryEntry, -}; +// 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 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 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, -}; +// 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); +// // assert(@sizeOf(PageTableEntry) == 32); diff --git a/src/index.zig b/src/index.zig index 90dc75f..f5dcdd6 100644 --- a/src/index.zig +++ b/src/index.zig @@ -1,3 +1,3 @@ pub const vga = @import("vga.zig"); pub const main = @import("main.zig"); -pub const multiboot = @import("multiboot.zig"); +pub const multiboot = @import("multiboot2.zig"); diff --git a/src/main.zig b/src/main.zig index fc192d0..f885cda 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,24 +1,29 @@ -usingnamespace @import("multiboot.zig"); +usingnamespace @import("multiboot2.zig"); usingnamespace @import("vga.zig"); -const pci = @import("pci.zig"); + const arch = @import("arch/x86/lib/index.zig"); -const console = @import("console.zig"); const x86 = @import("arch/x86/main.zig"); +const multiboot = @import("multiboot2.zig"); + const assert = @import("std").debug.assert; +const pci = @import("pci.zig"); +const console = @import("console.zig"); // arch independant initialization -export fn kmain(magic: u32, info: *const MultibootInfo) noreturn { - assert(magic == MULTIBOOT_BOOTLOADER_MAGIC); +export fn kmain(magic: u32, info_addr: u32) noreturn { + println("--- hello x86_main ---"); + assert(magic == MULTIBOOT2_BOOTLOADER_MAGIC); + + const info = multiboot.load(info_addr); console.initialize(); - printf("--- hello x86_main ---\n"); + println("--- hello x86_main ---"); - x86.x86_main(info); + x86.x86_main(&info); // pagefault_test(0xfeffc000); - printf("\n--- arch indepent boot ---\n"); - + println("--- end ---"); while (true) {} } diff --git a/src/multiboot.zig b/src/multiboot.zig deleted file mode 100644 index d2630d0..0000000 --- a/src/multiboot.zig +++ /dev/null @@ -1,131 +0,0 @@ -// MULTIBOOT1 -// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html - -// zig fmt: off -const tty = @import("tty.zig"); -const cstr = @import("std").cstr; -const Process = @import("process.zig").Process; - -// This should be in EAX. -pub const MULTIBOOT_BOOTLOADER_MAGIC = 0x2BADB002; - -// Is there basic lower/upper memory information? -pub const MULTIBOOT_INFO_MEMORY = 0x00000001; -// Is there a full memory map? -pub const MULTIBOOT_INFO_MEM_MAP = 0x00000040; -// System information structure passed by the bootloader. -pub const MultibootInfo = packed struct { - // Multiboot info version number. - flags: u32, - - // Available memory from BIOS. - mem_lower: u32, - mem_upper: u32, - - // "root" partition. - boot_device: u32, - - // Kernel command line. - cmdline: u32, - - // Boot-Module list. - mods_count: u32, - mods_addr: u32, - - // TODO: use the real types here. - u: u128, - - // Memory Mapping buffer. - mmap_length: u32, - mmap_addr: u32, - - // Drive Info buffer. - drives_length: u32, - drives_addr: u32, - - // ROM configuration table. - config_table: u32, - - // Boot Loader Name. - boot_loader_name: u32, - - // APM table. - apm_table: u32, - - // Video. - vbe_control_info: u32, - vbe_mode_info: u32, - vbe_mode: u16, - vbe_interface_seg: u16, - vbe_interface_off: u16, - vbe_interface_len: u16, - - //// - // Return the ending address of the last module. - // - pub fn lastModuleEnd(self: *const MultibootInfo) usize { - const mods = @intToPtr([*]MultibootModule, self.mods_addr); - return mods[self.mods_count - 1].mod_end; - } - - //// - // Load all the modules passed by the bootloader. - // - // pub fn loadModules(self: *const MultibootInfo) void { - // const mods = @intToPtr([*]MultibootModule, self.mods_addr)[0..self.mods_count]; - - // for (mods) |mod| { - // const cmdline = cstr.toSlice(@intToPtr([*]u8, mod.cmdline)); - // tty.step("Loading \"{}\"", cmdline); - - // _ = Process.create(mod.mod_start, null); - // // TODO: deallocate the original memory. - - // tty.stepOK(); - // } - // } -}; - -// Types of memory map entries. -pub const MULTIBOOT_MEMORY_AVAILABLE = 1; -pub const MULTIBOOT_MEMORY_RESERVED = 2; - -// Entries in the memory map. -pub const MultibootMMapEntry = packed struct { - size: u32, - addr: u64, - len: u64, - type: u32, -}; - -pub const MultibootModule = packed struct { - // The memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive. - mod_start: u32, - mod_end: u32, - - cmdline: u32, // Module command line. - pad: u32, // Padding to take it to 16 bytes (must be zero). -}; - -// Multiboot structure to be read by the bootloader. -const MultibootHeader = packed struct { - magic: u32, // Must be equal to header magic number. - flags: u32, // Feature flags. - checksum: u32, // Above fields plus this one must equal 0 mod 2^32. -}; -// NOTE: this structure is incomplete. - -// Place the header at the very beginning of the binary. -export const multiboot_header align(4) linksection(".multiboot") = multiboot: { - const MAGIC = u32(0x1BADB002); // multiboot magic - const ALIGN = u32(1 << 0); // Align loaded modules. - const MEMINFO = u32(1 << 1); // Receive a memory map from the bootloader. - const CMDLINE = u32(1 << 2); // Receive a cmdline from the bootloader - const FLAGS = ALIGN | MEMINFO | CMDLINE; // Combine the flags. - - break :multiboot MultibootHeader { - .magic = MAGIC, - .flags = FLAGS, - .checksum = ~(MAGIC +% FLAGS) +% 1, - }; -}; diff --git a/src/vga.zig b/src/vga.zig index 3a73c71..0a2455e 100644 --- a/src/vga.zig +++ b/src/vga.zig @@ -59,6 +59,9 @@ const Errors = error{}; pub fn printf(comptime format: []const u8, args: ...) void { 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 { vga.writeString(string);