diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index 4d6ad9cd..d66e8cb0 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit 4d6ad9cde926f2ad5d47041e3f3a2cda18f8e11e +Subproject commit d66e8cb0e5b10c2097a9aef985b4181694db9ce8 diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index bf201d5f..2b8b5995 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -86,3 +86,8 @@ GDTR: .ptr: DW .gdt_bottom - .gdt_top - 1 ; length of the structure minus 1 DD .gdt_top ; pointer to top of gdt + +section .bss +stack_bottom: + resb 4096 * 16 +stack_top: diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 91b1860b..c93a2140 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -15,7 +15,7 @@ SECTIONS { kernel_start = . ; /* ensure that the multiboot header is at the beginning */ - .multiboot_header : { KEEP(*(.multiboot_header)) } + .multiboot : { KEEP(*(.multiboot)) } .text : { *(.text .text.*) } .rodata : { *(.rodata .rodata.*) } .data : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) *(.data.*) } diff --git a/kernel-rs/src/arch/x86/multiboot_header.asm b/kernel-rs/src/arch/x86/multiboot_header.asm index 9f87d3bb..75fb5eb5 100644 --- a/kernel-rs/src/arch/x86/multiboot_header.asm +++ b/kernel-rs/src/arch/x86/multiboot_header.asm @@ -1,4 +1,4 @@ -section .multiboot_header +section .multiboot header_start: dd 0xe85250d6 ; magic number (multiboot 2) dd 0 ; architecture 0 (protected mode i386) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index cbe7800a..f32c67ad 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,14 +1,33 @@ extern crate core; +extern crate multiboot2; use cpuio; use core::char; +use context::CONTEXT; +use vga::*; + +pub fn dispatch(command: &str) { + match command { + "shutdown" | "halt" => self::shutdown(), + "reboot" => self::reboot(), + "stack" => self::print_stack(), + "multiboot" => self::mb2_info(), + "memory" => self::mb2_memory(), + "sections" => self::mb2_sections(), + _ => { + set_color!(Red); + println!("`{}': Command unknown ", command); + set_color!(); + } + } +} //TODO implement ACPI to have such functionality /// Reboot the kernel /// /// If reboot failed, will loop on a halt cmd /// -pub fn reboot() { +fn reboot() { //TODO disable interrupt here something like : asm volatile ("cli"); // I will now clear the keyboard buffer @@ -29,19 +48,21 @@ pub fn reboot() { /// /// If shutdown failed, will loop on a halt cmd /// -pub fn shutdown() -> ! { +fn shutdown() -> ! { cpuio::outb(0xf4, 0x00);//TODO doesn't work :( println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); cpuio::halt(); } -pub fn print_hexdump(data: &[u8], offset: usize) { +fn hexdump(start: usize, end: usize) { let mut address = 0; + let data = unsafe { core::slice::from_raw_parts_mut(start as *mut u8, end - start) }; while address <= data.len() { - let end = core::cmp::min(address + 16, data.len()); - print_line(&data[address..end], address + offset); + let next_end = core::cmp::min(address + 16, data.len()); + print_line(&data[address..next_end], address + start); address = address + 16; } + println!(""); } fn is_control(c: char) -> bool { @@ -63,13 +84,53 @@ fn print_line(line: &[u8], address: usize) { print!("|"); } -/// Print the kernel stack -pub fn print_kernel_stack() { +fn print_stack() { let esp: usize; let ebp: usize; unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; - println!("{:#x} -> {:#x} (size={} bytes)", ebp, esp, ebp - esp); - let slice = unsafe { core::slice::from_raw_parts_mut(ebp as *mut u8, ebp - esp) }; - print_hexdump(slice, ebp); - println!(""); + println!("esp = {:#x}", esp); + println!("ebp = {:#x}", ebp); + println!("size = {:#X} bytes", ebp - esp); + hexdump(esp, ebp); +} + +fn mb2_memory() { + let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + + let memory_map_tag = boot_info.memory_map_tag() + .expect("Memory map tag required"); + + println!("memory areas:"); + for area in memory_map_tag.memory_areas() { + println!(" start: 0x{:x}, length: 0x{:x}", + area.start_address(), area.size()); + } +} + +fn mb2_sections() { + let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("Elf-sections tag required"); + + println!("kernel sections:"); + for section in elf_sections_tag.sections() { + println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}", + section.name(), section.start_address(), section.size(), section.flags()); + } +} + +fn mb2_info() { + let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + + let command_line_tag = boot_info.command_line_tag() + .expect("Elf-sections tag required"); + + let bootloader_tag = boot_info.boot_loader_name_tag() + .expect("Elf-sections tag required"); + + println!("bootloader: {}", bootloader_tag.name()); + if command_line_tag.command_line().len() != 0 { + println!("command line: {}", command_line_tag.command_line()); + } } diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 06ca9bb4..2b6b3b93 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -4,12 +4,14 @@ use vga; pub static mut CONTEXT: Context = Context { current_term: 0, + boot_info_addr: 0, vga1: vga::Writer::new(), vga2: vga::Writer::new(), }; pub struct Context { pub current_term: u8, + pub boot_info_addr: usize, pub vga1: vga::Writer, pub vga2: vga::Writer, } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 3e7f8fcb..6aca6b97 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -24,25 +24,7 @@ use context::CONTEXT; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { - let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; - - let memory_map_tag = boot_info.memory_map_tag() - .expect("Memory map tag required"); - - println!("memory areas:"); - for area in memory_map_tag.memory_areas() { - println!(" start: 0x{:x}, length: 0x{:x}", - area.base_addr, area.length); - } - - let elf_sections_tag = boot_info.elf_sections_tag() - .expect("Elf-sections tag required"); - - println!("kernel sections:"); - for section in elf_sections_tag.sections() { - println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", - section.addr, section.size, section.flags); - } + unsafe { CONTEXT.boot_info_addr = multiboot_info_addr }; unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } unsafe { CONTEXT.vga2.prompt(); } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 4911dae7..1d8aec36 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -29,6 +29,15 @@ macro_rules! flush { () => (unsafe { CONTEXT.current_term().flush() }); } +macro_rules! set_color { + () => (unsafe { CONTEXT.current_term().color_code = + ColorCode::new(Color::White, Color::Black) }); + ($fg:ident) => (unsafe { CONTEXT.current_term().color_code = + ColorCode::new(Color::$fg, Color::Black) }); + ($fg:ident, $bg:ident) => (unsafe { CONTEXT.current_term().color_code = + ColorCode::new(Color::$fg, Color::$bg) }); +} + pub fn print(args: fmt::Arguments) { use core::fmt::Write; unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; @@ -58,10 +67,9 @@ impl Writer { } pub fn prompt(&mut self) { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Blue, Color::Black); + set_color!(Blue); self.write_str("> "); - self.color_code = color_code_save; + set_color!(); flush!(); } @@ -77,17 +85,7 @@ impl Writer { self.write_byte(b'\n'); { let command: &str = &core::str::from_utf8(&self.command).unwrap()[..self.command_len]; - match command { - "shutdown" | "halt" => console::shutdown(), - "reboot" => console::reboot(), - "stack" => console::print_kernel_stack(), - _ => { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Red, Color::Black); - println!("`{}': Command unknown ", command); - self.color_code = color_code_save; - } - } + console::dispatch(command); } self.command_len = 0; self.prompt();