Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5e95f52

Browse files
Clean up framebuffer abstraction (#64)
1 parent 08ffc84 commit 5e95f52

File tree

2 files changed

+107
-35
lines changed
  • src/proto/console
  • uefi-test-runner/src/proto/console

2 files changed

+107
-35
lines changed

‎src/proto/console/gop.rs

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
//! In theory, a buffer with a width of 640 should have (640 * 4) bytes per row,
2424
//! but in practice there might be some extra padding used for efficiency.
2525
26+
use core::marker::PhantomData;
27+
use core::mem;
2628
use core::ptr;
2729
use crate::{Completion, Result, Status};
2830

@@ -249,29 +251,20 @@ impl GraphicsOutput {
249251
*self.mode.info
250252
}
251253

252-
/// Returns the base pointer and size (in bytes) of the framebuffer
253-
///
254-
/// To use this pointer safely, a caller must...
255-
/// - Honor the pixel format specificed by the mode info
256-
/// - Keep pointer accesses in bound
257-
/// - Use volatile writes so that the compiler does not optimize out or
258-
/// aggressively reorder framebuffer accesses
259-
/// - Make sure that the pointer is not used beyond its validity limit
260-
///
261-
/// Although the UEFI spec makes no clear statement about framebuffer
262-
/// pointer validity, it seems reasonable to expect the framebuffer pointer
263-
/// to be valid until the next mode change. In the future, a safer interface
264-
/// may be introduced, which would enforce volatile writes and automatically
265-
/// check for dangling pointers using Rust's borrow checker.
266-
pub fn frame_buffer(&mut self) -> (*mut u8, usize) {
254+
/// Access the frame buffer directly
255+
pub fn frame_buffer(&mut self) -> FrameBuffer {
267256
assert!(
268257
self.mode.info.format != PixelFormat::BltOnly,
269258
"Cannot access the framebuffer in a Blt-only mode"
270259
);
271-
let data = self.mode.fb_address as *mut u8;
272-
let len = self.mode.fb_size;
260+
let base = self.mode.fb_address as *mut u8;
261+
let size = self.mode.fb_size;
273262

274-
(data, len)
263+
FrameBuffer {
264+
base,
265+
size,
266+
_lifetime: PhantomData,
267+
}
275268
}
276269
}
277270

@@ -519,3 +512,88 @@ pub enum BltOp<'a> {
519512
dims: (usize, usize),
520513
},
521514
}
515+
516+
/// Direct access to a memory-mapped frame buffer
517+
pub struct FrameBuffer<'a> {
518+
base: *mut u8,
519+
size: usize,
520+
_lifetime: PhantomData<&'a mut u8>,
521+
}
522+
523+
impl<'a> FrameBuffer<'a> {
524+
/// Access the raw framebuffer pointer
525+
///
526+
/// To use this pointer safely and correctly, you must...
527+
/// - Honor the pixel format and stride specified by the mode info
528+
/// - Keep memory accesses in bound
529+
/// - Use volatile reads and writes
530+
/// - Make sure that the pointer does not outlive the FrameBuffer
531+
pub fn as_mut_ptr(&mut self) -> *mut u8 {
532+
self.base
533+
}
534+
535+
/// Query the framebuffer size in bytes
536+
pub fn size(&self) -> usize {
537+
self.size
538+
}
539+
540+
/// Modify the i-th byte of the frame buffer
541+
///
542+
/// This operation is unsafe because...
543+
/// - You must honor the pixel format and stride specified by the mode info
544+
/// - There is no bound checking on memory accesses in release mode
545+
#[inline]
546+
pub unsafe fn write_byte(&mut self, index: usize, value: u8) {
547+
debug_assert!(index < self.size, "Frame buffer accessed out of bounds");
548+
self.base.add(index).write_volatile(value)
549+
}
550+
551+
/// Read the i-th byte of the frame buffer
552+
///
553+
/// This operation is unsafe because...
554+
/// - You must honor the pixel format and stride specified by the mode info
555+
/// - There is no bound checking on memory accesses in release mode
556+
#[inline]
557+
pub unsafe fn read_byte(&self, index: usize) -> u8 {
558+
debug_assert!(index < self.size, "Frame buffer accessed out of bounds");
559+
self.base.add(index).read_volatile()
560+
}
561+
562+
/// Write a value in the frame buffer, starting at the i-th byte
563+
///
564+
/// We only recommend using this method with [u8; N] arrays. Once Rust has
565+
/// const generics, it will be deprecated and replaced with a write_bytes()
566+
/// method that only accepts [u8; N] input.
567+
///
568+
/// This operation is unsafe because...
569+
/// - It is your reponsibility to make sure that the value type makes sense
570+
/// - You must honor the pixel format and stride specified by the mode info
571+
/// - There is no bound checking on memory accesses in release mode
572+
#[inline]
573+
pub unsafe fn write_value<T>(&mut self, index: usize, value: T) {
574+
debug_assert!(
575+
index.saturating_add(mem::size_of::<T>()) <= self.size,
576+
"Frame buffer accessed out of bounds"
577+
);
578+
(self.base.add(index) as *mut T).write_volatile(value)
579+
}
580+
581+
/// Read a value from the frame buffer, starting at the i-th byte
582+
///
583+
/// We only recommend using this method with [u8; N] arrays. Once Rust has
584+
/// const generics, it will be deprecated and replaced with a read_bytes()
585+
/// method that only accepts [u8; N] input.
586+
///
587+
/// This operation is unsafe because...
588+
/// - It is your reponsibility to make sure that the value type makes sense
589+
/// - You must honor the pixel format and stride specified by the mode info
590+
/// - There is no bound checking on memory accesses in release mode
591+
#[inline]
592+
pub unsafe fn read_value<T>(&self, index: usize) -> T {
593+
debug_assert!(
594+
index.saturating_add(mem::size_of::<T>()) <= self.size,
595+
"Frame buffer accessed out of bounds"
596+
);
597+
(self.base.add(index) as *const T).read_volatile()
598+
}
599+
}

