Testing groundwork
This commit is contained in:
parent
079579af06
commit
be6acf47da
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||
authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"]
|
||||
edition = "2018"
|
||||
description = "Support for vga specific functions, data structures, and registers."
|
||||
documentation = "https://docs.rs/vga"
|
||||
keywords = [
|
||||
"vga",
|
||||
"no_std",
|
||||
|
|
|
@ -14,5 +14,5 @@ mod registers;
|
|||
pub mod vga;
|
||||
mod writers;
|
||||
|
||||
pub use self::vga::VGA;
|
||||
pub use self::vga::{VideoMode, VGA};
|
||||
pub use self::writers::{Graphics640x480x16, Text40x25, Text40x50, Text80x25};
|
||||
|
|
|
@ -5,9 +5,11 @@ authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bootloader = "0.8.9"
|
||||
bootloader = { version = "0.8.9", features = ["map_physical_memory"] }
|
||||
conquer-once = { version = "0.2.0", default-features = false }
|
||||
spinning_top = { version = "0.1.0", features = ["nightly"] }
|
||||
pic8259_simple = "0.1.1"
|
||||
vga = { path = "../" }
|
||||
uart_16550 = "0.2.4"
|
||||
x86_64 = "0.9.6"
|
||||
|
||||
|
|
68
testing/src/interrupts.rs
Normal file
68
testing/src/interrupts.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use crate::gdt;
|
||||
use crate::{hlt_loop, serial_print, serial_println};
|
||||
use conquer_once::spin::Lazy;
|
||||
use core::convert::Into;
|
||||
use pic8259_simple::ChainedPics;
|
||||
use spinning_top::Spinlock;
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||||
|
||||
pub const PIC_1_OFFSET: u8 = 32;
|
||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum InterruptIndex {
|
||||
Timer = PIC_1_OFFSET,
|
||||
Keyboard,
|
||||
}
|
||||
|
||||
impl Into<u8> for InterruptIndex {
|
||||
fn into(self) -> u8 {
|
||||
self as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<usize> for InterruptIndex {
|
||||
fn into(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub static PICS: Spinlock<ChainedPics> =
|
||||
Spinlock::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||
|
||||
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||
unsafe {
|
||||
idt.double_fault
|
||||
.set_handler_fn(double_fault_handler)
|
||||
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
}
|
||||
|
||||
idt
|
||||
});
|
||||
|
||||
pub fn init_idt() {
|
||||
IDT.load();
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn double_fault_handler(
|
||||
stack_frame: &mut InterruptStackFrame,
|
||||
_error_code: u64,
|
||||
) -> ! {
|
||||
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn page_fault_handler(
|
||||
stack_frame: &mut InterruptStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
) {
|
||||
use x86_64::registers::control::Cr2;
|
||||
|
||||
serial_print!("EXCEPTION: PAGE FAULT");
|
||||
serial_println!("Accessed Address: {:?}", Cr2::read());
|
||||
serial_println!("Error Code: {:?}", error_code);
|
||||
serial_println!("{:#?}", stack_frame);
|
||||
hlt_loop();
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#![cfg_attr(test, no_main)]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
|
@ -6,9 +7,9 @@
|
|||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[macro_use]
|
||||
pub mod serial;
|
||||
pub mod gdt;
|
||||
pub mod interrupts;
|
||||
pub mod serial;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u32)]
|
||||
|
@ -26,6 +27,12 @@ pub fn exit_qemu(exit_code: QemuExitCode) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn hlt_loop() -> ! {
|
||||
loop {
|
||||
x86_64::instructions::hlt();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_runner(tests: &[&dyn Fn()]) {
|
||||
serial_println!("Running {} tests", tests.len());
|
||||
for test in tests {
|
||||
|
|
|
@ -5,23 +5,35 @@
|
|||
#![test_runner(testing::test_runner)]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use testing::{serial_print, serial_println};
|
||||
use testing::{gdt, interrupts, serial_print, serial_println};
|
||||
use vga::{VideoMode, VGA};
|
||||
|
||||
#[no_mangle] // don't mangle the name of this function
|
||||
pub extern "C" fn _start() -> ! {
|
||||
init();
|
||||
test_main();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn init() {
|
||||
gdt::init();
|
||||
interrupts::init_idt();
|
||||
unsafe { interrupts::PICS.lock().initialize() };
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
testing::test_panic_handler(info)
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn basic_boot() {
|
||||
serial_print!("basic_boot... ");
|
||||
assert_eq!(0, 0);
|
||||
fn set_mode_80x25() {
|
||||
serial_print!("mode 80x25... ");
|
||||
|
||||
let mut vga = VGA.lock();
|
||||
vga.set_video_mode(VideoMode::Mode80x25);
|
||||
|
||||
serial_println!("[ok]");
|
||||
}
|
Loading…
Reference in a new issue