//! `SkavOS` #![deny( clippy::complexity, clippy::correctness, clippy::nursery, clippy::pedantic, clippy::perf, clippy::restriction, clippy::style )] #![allow( clippy::arithmetic_side_effects, clippy::as_conversions, clippy::blanket_clippy_restriction_lints, clippy::else_if_without_else, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::expect_used, clippy::implicit_return, clippy::integer_arithmetic, clippy::integer_division, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::missing_trait_methods, clippy::mod_module_files, clippy::panic, clippy::panic_in_result_fn, clippy::pattern_type_mismatch, clippy::question_mark_used, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_unrelated, clippy::unreachable, clippy::unwrap_in_result, clippy::wildcard_in_or_patterns, const_item_mutation )] #![cfg_attr( test, allow( clippy::assertions_on_result_states, clippy::collection_is_never_read, clippy::enum_glob_use, clippy::indexing_slicing, clippy::non_ascii_literal, clippy::too_many_lines, clippy::unwrap_used, clippy::wildcard_imports ) )] #![no_std] #![no_main] #![feature(abi_x86_interrupt)] #![feature(alloc_error_handler)] #![feature(const_extern_fn)] #![feature(const_mut_refs)] #![feature(const_trait_impl)] #![feature(custom_test_frameworks)] #![feature(error_in_core)] #![feature(extend_one)] #![feature(int_roundings)] #![feature(iter_advance_by)] #![feature(new_uninit)] #![feature(no_coverage)] #![feature(strict_provenance)] #![feature(trait_upcasting)] #![feature(vec_into_raw_parts)] #![reexport_test_harness_main = "test_main"] #![test_runner(test::runner)] extern crate alloc; mod encoding; mod fs; mod kernel; mod macros; mod mutex; mod syslog; mod user; #[cfg(test)] mod test; use alloc::sync::Arc; use alloc::vec::Vec; use core::alloc::Layout; use bootloader_api::config::{Mapping, Mappings}; use bootloader_api::{entry_point, BootInfo, BootloaderConfig}; use kernel::device::storage::Device; use kernel::device::{STORAGE_CONTROLLERS, UEFI_UUID}; use kernel::task::executor::Executor; use kernel::task::Task; use log::{logger, set_logger, set_max_level, LevelFilter}; use spin::Mutex; #[cfg(test)] use test::exit; use user::tty::print_key; #[cfg(not(test))] use x86_64::instructions; use self::syslog::SYS_LOGGER; use crate::kernel::interrupt::cmos::CMOS; /// Configuration of the bootloader /// /// The only change from the default configuration is the dynamic mapping to the physical memory const BOOTLOADER_CONFIG: BootloaderConfig = { let mut config = BootloaderConfig::new_default(); config.mappings = Mappings::new_default(); config.mappings.page_table_recursive = Some(Mapping::Dynamic); config }; /// Main function of the kernel #[no_coverage] #[allow(unreachable_code)] fn kernel_main(boot_info: &'static mut BootInfo) -> ! { set_logger(&SYS_LOGGER).expect("Could not initialize the logger"); set_max_level(LevelFilter::Trace); kernel::init(boot_info); let storage_devices = STORAGE_CONTROLLERS .get() .expect("Storage controllers have not been initialized yet") .iter() .flat_map(|controller| controller.lock().devices()) .collect::<Vec<Arc<Mutex<dyn Device + Send>>>>() .into_iter() .filter(|device| device.lock().uuid() != UEFI_UUID) .collect::<Vec<Arc<Mutex<dyn Device + Send>>>>(); if let Some(device) = storage_devices.first() { fs::init(&Arc::clone(device)); } #[cfg(test)] { test_main(); exit(); }; println!("Hello world!"); let rtc = CMOS.rtc(); println!("It is currently : {:0>2}:{:0>2}:{:0>2} (UTC+0)", rtc.hour, rtc.minute, rtc.second); let mut executor = Executor::new(); executor.spawn(Task::new(print_key())); executor.run(); } /// Panic prints on screen the reason #[panic_handler] #[no_coverage] fn panic(info: &core::panic::PanicInfo) -> ! { logger().flush(); #[cfg(not(test))] { println!("kernel panic: {:#?}", info); loop { instructions::hlt(); } } #[cfg(test)] { use qemu_exit::QEMUExit; println!("[failed]\n"); println!("Error: {}\n", info); qemu_exit::X86::new(0xf4, 13).exit_failure(); } } /// Allocation failure handler #[alloc_error_handler] #[no_coverage] fn alloc_error_handler(layout: Layout) -> ! { panic!("allocation error: {:?}", layout); } entry_point!(kernel_main, config = &BOOTLOADER_CONFIG);