aboutsummaryrefslogtreecommitdiff
path: root/bunny/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bunny/src/main.rs')
-rw-r--r--bunny/src/main.rs211
1 files changed, 211 insertions, 0 deletions
diff --git a/bunny/src/main.rs b/bunny/src/main.rs
new file mode 100644
index 0000000..21fa9cc
--- /dev/null
+++ b/bunny/src/main.rs
@@ -0,0 +1,211 @@
+#![feature(lang_items, panic_info_message, abi_x86_interrupt, core_intrinsics, asm, link_llvm_intrinsics, int_to_from_bytes)]
+#![no_std]
+#![no_main]
+
+extern crate efi;
+extern crate x86_64;
+extern crate volatile;
+
+#[macro_use]
+mod println;
+mod interrupt;
+mod lapic;
+mod io;
+mod uefi;
+mod inttraits;
+
+use core::panic::PanicInfo;
+use core::ptr;
+use core::slice;
+
+use efi::types::Handle;
+use efi::SystemTable;
+use x86_64::instructions::interrupts;
+use x86_64::registers::control;
+
+use interrupt::*;
+use lapic::*;
+use inttraits::*;
+
+static mut SYSTEM_TABLE: *const SystemTable = 0 as *const SystemTable;
+
+fn serial_poke() {
+ const PORT: u16 = 0x3f8;
+
+ unsafe {
+ asm!("out dx, al" :: "{dx}"(PORT+1), "{al}"(0x00) :: "intel", "volatile");
+ asm!("out dx, al" :: "{dx}"(PORT+3), "{al}"(0x80) :: "intel", "volatile");
+ asm!("out dx, al" :: "{dx}"(PORT+0), "{al}"(0x03) :: "intel", "volatile");
+ asm!("out dx, al" :: "{dx}"(PORT+1), "{al}"(0x00) :: "intel", "volatile");
+ asm!("out dx, al" :: "{dx}"(PORT+3), "{al}"(0x03) :: "intel", "volatile");
+ asm!("out dx, al" :: "{dx}"(PORT+2), "{al}"(0xc7) :: "intel", "volatile");
+ asm!("out dx, al" :: "{dx}"(PORT+4), "{al}"(0x0b) :: "intel", "volatile");
+ }
+
+ for c in b"###*-*-*-*-*-*-*-*-*-*-###\r\n\r\n" {
+ let mut status: u8 = 0;
+ while status & 0x20 == 0 {
+ unsafe {
+ asm!("in al, dx" : "={al}"(status) : "{dx}"(PORT+5) :: "intel", "volatile");
+ }
+ }
+
+ unsafe {
+ asm!("out dx, al" :: "{dx}"(PORT), "{al}"(c) :: "intel", "volatile");
+ }
+ }
+}
+
+#[allow(improper_ctypes)]
+extern "C" {
+ #[link_name = "llvm.x86.rdtsc"]
+ fn rdtsc() -> i64;
+}
+
+fn busy() {
+ let init = unsafe { rdtsc() } as u64;
+ let future = init + 1_000_000;
+
+ let mut now = init;
+
+ while now < future {
+ now = unsafe { rdtsc() } as u64;
+ }
+}
+
+#[no_mangle]
+pub extern fn efi_main(_handle: Handle, systab: &SystemTable) -> ! {
+ /*
+ * Disable interrupts to avoid noise generated before we actually
+ * have anything to do *with* interrupts
+ */
+ interrupts::disable();
+
+ /*
+ * Save EFI system table ptr to globally accessible location.
+ * MUST do this before calling println!(), or just about anything else.
+ */
+ unsafe {
+ SYSTEM_TABLE = systab;
+ }
+
+ println!("FUZZY BUNNIES {}", env!("CARGO_PKG_VERSION"));
+ println!("efi_main @ 0x{:x}", efi_main as *const u8 as usize);
+ dprintln!("CR0: {:x?}, CR3: {:x?}", control::Cr0::read(), control::Cr3::read());
+
+ /* Set up basic exception handlers */
+ register_handlers();
+
+ // serial_poke();
+
+ // unsafe { asm!("hlt"); }
+ // let _mapkey = uefi::dump_mem_map().expect("Unable to read UEFI memory map");
+
+ let code = include_bytes!(concat!(env!("OUT_DIR"), "/ap_boot.bin"));
+ let dest = unsafe {
+ slice::from_raw_parts_mut(0x8000 as *mut u8, code.len())
+ };
+
+ let idtr = interrupt::descriptor();
+ dprintln!("copy {} bytes from 0x{:x} to 0x{:x}",
+ code.len(),
+ code.as_ptr() as usize,
+ dest.as_ptr() as usize);
+
+ dest.copy_from_slice(code);
+
+ let cr3_val: u64;
+ unsafe {
+ asm!("mov $0, cr3" : "=r" (cr3_val) ::: "intel");
+ }
+ dest[code.len()-14..code.len()-10].copy_from_slice(&(cr3_val as u32).as_bytes());
+ dest[code.len()-10..code.len()-8].copy_from_slice(&idtr.0.as_bytes());
+ dest[code.len()-8..].copy_from_slice(&idtr.1.as_bytes());
+ dprintln!("patched: {:x?}", &dest[code.len()-14..]);
+
+ unsafe {
+ ptr::write_volatile(0x6000 as *mut u64, 0);
+ ptr::write_volatile(0x6008 as *mut u64, 0);
+ ptr::write_volatile(0x600c as *mut u64, 0);
+ ptr::write_volatile(0x6010 as *mut u64, 0);
+ asm!("mfence; lfence");
+ }
+
+ /* Disable the PICs to prepare for APIC/IOAPIC */
+ unsafe {
+ io::out::<u8>(io::PIC1_DATA, io::PIC_DISABLE);
+ io::out::<u8>(io::PIC2_DATA, io::PIC_DISABLE);
+ }
+
+ let mut bsp_apic = LocalApic::init();
+ println!("APIC ID: {}, VERSION: {}", bsp_apic.id(), bsp_apic.version());
+
+ bsp_apic.enable();
+
+ dprintln!("APIC enabled");
+
+ /* INIT-SIPI-SIPI */
+ dprintln!("INIT ASSERT");
+ bsp_apic.send_ipi(IpiDestination::AllButMe,
+ IpiTriggerMode::Edge,
+ IpiLevel::Assert,
+ IpiDeliveryMode::Init,
+ 0);
+ busy();
+ // println!("INIT LEVEL DEASSERT");
+ // bsp_apic.send_ipi(IpiDestination::AllButMe,
+ // IpiTriggerMode::Level,
+ // IpiLevel::Deassert,
+ // IpiDeliveryMode::Init,
+ // 0);
+ // busy();
+ println!("SIPI spam");
+ let mut n_aps: u8 = 0;
+ // let mut ap_lock: u8;
+ while n_aps < 3 {
+ dprintln!("SIPI");
+ bsp_apic.send_ipi(IpiDestination::AllButMe,
+ IpiTriggerMode::Edge,
+ IpiLevel::Assert,
+ IpiDeliveryMode::StartUp,
+ 0x08);
+ busy();
+
+ unsafe { asm!("mfence; lfence"); }
+
+ // ap_lock = unsafe { ptr::read_volatile(0x6000 as *const u8) };
+ n_aps = unsafe { ptr::read_volatile(0x6001 as *const u8) };
+
+ // println!("ap_lock: {}, n_aps: {}", ap_lock, n_aps);
+ // {
+ // let ap_stats = unsafe { slice::from_raw_parts(0x6002 as *const u8, n_aps as usize) };
+ // println!("stat: {:x?}", ap_stats);
+ // }
+ }
+
+ interrupts::enable();
+
+ loop {
+ unsafe { asm!("hlt"); }
+ }
+}
+
+#[lang = "eh_personality"]
+#[no_mangle]
+pub extern fn eh_personality() { }
+
+#[no_mangle]
+#[panic_handler]
+pub extern fn panic_impl(pi: &PanicInfo) -> ! {
+ println!("!!! PANIC !!!");
+
+ if let Some(loc) = pi.location() {
+ println!("in file {}:{}:{}", loc.file(), loc.line(), loc.column());
+ }
+
+ if let Some(msg) = pi.message() {
+ println!("{}", msg);
+ }
+
+ loop {}
+}