#![feature(panic_implementation)] // required for defining the panic handler #![feature(abi_x86_interrupt)] #![no_std] // don't link the Rust standard library #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] #[macro_use] extern crate blog_os; extern crate x86_64; #[macro_use] extern crate lazy_static; use blog_os::interrupts::{self, PICS}; use core::panic::PanicInfo; /// This function is the entry point, since the linker looks for a function /// named `_start` by default. #[cfg(not(test))] #[no_mangle] // don't mangle the name of this function pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); blog_os::gdt::init(); init_idt(); unsafe { PICS.lock().initialize() }; x86_64::instructions::interrupts::enable(); println!("It did not crash!"); blog_os::hlt_loop(); } /// This function is called on panic. #[cfg(not(test))] #[panic_implementation] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { println!("{}", info); blog_os::hlt_loop(); } use x86_64::structures::idt::{ExceptionStackFrame, InterruptDescriptorTable}; lazy_static! { static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); unsafe { idt.double_fault .set_handler_fn(double_fault_handler) .set_stack_index(blog_os::gdt::DOUBLE_FAULT_IST_INDEX); } let timer_interrupt_id = usize::from(interrupts::TIMER_INTERRUPT_ID); idt[timer_interrupt_id].set_handler_fn(timer_interrupt_handler); let keyboard_interrupt_id = usize::from(interrupts::KEYBOARD_INTERRUPT_ID); idt[keyboard_interrupt_id].set_handler_fn(keyboard_interrupt_handler); idt }; } pub fn init_idt() { IDT.load(); } extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut ExceptionStackFrame) { println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); } extern "x86-interrupt" fn double_fault_handler( stack_frame: &mut ExceptionStackFrame, _error_code: u64, ) { println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); loop {} } extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut ExceptionStackFrame) { print!("."); unsafe { PICS.lock() .notify_end_of_interrupt(interrupts::TIMER_INTERRUPT_ID) } } extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: &mut ExceptionStackFrame) { use x86_64::instructions::port::Port; let port = Port::new(0x60); let scancode: u8 = unsafe { port.read() }; let key = match scancode { 0x02 => Some('1'), 0x03 => Some('2'), 0x04 => Some('3'), 0x05 => Some('4'), 0x06 => Some('5'), 0x07 => Some('6'), 0x08 => Some('7'), 0x09 => Some('8'), 0x0a => Some('9'), 0x0b => Some('0'), _ => None, }; if let Some(key) = key { print!("{}", key); } unsafe { PICS.lock() .notify_end_of_interrupt(interrupts::KEYBOARD_INTERRUPT_ID) } }