Skip to main content

kernel/kprint/
state.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! kprint State, lives in KSTATE
3//!
4//! Authors: MarioS271
5
6use super::ringbuffer::Ringbuffer;
7use crate::kprint::log_entry::LogLevel;
8use crate::lib::macros::bitflags::bitflags;
9use crate::lib::sync::irq_mutex::{IrqMutex, IrqMutexGuard};
10use core::sync::atomic::{AtomicU8, Ordering};
11
12/// A struct which goes into [`KSTATE`](crate::state::kstate::KSTATE) and contains an [`IrqMutex`]
13/// wrapped [`KPrintState`] and the current `max_log_level` and `log_targets` as [`AtomicU8`]s
14#[repr(align(64))]
15pub struct KPrint {
16    lockable: IrqMutex<KPrintState>,
17    config: KPrintConfig
18}
19impl KPrint {
20    /// Constructor; creates a new [`KPrint`] instance with zeroed values.
21    /// Init needs to be called before using any values in this struct to set the proper default values
22    pub const fn new() -> Self {
23        Self {
24            lockable: IrqMutex::new(KPrintState::new()),
25            config: KPrintConfig::new()
26        }
27    }
28
29    /// Initialize `self.config` to its correct default values
30    pub fn init(&self) {
31        self.config.init();
32    }
33
34    /// Locks and returns an [`IrqMutexGuard`] of [`KPrintState`]
35    pub fn lock(&self) -> IrqMutexGuard<'_, KPrintState> {
36        self.lockable.lock()
37    }
38
39    /// Getter for `self.config`
40    pub fn config(&self) -> &KPrintConfig {
41        &self.config
42    }
43}
44
45/// Inner, mutex-protected struct in [`KPrint`];
46/// holds the kernel [`Ringbuffer`] aswell as the current [`BasicFbState`]
47pub struct KPrintState {
48    pub ring_buffer: Ringbuffer,
49    pub basic_fb_state: BasicFbState
50}
51impl KPrintState {
52    /// Constructor; creates a new [`KPrintState`] instance, which contains a newly created
53    /// [`Ringbuffer`] and a newly created [`BasicFbState`] struct
54    pub const fn new() -> Self {
55        Self {
56            ring_buffer: Ringbuffer::new(),
57            basic_fb_state: BasicFbState::new()
58        }
59    }
60}
61
62/// Holds the kernel log configs like max log level and log targets
63#[repr(align(64))]
64pub struct KPrintConfig {
65    max_log_level: AtomicU8,
66    log_targets: AtomicU8
67}
68impl KPrintConfig {
69    /// Constructor; zero-initialize all values.
70    ///
71    /// > **Important:** The zero-initialized values are NOT the correct defaults. [`Self::init`]
72    /// > must be called first to load the correct defaults.
73    pub const fn new() -> Self {
74        Self {
75            max_log_level: AtomicU8::new(0),
76            log_targets: AtomicU8::new(0)
77        }
78    }
79
80    /// Initialize the inner values to their proper default values
81    pub fn init(&self) {
82        self.max_log_level.store(crate::config::MAX_LOG_LEVEL as u8, Ordering::Release);
83        self.log_targets.store(crate::config::DEFAULT_LOG_TARGETS.as_u8(), Ordering::Release);
84    }
85
86    /// Sets the max log level that will be shown by all `kprint` macro calls
87    pub fn set_max_log_level(&self, log_level: LogLevel) {
88        self.max_log_level.store(log_level as u8, Ordering::Release);
89    }
90
91    /// Sets the log level targets to which `kprint` will dispatch log entries
92    pub fn set_log_targets(&self, log_targets: LogTargets) {
93        self.log_targets.store(log_targets.as_u8(), Ordering::Release);
94    }
95
96    /// Getter for the current max log level
97    pub fn max_log_level(&self) -> LogLevel {
98        LogLevel::from_u8(self.max_log_level.load(Ordering::Relaxed)).unwrap_or(crate::config::MAX_LOG_LEVEL)
99    }
100
101    /// Getter for the current log targets
102    pub fn log_targets(&self) -> LogTargets {
103        LogTargets::from_u8(self.log_targets.load(Ordering::Acquire))
104    }
105}
106
107bitflags!(
108    /// Where to log kernel logs from the `kprint` subsystem
109    LogTargets, u8
110);
111impl LogTargets {
112    pub const ALL: Self = Self(u8::MAX);
113    pub const UART: Self = Self(1 << 0);
114    pub const BASIC_FB: Self = Self(1 << 1);
115
116    /// Check whether the given LogTargets is a valid log target
117    pub fn is_valid_log_target(value: u8) -> bool {
118        if value == Self::UART.as_u8()
119            || value == Self::BASIC_FB.as_u8()
120        { return true; }
121        false
122    }
123}
124
125/// A struct which holds the basic FB state (cursor position)
126pub struct BasicFbState {
127    pub cursor_x: usize,
128    pub cursor_y: usize
129}
130impl BasicFbState {
131    /// Constructor; creates a new [`BasicFbState`] with the cursor at (0, 0)
132    pub const fn new() -> Self {
133        Self {
134            cursor_x: 0,
135            cursor_y: 0
136        }
137    }
138}