uefi_loader/
framebuffer.rs

1//! # GOP for the Kernel
2
3use kernel_info::boot::{BootPixelFormat, BootPixelMasks, FramebufferInfo};
4use uefi::boot::ScopedProtocol;
5use uefi::proto::console::gop::{GraphicsOutput, PixelFormat};
6use uefi::{Status, boot};
7
8/// Fetch an optimal framebuffer for the Kernel.
9pub fn get_framebuffer() -> Result<FramebufferInfo, Status> {
10    uefi::println!("Obtaining Graphics Output Protocol (GOP)");
11    let mut gop = match get_gop() {
12        Ok(gop) => gop,
13        Err(e) => {
14            uefi::println!("Failed to get GOP: {e:?}");
15            return Err(Status::UNSUPPORTED);
16        }
17    };
18
19    let mode = gop.current_mode_info();
20    let (framebuffer_width, framebuffer_height) = mode.resolution();
21
22    let (framebuffer_format, framebuffer_masks) = match mode.pixel_format() {
23        PixelFormat::Rgb => (
24            BootPixelFormat::Rgb,
25            BootPixelMasks {
26                red_mask: 0,
27                green_mask: 0,
28                blue_mask: 0,
29                alpha_mask: 0,
30            },
31        ),
32        PixelFormat::Bgr => (
33            BootPixelFormat::Bgr,
34            BootPixelMasks {
35                red_mask: 0,
36                green_mask: 0,
37                blue_mask: 0,
38                alpha_mask: 0,
39            },
40        ),
41        PixelFormat::Bitmask if mode.pixel_bitmask().is_some() => {
42            let mask = mode.pixel_bitmask().unwrap();
43            (
44                BootPixelFormat::Bitmask,
45                BootPixelMasks {
46                    red_mask: mask.red,
47                    green_mask: mask.green,
48                    blue_mask: mask.blue,
49                    alpha_mask: mask.reserved,
50                },
51            )
52        }
53        PixelFormat::BltOnly | PixelFormat::Bitmask => {
54            uefi::println!("Unsupported pixel format: Bitmask");
55            return Err(Status::UNSUPPORTED);
56        }
57    };
58
59    let mut fb = gop.frame_buffer();
60    let framebuffer_ptr = fb.as_mut_ptr();
61    let framebuffer_size = fb.size();
62    let framebuffer_stride = mode.stride();
63
64    let fb = FramebufferInfo {
65        framebuffer_ptr: framebuffer_ptr as u64,
66        framebuffer_size: framebuffer_size as u64,
67        framebuffer_width: framebuffer_width as u64,
68        framebuffer_height: framebuffer_height as u64,
69        framebuffer_stride: framebuffer_stride as u64,
70        framebuffer_format,
71        framebuffer_masks,
72    };
73
74    Ok(fb)
75}
76
77/// Fetch the Graphics Output Protocol (GOP).
78fn get_gop() -> Result<ScopedProtocol<GraphicsOutput>, uefi::Error> {
79    let handle = boot::get_handle_for_protocol::<GraphicsOutput>().map_err(|e| {
80        uefi::println!("Failed to get GOP handle: {e:?}");
81        uefi::Error::new(Status::ABORTED, ())
82    })?;
83
84    let gop = boot::open_protocol_exclusive::<GraphicsOutput>(handle).map_err(|e| {
85        uefi::println!("Failed to open GOP exclusively: {e:?}");
86        uefi::Error::new(Status::ABORTED, ())
87    })?;
88    Ok(gop)
89}