2015-11-07 22:53:31 -08:00
|
|
|
|
2015-11-08 03:05:27 -08:00
|
|
|
#![feature(no_std, lang_items, const_fn)]
|
2015-11-07 22:53:31 -08:00
|
|
|
#![no_std]
|
|
|
|
|
|
2015-11-10 22:17:54 -08:00
|
|
|
#[cfg(test)]
|
|
|
|
|
#[macro_use]
|
|
|
|
|
extern crate std;
|
|
|
|
|
|
2015-11-08 01:09:07 -08:00
|
|
|
extern crate rlibc;
|
|
|
|
|
|
2015-11-10 02:23:56 -08:00
|
|
|
extern {
|
2015-11-10 02:46:54 -08:00
|
|
|
fn asm_printchar() -> u32;
|
2015-11-10 03:06:14 -08:00
|
|
|
fn get_rdtsc() -> u32;
|
2015-11-10 02:23:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-11-07 22:53:31 -08:00
|
|
|
#[no_mangle]
|
2015-11-07 23:11:07 -08:00
|
|
|
pub extern fn rust_main() {
|
2015-11-10 00:46:08 -08:00
|
|
|
clear();
|
2015-11-10 02:23:56 -08:00
|
|
|
|
2015-11-10 00:52:26 -08:00
|
|
|
checkerboard(vga_buffer::Color::Red);
|
2015-11-10 02:23:56 -08:00
|
|
|
unsafe {
|
2015-11-10 02:46:54 -08:00
|
|
|
let a = asm_printchar();
|
|
|
|
|
if a == 1 {
|
|
|
|
|
checkerboard(vga_buffer::Color::Blue);
|
|
|
|
|
}
|
2015-11-10 02:23:56 -08:00
|
|
|
}
|
2015-11-07 23:11:07 -08:00
|
|
|
|
2015-11-10 20:01:15 -08:00
|
|
|
let mut cur_checkerboard = vga_buffer::Color::Red;
|
|
|
|
|
let mut update_checkerboard = move || {
|
|
|
|
|
cur_checkerboard = match cur_checkerboard {
|
|
|
|
|
vga_buffer::Color::Red => vga_buffer::Color::Blue,
|
|
|
|
|
_ => vga_buffer::Color::Red,
|
|
|
|
|
};
|
|
|
|
|
checkerboard(cur_checkerboard);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut timer;
|
|
|
|
|
let mut prev_timer = 0;
|
|
|
|
|
|
2015-11-10 23:28:36 -08:00
|
|
|
let mut count: u32 = 0;
|
2015-11-10 03:06:14 -08:00
|
|
|
loop {
|
2015-11-10 20:01:15 -08:00
|
|
|
timer = unsafe { get_rdtsc() };
|
2015-11-10 23:28:36 -08:00
|
|
|
let color_code = vga_buffer::ColorCode::new(vga_buffer::Color::White, vga_buffer::Color::Black);
|
2015-11-10 20:01:15 -08:00
|
|
|
if timer - prev_timer > 4_000_000_000 {
|
|
|
|
|
update_checkerboard();
|
2015-11-10 23:28:36 -08:00
|
|
|
|
|
|
|
|
let s = util::u32_to_chars(timer);
|
|
|
|
|
vga_buffer::print_array(s, 10, color_code);
|
|
|
|
|
|
|
|
|
|
vga_buffer::print_array(
|
|
|
|
|
util::u32_to_chars(count), 11, color_code);
|
|
|
|
|
count += 1;
|
|
|
|
|
|
2015-11-10 20:01:15 -08:00
|
|
|
timer = 0;
|
2015-11-10 23:28:36 -08:00
|
|
|
|
2015-11-10 20:01:15 -08:00
|
|
|
}
|
2015-11-10 23:28:36 -08:00
|
|
|
|
2015-11-10 03:06:14 -08:00
|
|
|
}
|
2015-11-10 03:02:30 -08:00
|
|
|
|
2015-11-10 00:46:08 -08:00
|
|
|
loop {}
|
|
|
|
|
}
|
2015-11-08 03:05:27 -08:00
|
|
|
|
2015-11-10 00:46:08 -08:00
|
|
|
fn clear() {
|
2015-11-10 00:52:26 -08:00
|
|
|
use vga_buffer::*;
|
2015-11-08 03:05:27 -08:00
|
|
|
|
2015-11-10 00:52:26 -08:00
|
|
|
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);
|
|
|
|
|
}
|
2015-11-10 00:46:08 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-11-07 23:11:07 -08:00
|
|
|
}
|
2015-11-07 22:53:31 -08:00
|
|
|
|
2015-11-10 22:17:54 -08:00
|
|
|
|
|
|
|
|
// 123 |3,2,1
|
|
|
|
|
mod util {
|
2015-11-10 23:28:36 -08:00
|
|
|
pub fn u32_to_chars(n: u32) -> [u8; 10] {
|
2015-11-10 22:17:54 -08:00
|
|
|
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]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-11-08 03:05:27 -08:00
|
|
|
mod vga_buffer {
|
|
|
|
|
#[repr(u8)]
|
2015-11-10 00:52:26 -08:00
|
|
|
#[derive(Clone, Copy)]
|
2015-11-08 03:05:27 -08:00
|
|
|
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)]
|
2015-11-10 00:46:08 -08:00
|
|
|
pub struct ColorCode(u8);
|
2015-11-08 03:05:27 -08:00
|
|
|
impl ColorCode {
|
2015-11-10 00:46:08 -08:00
|
|
|
pub const fn new(foreground: Color, background: Color) -> ColorCode {
|
2015-11-08 03:05:27 -08:00
|
|
|
ColorCode((background as u8) << 4 | (foreground as u8))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
struct ScreenChar {
|
|
|
|
|
ascii_char: u8,
|
|
|
|
|
color_code: ColorCode
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 00:46:08 -08:00
|
|
|
pub const BUFFER_HEIGHT: usize = 25;
|
|
|
|
|
pub const BUFFER_WIDTH: usize = 80;
|
2015-11-08 03:05:27 -08:00
|
|
|
const BUFFER_PTR: usize = 0xb8000;
|
|
|
|
|
|
2015-11-10 01:25:46 -08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 23:28:36 -08:00
|
|
|
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 {
|
2015-11-10 03:02:30 -08:00
|
|
|
break;
|
|
|
|
|
}
|
2015-11-10 23:28:36 -08:00
|
|
|
write_to_coord(x, line, *ch, color_code);
|
|
|
|
|
x += 1;
|
2015-11-10 03:02:30 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 00:46:08 -08:00
|
|
|
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);
|
2015-11-08 03:05:27 -08:00
|
|
|
let data = ScreenChar {
|
|
|
|
|
ascii_char: character,
|
2015-11-10 00:46:08 -08:00
|
|
|
color_code: color_code,
|
2015-11-08 03:05:27 -08:00
|
|
|
};
|
2015-11-10 00:46:08 -08:00
|
|
|
|
|
|
|
|
if x > BUFFER_WIDTH || y > BUFFER_HEIGHT {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-08 03:05:27 -08:00
|
|
|
unsafe {
|
|
|
|
|
*(ptr as *mut _) = data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 22:17:54 -08:00
|
|
|
#[cfg(not(test))]
|
2015-11-07 22:53:31 -08:00
|
|
|
#[lang = "eh_personality"]
|
|
|
|
|
extern fn eh_personality() {}
|
|
|
|
|
|
2015-11-10 22:17:54 -08:00
|
|
|
#[cfg(not(test))]
|
2015-11-07 22:53:31 -08:00
|
|
|
#[lang = "panic_fmt"]
|
|
|
|
|
extern fn panic_fmt() -> ! { loop {}}
|