#![feature(lang_items, panic_info_message, abi_x86_interrupt, core_intrinsics, asm, link_llvm_intrinsics, abi_efiapi)] #![no_std] #![no_main] extern crate rlibc; extern crate alloc; extern crate uefi; extern crate uefi_services; #[macro_use] extern crate log; #[macro_use] mod println; mod interrupt; mod lapic; mod io; mod inttraits; use core::ptr; use core::ffi::c_void; use core::sync::atomic::{AtomicUsize, Ordering}; use uefi::prelude::*; use uefi::proto::pi::mp::MpServices; use x86_64::instructions::interrupts; use self::interrupt::*; const NUM_CORES: usize = 4; // const RESOLUTION: (usize, usize) = (1920, 1080); static mut SYSTEM_TABLE: Option> = None; static AP_COUNT: AtomicUsize = AtomicUsize::new(0); pub(crate) fn system_table() -> &'static SystemTable { unsafe { SYSTEM_TABLE.as_ref().expect("System table is missing!") } } #[allow(improper_ctypes)] extern "C" { #[link_name = "llvm.x86.rdtsc"] fn rdtsc() -> i64; } /* Awful way of busy-waiting some constant-ish number of cycle-ish intervals */ 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; } } extern "efiapi" fn ap_main(_ctxt: *mut c_void) { AP_COUNT.fetch_add(1, Ordering::SeqCst); // loop { // unsafe { asm!("hlt"); } // } } #[entry] fn efi_main(_handle: uefi::Handle, systab: SystemTable) -> Status { /* * Disable interrupts to avoid noise generated before we actually * have anything to do *with* interrupts */ uefi_services::init(&systab).expect_success("Failed to init services"); systab.stdout() .reset(false) .expect_success("Failed to reset stdout"); interrupts::disable(); /* Save global reference to the system table */ unsafe { SYSTEM_TABLE = Some(systab); } /* Set up basic exception handlers */ register_handlers(); interrupts::enable(); info!("FUZZY BUNNIES {}", env!("CARGO_PKG_VERSION")); info!("efi_main @ 0x{:x}", efi_main as *const u8 as usize); let mp = unsafe { &*system_table() .boot_services() .locate_protocol::() .expect_success("Failed to get MP services") .get() }; info!("Processors: {:?}", mp.get_number_of_processors()); mp.startup_all_aps(false, ap_main, ptr::null_mut(), None) .expect_success("Failed to start APs"); info!("huh?"); while AP_COUNT.load(Ordering::SeqCst) < NUM_CORES - 1 { info!("{} cores", AP_COUNT.load(Ordering::SeqCst)); busy(); } info!("{} APs online", AP_COUNT.load(Ordering::SeqCst)); /* All good, turn interrupts back on and idle */ interrupts::enable(); loop { unsafe { asm!("hlt"); } } }