Skip to main content

kernel/state/
simple_state.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! Simple State struct; used in early boot and on a kernel panic
3//!
4//! Authors: MarioS271
5
6use crate::drivers::gpu::basic_fb::font::Psf2Font;
7use crate::drivers::gpu::basic_fb::framebuffer::BasicFramebuffer;
8use crate::drivers::tty::uart::Uart;
9use crate::lib::panic::kernel_panic;
10use crate::lib::panic_codes::PanicCode;
11use crate::lib::sync::irq_mutex::IrqMutex;
12use crate::lib::sync::unchecked_cell::UncheckedCell;
13use crate::lib::types::boot_info::PanicAction;
14use core::sync::atomic::{AtomicU8, Ordering};
15
16/// Data structure for keeping the serial UART logger and basic_fb fb resources for early boot and panic
17/// The default initializations should not contain any non-null value in order for [`SIMPLE_STATE`]
18/// to be able to live in `.bss` to reduce binary size
19pub(crate) static SIMPLE_STATE: SimpleKernelState = SimpleKernelState {
20    is_init: AtomicU8::new(0),
21    uart: UncheckedCell::new(),
22    basic_fb: UncheckedCell::new(),
23    basic_fb_psf2_font: UncheckedCell::new(),
24    panic_action: AtomicU8::new(0)
25};
26
27#[repr(align(64))]
28pub struct SimpleKernelState {
29    is_init: AtomicU8,
30    uart: UncheckedCell<IrqMutex<Uart>>,
31    basic_fb: UncheckedCell<IrqMutex<BasicFramebuffer>>,
32    basic_fb_psf2_font: UncheckedCell<Psf2Font>,
33    panic_action: AtomicU8
34}
35
36impl SimpleKernelState {
37    const IS_UART_INIT: u8 = 1 << 0;
38    const IS_BASIC_FB_INIT: u8 = 1 << 1;
39    const IS_BASIC_FB_FONT_INIT: u8 = 1 << 2;
40
41    /// Move the given [`Uart`] into `SIMPLE_STATE::uart`
42    ///
43    /// # Safety
44    /// The caller must guarantee the following:
45    /// - That this method has never been called before and will never be called again
46    /// - That at the time of calling this method, no references or pointers to this data exist
47    /// - While this method is being called, no other CPU is working with the given data
48    pub unsafe fn init_uart(&self, uart: Uart) {
49        if self.is_init.load(Ordering::Acquire) & Self::IS_UART_INIT != 0 {
50            kernel_panic(
51                PanicCode::DoubleInitialization,
52                "Attempted to double-initialize SIMPLE_STATE.uart"
53            );
54        }
55
56        unsafe { self.uart.init(IrqMutex::new(uart)) };
57        self.is_init.fetch_or(Self::IS_UART_INIT, Ordering::Release);
58    }
59
60    /// Move the given [`BasicFramebuffer`] into `SIMPLE_STATE::basic_fb`
61    ///
62    /// # Safety
63    /// The caller must guarantee the following:
64    /// - That this method has never been called before and will never be called again
65    /// - That at the time of calling this method, no references or pointers to this data exist
66    /// - While this method is being called, no other CPU is working with the given data
67    pub unsafe fn init_basic_fb(&self, basic_fb: BasicFramebuffer) {
68        if self.is_init.load(Ordering::Acquire) & Self::IS_BASIC_FB_INIT != 0 {
69            kernel_panic(
70                PanicCode::DoubleInitialization,
71                "Attempted to double-initialize SIMPLE_STATE.basic_fb"
72            );
73        }
74
75        unsafe { self.basic_fb.init(IrqMutex::new(basic_fb)) };
76        self.is_init.fetch_or(Self::IS_BASIC_FB_INIT, Ordering::Release);
77    }
78
79    /// Move the given [`Psf2Font`] into `SIMPLE_STATE::basic_fb_psf2_font`
80    ///
81    /// # Safety
82    /// The caller must guarantee the following:
83    /// - That this method has never been called before and will never be called again
84    /// - That at the time of calling this method, no references or pointers to this data exist
85    /// - While this method is being called, no other CPU is working with the given data
86    pub unsafe fn init_basic_fb_psf2_font(&self, basic_fb_psf2_font: Psf2Font) {
87        if self.is_init.load(Ordering::Acquire) & Self::IS_BASIC_FB_FONT_INIT != 0 {
88            kernel_panic(
89                PanicCode::DoubleInitialization,
90                "Attempted to double-initialize SIMPLE_STATE.basic_fb_psf2_font"
91            );
92        }
93
94        unsafe { self.basic_fb_psf2_font.init(basic_fb_psf2_font) };
95        self.is_init.fetch_or(Self::IS_BASIC_FB_FONT_INIT, Ordering::Release);
96    }
97
98    /// Move the given [`PanicAction`] into `SIMPLE_STATE::panic_action`
99    pub fn set_panic_action(&self, panic_action: PanicAction) {
100        self.panic_action.store(panic_action as u8, Ordering::Release);
101    }
102
103    /// Getter for `SIMPLE_STATE::uart`
104    ///
105    /// # Safety
106    /// The caller must guarantee the following:
107    /// - That this value's `init` method has already been called before
108    /// - That at this method's entire execution time, no mutable references or pointers to this data
109    ///   exist or will exist
110    pub unsafe fn uart(&self) -> &IrqMutex<Uart> {
111        unsafe { self.uart.get() }
112    }
113
114    /// Getter for `SIMPLE_STATE::basic_fb`
115    ///
116    /// # Safety
117    /// The caller must guarantee the following:
118    /// - That this value's `init` method has already been called before
119    /// - That at this method's entire execution time, no mutable references or pointers to this data
120    ///   exist or will exist
121    pub unsafe fn basic_fb(&self) -> &IrqMutex<BasicFramebuffer> {
122        unsafe { self.basic_fb.get() }
123    }
124
125    /// Getter for `SIMPLE_STATE::basic_fb_psf2_font`
126    ///
127    /// # Safety
128    /// The caller must guarantee the following:
129    /// - That this value's `init` method has already been called before
130    /// - That at this method's entire execution time, no mutable references or pointers to this data
131    ///   exist or will exist
132    pub unsafe fn basic_fb_psf2_font(&self) -> &Psf2Font {
133        unsafe { self.basic_fb_psf2_font.get() }
134    }
135
136    /// Getter for `SIMPLE_STATE::panic_action`
137    pub fn panic_action(&self) -> PanicAction {
138        PanicAction::from_u8(self.panic_action.load(Ordering::Acquire)).unwrap_or(crate::config::DEFAULT_PANIC_ACTION)
139    }
140
141    /// Check whether `SIMPLE_STATE::uart` is initialized
142    pub fn is_uart_initialized(&self) -> bool {
143        self.is_init.load(Ordering::Acquire) & Self::IS_UART_INIT != 0
144    }
145
146    /// Check whether `SIMPLE_STATE::basic_fb` is initialized
147    pub fn is_basic_fb_initialized(&self) -> bool {
148        self.is_init.load(Ordering::Acquire) & Self::IS_BASIC_FB_INIT != 0
149    }
150
151    /// Check whether `SIMPLE_STATE::basic_fb_psf2_font` is initialized
152    pub fn is_basic_fb_psf2_font_initialized(&self) -> bool {
153        self.is_init.load(Ordering::Acquire) & Self::IS_BASIC_FB_FONT_INIT != 0
154    }
155}