kernel/
framebuffer.rs

1//! # Kernel Framebuffer helpers
2
3use kernel_info::boot::{BootPixelFormat, FramebufferInfo};
4
5/// Virtual offset inside the HHDM where we map the framebuffer.
6///
7/// We pick **`HHDM_BASE + 1 GiB + 0xB8000`** (“VGA-like”) to stay well clear
8/// of a potential 1 GiB huge page mapping at the very start of the HHDM.
9///
10/// This reduces the risk of having to split a 1 GiB page into 4 KiB pages.
11pub const VGA_LIKE_OFFSET: u64 = (1u64 << 30) + 0x000B_8000; // 1 GiB + 0xB8000 inside HHDM range
12
13#[allow(clippy::missing_safety_doc, clippy::many_single_char_names)]
14pub unsafe fn fill_solid(fb: &FramebufferInfo, r: u8, g: u8, b: u8) {
15    // Nothing to draw into
16    if matches!(fb.framebuffer_format, BootPixelFormat::BltOnly) {
17        return;
18    }
19
20    // Precompute the packed pixel once (little-endian):
21    // - RGB format => bytes [R, G, B, 0xFF] -> value 0xFF_BB_GG_RR
22    // - BGR format => bytes [B, G, R, 0xFF] -> value 0xFF_RR_GG_BB
23    let px: u32 = match fb.framebuffer_format {
24        BootPixelFormat::Rgb => {
25            (0xFFu32 << 24) | (u32::from(b) << 16) | (u32::from(g) << 8) | u32::from(r)
26        }
27        BootPixelFormat::Bgr => {
28            (0xFFu32 << 24) | (u32::from(r) << 16) | (u32::from(g) << 8) | u32::from(b)
29        }
30        BootPixelFormat::Bitmask | BootPixelFormat::BltOnly => return,
31    };
32
33    // 32-bit pixels
34    let base = fb.framebuffer_ptr as *mut u32;
35
36    // pixels per row (GOP "PixelsPerScanLine")
37    let stride = usize::try_from(fb.framebuffer_stride).unwrap_or_default();
38    if stride == 0 {
39        return;
40    }
41
42    let w = usize::try_from(fb.framebuffer_width).unwrap_or_default();
43    let h = usize::try_from(fb.framebuffer_height).unwrap_or_default();
44
45    let start_x = w / 4;
46    let end_x = w * 3 / 4;
47    let start_y = h / 4;
48    let end_y = h * 3 / 4;
49
50    for y in start_y..end_y {
51        // Pointer to first pixel in this row at start_x
52        let mut p = unsafe { base.add(y * stride + start_x) };
53
54        // Fill [start_x, end_x)
55        for _ in start_x..end_x {
56            unsafe {
57                p.write_volatile(px);
58                p = p.add(1);
59            }
60        }
61    }
62}