‎uefi-test-runner/src/proto/console/gop.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use uefi::prelude::*;
2-
use uefi::proto::console::gop::{BltOp, BltPixel, GraphicsOutput, PixelFormat};
2+
use uefi::proto::console::gop::{BltOp, BltPixel, FrameBuffer,GraphicsOutput, PixelFormat};
33
use uefi::table::boot::BootServices;
44
use uefi_exts::BootServicesExt;
55

@@ -54,20 +54,14 @@ fn draw_fb(gop: &mut GraphicsOutput) {
5454
let stride = mi.stride();
5555
let (width, height) = mi.resolution();
5656

57-
let (fb_base, _fb_size) = gop.frame_buffer();
57+
let mut fb = gop.frame_buffer();
5858

59-
type PixelWriter = unsafe fn(*mut u8, [u8; 3]);
60-
unsafe fn write_pixel_rgb(pixel_base: *mut u8, rgb: [u8; 3]) {
61-
let [r, g, b] = rgb;
62-
pixel_base.add(0).write_volatile(r);
63-
pixel_base.add(1).write_volatile(g);
64-
pixel_base.add(2).write_volatile(b);
59+
type PixelWriter = unsafe fn(&mut FrameBuffer, usize, [u8; 3]);
60+
unsafe fn write_pixel_rgb(fb: &mut FrameBuffer, pixel_base: usize, rgb: [u8; 3]) {
61+
fb.write_value(pixel_base, rgb);
6562
};
66-
unsafe fn write_pixel_bgr(pixel_base: *mut u8, rgb: [u8; 3]) {
67-
let [r, g, b] = rgb;
68-
pixel_base.add(0).write_volatile(b);
69-
pixel_base.add(1).write_volatile(g);
70-
pixel_base.add(2).write_volatile(r);
63+
unsafe fn write_pixel_bgr(fb: &mut FrameBuffer, pixel_base: usize, rgb: [u8; 3]) {
64+
fb.write_value(pixel_base, [rgb[2], rgb[1], rgb[0]]);
7165
};
7266
let write_pixel: PixelWriter = match mi.pixel_format() {
7367
PixelFormat::RGB => write_pixel_rgb,
@@ -78,15 +72,15 @@ fn draw_fb(gop: &mut GraphicsOutput) {
7872
}
7973
};
8074

81-
let fill_rectangle = |(x1, y1), (x2, y2), color| {
75+
let mutfill_rectangle = |(x1, y1), (x2, y2), color| {
8276
assert!((x1 < width) && (x2 < width), "Bad X coordinate");
8377
assert!((y1 < height) && (y2 < height), "Bad Y coordinate");
8478
for row in y1..y2 {
8579
for column in x1..x2 {
8680
unsafe {
87-
let index = (row * stride) + column;
88-
let pixel_base = fb_base.add(4 * index);
89-
write_pixel(pixel_base, color);
81+
let pixel_index = (row * stride) + column;
82+
let pixel_base = 4 * pixel_index;
83+
write_pixel(&mut fb,pixel_base, color);
9084
}
9185
}
9286
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /