Skip to main content

kernel/kprint/receivers/
basic_fb.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! Basic FB KPrint Receiver, receives kprint output to log to the basic framebuffer (if active)
3//!
4//! Authors: MarioS271
5
6use super::KPrintReceiver;
7use crate::kprint::log_entry::{LogEntryHeader, LogLevel};
8use crate::kprint::state::KPrintState;
9use crate::state::simple_state::SIMPLE_STATE;
10
11pub struct BasicFbReceiver;
12
13impl KPrintReceiver for BasicFbReceiver {
14    fn receive(state: &mut KPrintState, header: &LogEntryHeader, text: &str) {
15        if !SIMPLE_STATE.is_basic_fb_initialized() || !SIMPLE_STATE.is_basic_fb_psf2_font_initialized() {
16            return;
17        }
18
19        let log_level_u8 = header.flags_and_level.get(
20            LogEntryHeader::LEVEL_START_BIT,
21            LogEntryHeader::LEVEL_NUM_BITS
22        );
23        let log_level = LogLevel::from_u8(log_level_u8);
24        if log_level.is_none() { return; }
25        let log_level = log_level.unwrap();
26        
27        let log_level_color = log_level.get_color();
28        let log_level_prefix = [log_level.get_letter(), b' '];
29        // Safety: log_level.get_letter() can only return valid characters
30        let log_level_prefix_str = unsafe {
31            core::str::from_utf8_unchecked(&log_level_prefix)
32        };
33
34        let cursor_x = &mut state.basic_fb_state.cursor_x;
35        let cursor_y = &mut state.basic_fb_state.cursor_y;
36
37        // Safety: was already initialized in stage 1
38        let font = unsafe { SIMPLE_STATE.basic_fb_psf2_font() };
39        // Safety: was already initialized in stage 1
40        let fb = unsafe { SIMPLE_STATE.basic_fb().lock() };
41
42        // Draw Log Level Prefix
43        font.draw_string(
44            &*fb,
45            log_level_prefix_str,
46            cursor_x,
47            cursor_y,
48            Some(log_level_color)
49        );
50        // Draw actual text
51        font.draw_string(
52            &*fb,
53            text,
54            cursor_x,
55            cursor_y,
56            None
57        );
58
59        let last_row = fb.height - font.glyph_height();
60        if *cursor_y > last_row {
61            *cursor_y = last_row;
62
63            // Safety: src and dst are within framebuffer bounds, counts derived from fb dimensions
64            unsafe {
65                let src = fb.fb_pointer.add(font.glyph_height() * fb.pixels_per_row);
66                let dst = fb.fb_pointer;
67                let count = (fb.height - font.glyph_height()) * fb.pixels_per_row;
68                core::ptr::copy(src, dst, count);
69            }
70
71            // Safety: iteration range is within framebuffer bounds
72            unsafe {
73                let start = fb.fb_pointer.add((fb.height - font.glyph_height()) * fb.pixels_per_row);
74                core::ptr::write_bytes(start, 0u8, fb.pixels_per_row * font.glyph_height());
75            }
76        }
77    }
78}