1
1
//! UEFI services available during boot.
2
2
3
3
use super :: { Header , Revision } ;
4
- use crate :: data_types:: { Align , PhysicalAddress , VirtualAddress } ;
4
+ use crate :: data_types:: { Align , PhysicalAddress , SearchKey , VirtualAddress } ;
5
5
use crate :: proto:: device_path:: { DevicePath , FfiDevicePath } ;
6
6
#[ cfg( feature = "exts" ) ]
7
7
use crate :: proto:: { loaded_image:: LoadedImage , media:: fs:: SimpleFileSystem } ;
@@ -128,17 +128,32 @@ pub struct BootServices {
128
128
check_event : unsafe extern "efiapi" fn ( event : Event ) -> Status ,
129
129
130
130
// Protocol handlers
131
- install_protocol_interface : usize ,
132
- reinstall_protocol_interface : usize ,
133
- uninstall_protocol_interface : usize ,
131
+ install_protocol_interface : unsafe extern "efiapi" fn (
132
+ handle : Option < & Handle > ,
133
+ guid : & Guid ,
134
+ interface_type : InterfaceType ,
135
+ interface : Option < NonNull < c_void > > ,
136
+ ) -> Status ,
137
+ reinstall_protocol_interface : unsafe extern "efiapi" fn (
138
+ handle : Handle ,
139
+ protocol : & Guid ,
140
+ old_interface : Option < NonNull < c_void > > ,
141
+ new_interface : Option < NonNull < c_void > > ,
142
+ ) -> Status ,
143
+ uninstall_protocol_interface : unsafe extern "efiapi" fn (
144
+ handle : Handle ,
145
+ protocol : & Guid ,
146
+ interface : Option < NonNull < c_void > > ,
147
+ ) -> Status ,
134
148
handle_protocol :
135
149
extern "efiapi" fn ( handle : Handle , proto : & Guid , out_proto : & mut * mut c_void ) -> Status ,
136
150
_reserved : usize ,
137
- register_protocol_notify : usize ,
151
+ register_protocol_notify :
152
+ extern "efiapi" fn ( protocol : & Guid , event : Event , registration : * mut SearchKey ) -> Status ,
138
153
locate_handle : unsafe extern "efiapi" fn (
139
154
search_ty : i32 ,
140
- proto : * const Guid ,
141
- key : * mut c_void ,
155
+ proto : Option < & Guid > ,
156
+ key : Option < SearchKey > ,
142
157
buf_sz : & mut usize ,
143
158
buf : * mut MaybeUninit < Handle > ,
144
159
) -> Status ,
@@ -221,8 +236,8 @@ pub struct BootServices {
221
236
) -> Status ,
222
237
locate_handle_buffer : unsafe extern "efiapi" fn (
223
238
search_ty : i32 ,
224
- proto : * const Guid ,
225
- key : * const c_void ,
239
+ proto : Option < & Guid > ,
240
+ key : Option < SearchKey > ,
226
241
no_handles : & mut usize ,
227
242
buf : & mut * mut Handle ,
228
243
) -> Status ,
@@ -618,6 +633,72 @@ impl BootServices {
618
633
}
619
634
}
620
635
636
+ /// Installs a protocol interface on a device handle. If `handle` is `None`, one will be
637
+ /// created and added to the list of handles in the system and then returned.
638
+ ///
639
+ /// When a protocol interface is installed, firmware will call all functions that have registered
640
+ /// to wait for that interface to be installed.
641
+ ///
642
+ /// # Safety
643
+ ///
644
+ /// The caller is responsible for ensuring that they pass a valid `Guid` for `protocol`.
645
+ pub unsafe fn install_protocol_interface (
646
+ & self ,
647
+ handle : Option < & Handle > ,
648
+ protocol : & Guid ,
649
+ interface : Option < NonNull < c_void > > ,
650
+ ) -> Result < Handle > {
651
+ ( ( self . install_protocol_interface ) (
652
+ handle,
653
+ protocol,
654
+ InterfaceType :: NATIVE_INTERFACE ,
655
+ interface,
656
+ ) )
657
+ // this `unwrapped_unchecked` is safe, `handle` is guaranteed to be Some() if this call is
658
+ // successful
659
+ . into_with_val ( || * handle. unwrap_unchecked ( ) )
660
+ }
661
+
662
+ /// Reinstalls a protocol interface on a device handle. `old_interface` is replaced with `new_interface`.
663
+ /// These interfaces may be the same, in which case the registered protocol notifies occur for the handle
664
+ /// without replacing the interface.
665
+ ///
666
+ /// As with `install_protocol_interface`, any process that has registered to wait for the installation of
667
+ /// the interface is notified.
668
+ ///
669
+ /// # Safety
670
+ ///
671
+ /// The caller is responsible for ensuring that there are no references to the `old_interface` that is being
672
+ /// removed.
673
+ pub unsafe fn reinstall_protocol_interface (
674
+ & self ,
675
+ handle : Handle ,
676
+ protocol : & Guid ,
677
+ old_interface : Option < NonNull < c_void > > ,
678
+ new_interface : Option < NonNull < c_void > > ,
679
+ ) -> Result < ( ) > {
680
+ ( self . reinstall_protocol_interface ) ( handle, protocol, old_interface, new_interface) . into ( )
681
+ }
682
+
683
+ /// Removes a protocol interface from a device handle.
684
+ ///
685
+ /// # Safety
686
+ ///
687
+ /// The caller is responsible for ensuring that there are no references to a protocol interface
688
+ /// that has been removed. Some protocols may not be able to be removed as there is no information
689
+ /// available regarding the references. This includes Console I/O, Block I/O, Disk I/o, and handles
690
+ /// to device protocols.
691
+ ///
692
+ /// The caller is responsible for ensuring that they pass a valid `Guid` for `protocol`.
693
+ pub unsafe fn uninstall_protocol_interface (
694
+ & self ,
695
+ handle : Handle ,
696
+ protocol : & Guid ,
697
+ interface : Option < NonNull < c_void > > ,
698
+ ) -> Result < ( ) > {
699
+ ( self . uninstall_protocol_interface ) ( handle, protocol, interface) . into ( )
700
+ }
701
+
621
702
/// Query a handle for a certain protocol.
622
703
///
623
704
/// This function attempts to get the protocol implementation of a handle,
@@ -655,6 +736,26 @@ impl BootServices {
655
736
} )
656
737
}
657
738
739
+ /// Registers `event` to be signalled whenever a protocol interface is registered for
740
+ /// `protocol` by `install_protocol_interface()` or `reinstall_protocol_interface()`.
741
+ ///
742
+ /// Once `event` has been signalled, `BootServices::locate_handle()` can be used to identify
743
+ /// the newly (re)installed handles that support `protocol`. The returned `SearchKey` on success
744
+ /// corresponds to the `search_key` parameter in `locate_handle()`.
745
+ ///
746
+ /// Events can be unregistered from protocol interface notification by calling `close_event()`.
747
+ pub fn register_protocol_notify (
748
+ & self ,
749
+ protocol : & Guid ,
750
+ event : Event ,
751
+ ) -> Result < ( Event , SearchKey ) > {
752
+ let mut key: MaybeUninit < SearchKey > = MaybeUninit :: uninit ( ) ;
753
+ // Safety: we clone `event` a couple times, but there will be only one left once we return.
754
+ unsafe { ( self . register_protocol_notify ) ( protocol, event. unsafe_clone ( ) , key. as_mut_ptr ( ) ) }
755
+ // Safety: as long as this call is successful, `key` will be valid.
756
+ . into_with_val ( || unsafe { ( event. unsafe_clone ( ) , key. assume_init ( ) ) } )
757
+ }
758
+
658
759
/// Enumerates all handles installed on the system which match a certain query.
659
760
///
660
761
/// You should first call this function with `None` for the output buffer,
@@ -677,8 +778,9 @@ impl BootServices {
677
778
678
779
// Obtain the needed data from the parameters.
679
780
let ( ty, guid, key) = match search_ty {
680
- SearchType :: AllHandles => ( 0 , ptr:: null ( ) , ptr:: null_mut ( ) ) ,
681
- SearchType :: ByProtocol ( guid) => ( 2 , guid as * const _ , ptr:: null_mut ( ) ) ,
781
+ SearchType :: AllHandles => ( 0 , None , None ) ,
782
+ SearchType :: ByRegisterNotify ( registration) => ( 1 , None , Some ( registration) ) ,
783
+ SearchType :: ByProtocol ( guid) => ( 2 , Some ( guid) , None ) ,
682
784
} ;
683
785
684
786
let status = unsafe { ( self . locate_handle ) ( ty, guid, key, & mut buffer_size, buffer) } ;
@@ -1095,8 +1197,9 @@ impl BootServices {
1095
1197
1096
1198
// Obtain the needed data from the parameters.
1097
1199
let ( ty, guid, key) = match search_ty {
1098
- SearchType :: AllHandles => ( 0 , ptr:: null ( ) , ptr:: null_mut ( ) ) ,
1099
- SearchType :: ByProtocol ( guid) => ( 2 , guid as * const _ , ptr:: null_mut ( ) ) ,
1200
+ SearchType :: AllHandles => ( 0 , None , None ) ,
1201
+ SearchType :: ByRegisterNotify ( registration) => ( 1 , None , Some ( registration) ) ,
1202
+ SearchType :: ByProtocol ( guid) => ( 2 , Some ( guid) , None ) ,
1100
1203
} ;
1101
1204
1102
1205
unsafe { ( self . locate_handle_buffer ) ( ty, guid, key, & mut num_handles, & mut buffer) }
@@ -1731,7 +1834,9 @@ pub enum SearchType<'guid> {
1731
1834
/// If the protocol implements the `Protocol` interface,
1732
1835
/// you can use the `from_proto` function to construct a new `SearchType`.
1733
1836
ByProtocol ( & ' guid Guid ) ,
1734
- // TODO: add ByRegisterNotify once the corresponding function is implemented.
1837
+ /// Return all handles that implement a protocol when an interface for that protocol
1838
+ /// is (re)installed.
1839
+ ByRegisterNotify ( SearchKey ) ,
1735
1840
}
1736
1841
1737
1842
impl < ' guid > SearchType < ' guid > {
@@ -1741,6 +1846,13 @@ impl<'guid> SearchType<'guid> {
1741
1846
}
1742
1847
}
1743
1848
1849
+ impl SearchType < ' _ > {
1850
+ /// Constructs a new search type from a SearchKey.
1851
+ pub fn from_search_key ( key : SearchKey ) -> Self {
1852
+ SearchType :: ByRegisterNotify ( key)
1853
+ }
1854
+ }
1855
+
1744
1856
bitflags ! {
1745
1857
/// Flags describing the type of an UEFI event and its attributes.
1746
1858
pub struct EventType : u32 {
@@ -1844,3 +1956,13 @@ impl<'a> HandleBuffer<'a> {
1844
1956
unsafe { slice:: from_raw_parts ( self . buffer , self . count ) }
1845
1957
}
1846
1958
}
1959
+
1960
+ newtype_enum ! {
1961
+ /// Interface type of a protocol interface
1962
+ ///
1963
+ /// Only has one variant when this was written (v2.10 of the UEFI spec)
1964
+ pub enum InterfaceType : i32 => {
1965
+ /// Native interface
1966
+ NATIVE_INTERFACE = 0 ,
1967
+ }
1968
+ }
0 commit comments