#![feature(no_std, lang_items, const_fn, asm)] #![no_std] #[cfg(test)] #[macro_use] extern crate std; extern crate rlibc; extern { fn asm_printchar() -> u32; fn get_rdtsc() -> u32; fn call_interrupt(); } #[no_mangle] pub extern fn rust_setup_PIC() { PIC::setup_PIC(); } mod PIC { use x86_asm::{outb, inb}; const PIC1_COMMAND: u16 = 0x20; const PIC2_COMMAND: u16 = 0xa0; const PIC1_DATA: u16 = 0x21; const PIC2_DATA: u16 = 0xa1; const INITIALIZE: u8 = 0x11; const ENVIRONMENT: u8 = 0x01; //I don't really know what this does pub fn setup_PIC() { let interrupt_mask1: u8 = 0xfc; let interrupt_mask2: u8 = 0xff; unsafe { asm!("cli"); outb(PIC1_COMMAND, INITIALIZE); outb(PIC2_COMMAND, INITIALIZE); // change IRQ offsets to int 32-47 outb(PIC1_DATA, 32); outb(PIC2_DATA, 40); outb(PIC1_DATA, 0x4); //master: slave IRQ location (IRQ 2) outb(PIC2_DATA, 0x2); //slave: cascade identity outb(PIC1_DATA, ENVIRONMENT); outb(PIC2_DATA, ENVIRONMENT); outb(PIC1_DATA, interrupt_mask1); outb(PIC2_DATA, interrupt_mask2); asm!("sti"); } } } mod x86_asm { pub unsafe fn outb(port: u16, value: u8) { asm!("outb %%dx, %%al" : : "dx" (port), "al"(value)); } pub unsafe fn inb(port: u16) -> u8{ let inval: u8; asm!("inb %dx, %al" : "={al}"(inval) : "{dx}"(port)); return inval; } } #[no_mangle] pub extern fn rust_interrupt_handler() { checkerboard(vga_buffer::Color::White); } #[no_mangle] pub extern fn rust_handle_keyboard(x: u8) { checkerboard(vga_buffer::Color::Green); vga_buffer::print_u32(x as u32, 0); } static mut global_timer_count: u64 = 0; #[no_mangle] pub extern fn rust_handle_timer() { let gtc = unsafe { global_timer_count }; unsafe { global_timer_count += 1; } timer_callback(gtc); } fn timer_callback(count: u64) { if count % 1000 == 0 { checkerboard(vga_buffer::Color::White); } if count % 1000 == 500 { checkerboard(vga_buffer::Color::LightCyan); } vga_buffer::print_u32(count as u32, 0); } #[no_mangle] pub extern fn rust_main() { clear(); checkerboard(vga_buffer::Color::Red); loop { } } fn clear() { use vga_buffer::*; let blank_color = ColorCode::new( Color::White, Color::Black); for i in 0..BUFFER_WIDTH { for j in 0..BUFFER_HEIGHT { write_to_coord(i, j, b' ', blank_color); } } } fn checkerboard(color: vga_buffer::Color) { use vga_buffer::*; let active = ColorCode::new(color, color); let blank = ColorCode::new(Color::White, Color::Black); for i in 0..BUFFER_WIDTH { for j in 0..BUFFER_HEIGHT { if (i + j) % 2 == 0 { write_to_coord(i, j, b' ', active); } else { write_to_coord(i, j, b' ', blank); } } } } // 123 |3,2,1 mod util { pub fn u32_to_chars(n: u32) -> [u8; 10] { let mut accum = [0; 10]; let mut i = 0; let mut val = n; loop { if val < 10 { let ch = b'0' + (val as u8); accum[i] = ch; break; } else { let ch = b'0' + ((val % 10) as u8); val = val / 10; accum[i] = ch; i += 1; } } let mut output = [0; 10]; let mut j = 0; loop { output[j] = accum[i]; j += 1; if i == 0 { break; } i -= 1; } output } #[test] fn test_u32_to_chars() { assert_eq!(u32_to_chars(12345), [b'1', b'2', b'3', b'4', b'5', 0, 0, 0, 0, 0]); assert_eq!(u32_to_chars(9), [b'9', 0, 0, 0, 0, 0, 0, 0, 0, 0]); } } mod vga_buffer { #[repr(u8)] #[derive(Clone, Copy)] pub enum Color { Black = 0, Blue = 1, Green = 2, Cyan = 3, Red = 4, Magenta = 5, Brown = 6, LightGray = 7, DarkGray = 8, LightBlue = 9, LightGreen = 10, LightCyan = 11, LightRed = 12, Pink = 13, Yellow = 14, White = 15, } #[derive(Clone, Copy)] pub struct ColorCode(u8); impl ColorCode { pub const fn new(foreground: Color, background: Color) -> ColorCode { ColorCode((background as u8) << 4 | (foreground as u8)) } } #[repr(C)] struct ScreenChar { ascii_char: u8, color_code: ColorCode } pub const BUFFER_HEIGHT: usize = 25; pub const BUFFER_WIDTH: usize = 80; const BUFFER_PTR: usize = 0xb8000; pub fn charloop() { for ch in 32..255 { let ptr = BUFFER_PTR + 2*ch as usize; let data = ScreenChar { ascii_char: ch, color_code: ColorCode::new(Color::Black, Color::White) }; unsafe { *(ptr as *mut _) = data; } } } pub fn print_array(array: [u8; 10], line: usize, color_code: ColorCode) { let mut x = 0; for ch in array.into_iter() { if *ch == 0 { break; } write_to_coord(x, line, *ch, color_code); x += 1; } } pub fn print_u32(num: u32, location: usize) { let default_color = ColorCode::new(Color::Black, Color::White); let char_array = ::util::u32_to_chars(num); print_array(char_array, location, default_color); } pub fn write_to_coord(x: usize, y: usize, character: u8, color_code: ColorCode) { let ptr = BUFFER_PTR + (2*x as usize) + (BUFFER_WIDTH*2*y as usize); let data = ScreenChar { ascii_char: character, color_code: color_code, }; if x > BUFFER_WIDTH || y > BUFFER_HEIGHT { return; } unsafe { *(ptr as *mut _) = data; } } } #[cfg(not(test))] #[lang = "eh_personality"] extern fn eh_personality() {} #[cfg(not(test))] #[lang = "panic_fmt"] extern fn panic_fmt() -> ! { loop {}}