1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
//! Placeholder no-op HAL implementation
use core::default::Default;
use lazy_static::lazy_static;
use slos_helpers::UnsafeContainer;
use crate::{SystemConsole, SystemCpu, SystemHardware, SystemKmainHooks};
mod console;
pub use self::console::{NullConsole, NULL_CONSOLE};
#[cfg(test)]
mod tests;
lazy_static! {
/// Global instance of the [`NullSystem`]
pub static ref SYSTEM: UnsafeContainer<NullSystem> = UnsafeContainer::new(Default::default());
}
/// A [`SystemHardware`] implementation where (almost) everything has no-op
/// implementations
///
/// # Behaviour
///
/// The following general rules apply:
///
/// Methods on HAL traits that return `&'static mut T` references to other HAL
/// trait objects return references to valid things, but those things are also
/// all no-op implementations (for example, [`NullConsole`]).
///
/// All methods that do not return a value are implemented as empty functions.
///
/// All methods that return a value will return either (a) a "sensible" value,
/// in the case where the value is critical to the kernel, (b) the same value
/// that [`Default::default`] would return, where `Default` is implemented for
/// the type, or (c) a manually-constructed default value for the type that
/// will make any operations on that type into no-ops.
///
/// ## Exceptions to the rules
///
/// - [`SystemHardware::system_name`] returns "slos-hal-nullsystem".
///
/// - [`SystemHardware::has_requested_return`] will return the value of the
/// `has_requested_return` field of the struct - this field is set to
/// `false` in the constructor, and set to `true` on every call to the
/// [`SystemKmainHooks::hook_kmain_loop_head`] method. This is done so that
/// `kmain` will iterate exactly **once** before returning.
///
/// - If the `is_virtualized` field of this struct is set to `true`, the
/// [`SystemHardware::virtualization`] method will return a value indicating
/// that the system is virtualized (the "virtualization type" field of the
/// value is set to [`SystemHardware::system_name`]). If the field is set to
/// `false`, [`None`][Option::None] is returned.
///
/// # Default values
///
/// This struct implements the [`Default`] trait, these are the values that
/// are set in that constructor:
///
/// ```
/// # use slos_hal::null_system::NullSystem;
/// # let sys: NullSystem = {
/// NullSystem {
/// has_requested_return: false,
/// is_virtualized: true,
/// }
/// # };
/// #
/// # // let's check that the documentation is actually correct, huh
/// # assert_eq!(sys, core::default::Default::default());
/// ```
///
/// # Safety
///
/// This implementation will never panic directly.
#[derive(Debug, PartialEq)]
pub struct NullSystem {
/// Whether to request a `kmain` return
pub has_requested_return: bool,
/// Whether to indicate the system is virtualized
pub is_virtualized: bool,
}
impl Default for NullSystem {
fn default() -> Self {
Self {
has_requested_return: false,
is_virtualized: true,
}
}
}
impl SystemCpu for NullSystem {
fn interrupts_disable(&mut self) {}
fn interrupts_enable(&mut self) {}
fn halt(&mut self) {}
fn interrupts_are_enabled(&self) -> bool {
false
}
}
impl SystemKmainHooks for NullSystem {
fn hook_kmain_loop_head(&mut self) {
self.has_requested_return = true;
}
}
impl SystemHardware for NullSystem {
fn system_name(&self) -> &'static str {
concat!(env!("CARGO_PKG_NAME"), "-nullsystem")
}
fn console(&mut self) -> &'static mut dyn SystemConsole {
NULL_CONSOLE.get()
}
fn has_requested_return(&self) -> bool {
self.has_requested_return
}
fn current_cpu(&mut self) -> &'static mut dyn SystemCpu {
SYSTEM.get()
}
fn virtualization(&self) -> Option<(&'static str, ())> {
match self.is_virtualized {
true => Some((self.system_name(), ())),
false => None,
}
}
}