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}