Compare commits
1 commit
master
...
feat/multi
| Author | SHA1 | Date | |
|---|---|---|---|
| e0eda2690c |
9 changed files with 145 additions and 276 deletions
|
|
@ -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");
|
||||||
|
|
|
||||||
14
grub.sh
14
grub.sh
|
|
@ -5,6 +5,16 @@ exit_missing() {
|
||||||
|
|
||||||
which xorriso || exit_missing
|
which xorriso || exit_missing
|
||||||
which grub-mkrescue || exit_missing
|
which grub-mkrescue || exit_missing
|
||||||
mkdir -p build/iso/boot
|
mkdir -p build/iso/boot/grub
|
||||||
cp build/bzImage build/iso/boot
|
cp build/kernel build/iso/boot
|
||||||
|
>build/iso/boot/grub/grub.cfg <<EOF
|
||||||
|
set timeout=0
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "OS" {
|
||||||
|
multiboot2 /boot/kernel
|
||||||
|
boot
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
grub-mkrescue -o build/kernel.iso build/iso
|
grub-mkrescue -o build/kernel.iso build/iso
|
||||||
|
|
|
||||||
19
qemu.sh
19
qemu.sh
|
|
@ -1,30 +1,27 @@
|
||||||
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 qemu-system-i386 \
|
sudo qemu-system-i386 \
|
||||||
-gdb tcp::${QEMU_GDB_PORT} \
|
-gdb tcp::${QEMU_GDB_PORT} \
|
||||||
-monitor unix:${QEMU_SOCKET},server,nowait \
|
-monitor unix:${QEMU_SOCKET},server,nowait \
|
||||||
-enable-kvm \
|
-enable-kvm \
|
||||||
-m 1337M \
|
-m 50M \
|
||||||
-display curses \
|
|
||||||
-serial mon:stdio \
|
-serial mon:stdio \
|
||||||
-append "Hello" \
|
-curses \
|
||||||
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
|
||||||
-kernel ${KERNEL}
|
-kernel ${KERNEL}
|
||||||
|
# -cdrom ${KERNEL}.iso
|
||||||
|
# -append "Hello" \
|
||||||
|
# -S
|
||||||
|
# -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \
|
||||||
# build/kernel.iso
|
# build/kernel.iso
|
||||||
"$@"
|
"$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor() {
|
monitor() {
|
||||||
if [ "$1" == "" ]; then
|
[ "$1" == "" ] && sudo ${QEMU_MONITOR} || echo "$1" | sudo ${QEMU_MONITOR} >/dev/null
|
||||||
sudo ${QEMU_MONITOR}
|
|
||||||
else
|
|
||||||
echo "$1" | sudo ${QEMU_MONITOR} >/dev/null
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ 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);
|
var allocator = mem.initialize(info);
|
||||||
|
|
||||||
// gdt.initialize();
|
// gdt.initialize();
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,16 @@ usingnamespace @import("kernel").multiboot;
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
const vga = @import("../../vga.zig");
|
const vga = @import("../../vga.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const printf = @import("../../vga.zig").printf;
|
const println = @import("../../vga.zig").println;
|
||||||
|
|
||||||
pub fn initialize(info: *const MultibootInfo) bumpAllocator {
|
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEMORY) != 0);
|
|
||||||
assert((info.flags & MULTIBOOT_INFO_MEM_MAP) != 0);
|
|
||||||
|
|
||||||
|
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);
|
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) {
|
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
vga.printf("AVAILABLE: ");
|
vga.printf("AVAILABLE: ");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -26,132 +25,118 @@ pub fn format_multibootentry(entry: *MultibootMMapEntry) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_multibootinfo(info: *const MultibootInfo) void {
|
pub fn format_multibootinfo(info: *const multibootInfo) void {
|
||||||
var cmdline_ptr = @intToPtr([*c]const u8, info.cmdline);
|
println("-- multiboot2 info --");
|
||||||
var cmdline = @ptrCast([*c]const u8, cmdline_ptr);
|
// println("start: {}, end {}, size {}", info.start_address(), info.end_address(), info.total_size());
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 allocator = bumpAllocator{
|
||||||
.current_area = first_area,
|
// .current_area = first_area,
|
||||||
.next_free_frame = physFrame.from_addr(first_area.addr),
|
// .next_free_frame = physFrame.from_addr(first_area.addr),
|
||||||
.info = info,
|
// .info = info,
|
||||||
};
|
// };
|
||||||
// allocator.choose_next_area();
|
// // allocator.choose_next_area();
|
||||||
return allocator;
|
// return allocator;
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn allocate(self: var, count: u64) ?physFrame {
|
// pub fn allocate(self: var, count: u64) ?physFrame {
|
||||||
if (count == 0) {
|
// if (count == 0) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
if (self.current_area == null) {
|
// if (self.current_area == null) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
if (self.current_area.?.type != MULTIBOOT_MEMORY_AVAILABLE) {
|
// if (self.current_area.?.type != MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
self.choose_next_area();
|
// self.choose_next_area();
|
||||||
return self.allocate(count);
|
// 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(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);
|
||||||
}
|
// }
|
||||||
self.next_free_frame.number += count;
|
// self.next_free_frame.number += count;
|
||||||
return start_frame;
|
// return start_frame;
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn choose_next_area(self: var) void {
|
// pub fn choose_next_area(self: var) void {
|
||||||
printf("choosing next area\n");
|
// printf("choosing next area\n");
|
||||||
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.?);
|
// 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(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: u64,
|
||||||
|
|
||||||
pub fn from_addr(addr: u64) physFrame {
|
// pub fn from_addr(addr: u64) 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: u64) 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) u64 {
|
||||||
return (self.number * PAGE_SIZE);
|
// return (self.number * PAGE_SIZE);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
const PageDirectory = packed struct {
|
// const PageDirectory = packed struct {
|
||||||
entries: [1024]PageDirectoryEntry,
|
// entries: [1024]PageDirectoryEntry,
|
||||||
};
|
// };
|
||||||
|
|
||||||
const PageDirectoryEntry = packed struct {
|
// const PageDirectoryEntry = packed struct {
|
||||||
address: u21,
|
// address: u21,
|
||||||
available: u2,
|
// available: u2,
|
||||||
ignored: u1,
|
// ignored: u1,
|
||||||
size: u1,
|
// size: u1,
|
||||||
zero: u1,
|
// zero: u1,
|
||||||
accessed: u1,
|
// accessed: u1,
|
||||||
cache_disabled: u1,
|
// cache_disabled: u1,
|
||||||
write_through: u1,
|
// write_through: u1,
|
||||||
user: u1,
|
// user: u1,
|
||||||
writeable: u1,
|
// writeable: u1,
|
||||||
present: u1,
|
// present: u1,
|
||||||
};
|
// };
|
||||||
|
|
||||||
const PageTable = packed struct {
|
// const PageTable = packed struct {
|
||||||
entries: [1024]PageTableEntry,
|
// entries: [1024]PageTableEntry,
|
||||||
};
|
// };
|
||||||
|
|
||||||
const PageTableEntry = packed struct {
|
// const PageTableEntry = packed struct {
|
||||||
address: u21,
|
// address: u21,
|
||||||
available: u2,
|
// available: u2,
|
||||||
global: u1,
|
// global: u1,
|
||||||
zero: u1,
|
// zero: u1,
|
||||||
dirty: u1,
|
// dirty: u1,
|
||||||
accessed: u1,
|
// accessed: u1,
|
||||||
cache_disabled: u1,
|
// cache_disabled: u1,
|
||||||
write_through: u1,
|
// write_through: u1,
|
||||||
user: u1,
|
// user: u1,
|
||||||
writeable: u1,
|
// writeable: u1,
|
||||||
present: u1,
|
// present: u1,
|
||||||
};
|
// };
|
||||||
|
|
||||||
// assert(@sizeOf(PageTableEntry) == 32);
|
// // assert(@sizeOf(PageTableEntry) == 32);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
pub const vga = @import("vga.zig");
|
pub const vga = @import("vga.zig");
|
||||||
pub const main = @import("main.zig");
|
pub const main = @import("main.zig");
|
||||||
pub const multiboot = @import("multiboot.zig");
|
pub const multiboot = @import("multiboot2.zig");
|
||||||
|
|
|
||||||
23
src/main.zig
23
src/main.zig
|
|
@ -1,24 +1,29 @@
|
||||||
usingnamespace @import("multiboot.zig");
|
usingnamespace @import("multiboot2.zig");
|
||||||
usingnamespace @import("vga.zig");
|
usingnamespace @import("vga.zig");
|
||||||
const pci = @import("pci.zig");
|
|
||||||
const arch = @import("arch/x86/lib/index.zig");
|
const arch = @import("arch/x86/lib/index.zig");
|
||||||
const console = @import("console.zig");
|
|
||||||
const x86 = @import("arch/x86/main.zig");
|
const x86 = @import("arch/x86/main.zig");
|
||||||
|
const multiboot = @import("multiboot2.zig");
|
||||||
|
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
|
const pci = @import("pci.zig");
|
||||||
|
const console = @import("console.zig");
|
||||||
|
|
||||||
// arch independant initialization
|
// arch independant initialization
|
||||||
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
export fn kmain(magic: u32, info_addr: u32) noreturn {
|
||||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
println("--- hello x86_main ---");
|
||||||
|
assert(magic == MULTIBOOT2_BOOTLOADER_MAGIC);
|
||||||
|
|
||||||
|
const info = multiboot.load(info_addr);
|
||||||
console.initialize();
|
console.initialize();
|
||||||
|
|
||||||
printf("--- hello x86_main ---\n");
|
println("--- hello x86_main ---");
|
||||||
|
|
||||||
x86.x86_main(info);
|
x86.x86_main(&info);
|
||||||
|
|
||||||
// pagefault_test(0xfeffc000);
|
// pagefault_test(0xfeffc000);
|
||||||
|
|
||||||
printf("\n--- arch indepent boot ---\n");
|
println("--- end ---");
|
||||||
|
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -59,6 +59,9 @@ const Errors = error{};
|
||||||
pub fn printf(comptime format: []const u8, args: ...) void {
|
pub fn printf(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);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue