5050//! You will have to implement your own double buffering if you want to
5151//! avoid tearing with animations.
5252
53+ use crate :: prelude:: BootServices ;
5354use crate :: proto:: unsafe_protocol;
5455use crate :: util:: usize_from_u32;
5556use crate :: { Result , StatusExt } ;
@@ -75,27 +76,37 @@ pub struct GraphicsOutput(GraphicsOutputProtocol);
7576impl GraphicsOutput {
7677 /// Returns information for an available graphics mode that the graphics
7778 /// device and the set of active video output devices supports.
78- pub fn query_mode ( & self , index : u32 ) -> Result < Mode > {
79+ pub fn query_mode ( & self , index : u32 , bs : & BootServices ) -> Result < Mode > {
7980 let mut info_sz = 0 ;
80- let mut info = ptr:: null ( ) ;
81+ let mut info_heap_ptr = ptr:: null ( ) ;
82+ // query_mode allocates a buffer and stores the heap ptr in the provided
83+ // variable. In this buffer, the queried data can be found.
84+ unsafe { ( self . 0 . query_mode ) ( & self . 0 , index, & mut info_sz, & mut info_heap_ptr) }
85+ . to_result_with_val ( || {
86+ // Transform to owned info on the stack.
87+ let info = unsafe { * info_heap_ptr } ;
88+
89+ let info_heap_ptr = info_heap_ptr. cast :: < u8 > ( ) . cast_mut ( ) ;
90+
91+ // User has no benefit from propagating this error. If this
92+ // fails, it is an error of the UEFI implementation.
93+ bs. free_pool ( info_heap_ptr)
94+ . expect ( "buffer should be deallocatable" ) ;
8195
82- unsafe { ( self . 0 . query_mode ) ( & self . 0 , index, & mut info_sz, & mut info) } . to_result_with_val (
83- || {
84- let info = unsafe { * info } ;
8596 Mode {
8697 index,
8798 info_sz,
8899 info : ModeInfo ( info) ,
89100 }
90- } ,
91- )
101+ } )
92102 }
93103
94104 /// Returns information about all available graphics modes.
95105 #[ must_use]
96- pub fn modes ( & self ) -> ModeIter {
106+ pub fn modes < ' a > ( & ' a self , bs : & ' a BootServices ) -> ModeIter {
97107 ModeIter {
98108 gop : self ,
109+ bs,
99110 current : 0 ,
100111 max : self . mode ( ) . max_mode ,
101112 }
@@ -400,6 +411,7 @@ impl ModeInfo {
400411/// Iterator for [`Mode`]s of the [`GraphicsOutput`] protocol.
401412pub struct ModeIter < ' gop > {
402413 gop : & ' gop GraphicsOutput ,
414+ bs : & ' gop BootServices ,
403415 current : u32 ,
404416 max : u32 ,
405417}
@@ -410,7 +422,7 @@ impl<'gop> Iterator for ModeIter<'gop> {
410422 fn next ( & mut self ) -> Option < Self :: Item > {
411423 let index = self . current ;
412424 if index < self . max {
413- let m = self . gop . query_mode ( index) ;
425+ let m = self . gop . query_mode ( index, self . bs ) ;
414426 self . current += 1 ;
415427
416428 m. ok ( ) . or_else ( || self . next ( ) )
0 commit comments