@@ -128,17 +128,35 @@ pub struct BootServices {
128128 check_event : unsafe extern "efiapi" fn ( event : Event ) -> Status ,
129129
130130 // 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 : & mut Option < Handle > ,
133+ guid : & Guid ,
134+ interface_type : InterfaceType ,
135+ interface : * mut c_void ,
136+ ) -> Status ,
137+ reinstall_protocol_interface : unsafe extern "efiapi" fn (
138+ handle : Handle ,
139+ protocol : & Guid ,
140+ old_interface : * mut c_void ,
141+ new_interface : * mut c_void ,
142+ ) -> Status ,
143+ uninstall_protocol_interface : unsafe extern "efiapi" fn (
144+ handle : Handle ,
145+ protocol : & Guid ,
146+ interface : * mut c_void ,
147+ ) -> Status ,
134148 handle_protocol :
135149 extern "efiapi" fn ( handle : Handle , proto : & Guid , out_proto : & mut * mut c_void ) -> Status ,
136150 _reserved : usize ,
137- register_protocol_notify : usize ,
151+ register_protocol_notify : extern "efiapi" fn (
152+ protocol : & Guid ,
153+ event : Event ,
154+ registration : * mut ProtocolSearchKey ,
155+ ) -> Status ,
138156 locate_handle : unsafe extern "efiapi" fn (
139157 search_ty : i32 ,
140- proto : * const Guid ,
141- key : * mut c_void ,
158+ proto : Option < & Guid > ,
159+ key : Option < ProtocolSearchKey > ,
142160 buf_sz : & mut usize ,
143161 buf : * mut MaybeUninit < Handle > ,
144162 ) -> Status ,
@@ -221,8 +239,8 @@ pub struct BootServices {
221239 ) -> Status ,
222240 locate_handle_buffer : unsafe extern "efiapi" fn (
223241 search_ty : i32 ,
224- proto : * const Guid ,
225- key : * const c_void ,
242+ proto : Option < & Guid > ,
243+ key : Option < ProtocolSearchKey > ,
226244 no_handles : & mut usize ,
227245 buf : & mut * mut Handle ,
228246 ) -> Status ,
@@ -618,6 +636,72 @@ impl BootServices {
618636 }
619637 }
620638
639+ /// Installs a protocol interface on a device handle. If the inner `Option` in `handle` is `None`,
640+ /// one will be created and added to the list of handles in the system and then returned.
641+ ///
642+ /// When a protocol interface is installed, firmware will call all functions that have registered
643+ /// to wait for that interface to be installed.
644+ ///
645+ /// # Safety
646+ ///
647+ /// The caller is responsible for ensuring that they pass a valid `Guid` for `protocol`.
648+ pub unsafe fn install_protocol_interface (
649+ & self ,
650+ mut handle : Option < Handle > ,
651+ protocol : & Guid ,
652+ interface : * mut c_void ,
653+ ) -> Result < Handle > {
654+ ( ( self . install_protocol_interface ) (
655+ & mut handle,
656+ protocol,
657+ InterfaceType :: NATIVE_INTERFACE ,
658+ interface,
659+ ) )
660+ // this `unwrapped_unchecked` is safe, `handle` is guaranteed to be Some() if this call is
661+ // successful
662+ . into_with_val ( || handle. unwrap_unchecked ( ) )
663+ }
664+
665+ /// Reinstalls a protocol interface on a device handle. `old_interface` is replaced with `new_interface`.
666+ /// These interfaces may be the same, in which case the registered protocol notifies occur for the handle
667+ /// without replacing the interface.
668+ ///
669+ /// As with `install_protocol_interface`, any process that has registered to wait for the installation of
670+ /// the interface is notified.
671+ ///
672+ /// # Safety
673+ ///
674+ /// The caller is responsible for ensuring that there are no references to the `old_interface` that is being
675+ /// removed.
676+ pub unsafe fn reinstall_protocol_interface (
677+ & self ,
678+ handle : Handle ,
679+ protocol : & Guid ,
680+ old_interface : * mut c_void ,
681+ new_interface : * mut c_void ,
682+ ) -> Result < ( ) > {
683+ ( self . reinstall_protocol_interface ) ( handle, protocol, old_interface, new_interface) . into ( )
684+ }
685+
686+ /// Removes a protocol interface from a device handle.
687+ ///
688+ /// # Safety
689+ ///
690+ /// The caller is responsible for ensuring that there are no references to a protocol interface
691+ /// that has been removed. Some protocols may not be able to be removed as there is no information
692+ /// available regarding the references. This includes Console I/O, Block I/O, Disk I/o, and handles
693+ /// to device protocols.
694+ ///
695+ /// The caller is responsible for ensuring that they pass a valid `Guid` for `protocol`.
696+ pub unsafe fn uninstall_protocol_interface (
697+ & self ,
698+ handle : Handle ,
699+ protocol : & Guid ,
700+ interface : * mut c_void ,
701+ ) -> Result < ( ) > {
702+ ( self . uninstall_protocol_interface ) ( handle, protocol, interface) . into ( )
703+ }
704+
621705 /// Query a handle for a certain protocol.
622706 ///
623707 /// This function attempts to get the protocol implementation of a handle,
@@ -655,6 +739,31 @@ impl BootServices {
655739 } )
656740 }
657741
742+ /// Registers `event` to be signalled whenever a protocol interface is registered for
743+ /// `protocol` by `install_protocol_interface()` or `reinstall_protocol_interface()`.
744+ ///
745+ /// Once `event` has been signalled, `BootServices::locate_handle()` can be used to identify
746+ /// the newly (re)installed handles that support `protocol`. The returned `SearchKey` on success
747+ /// corresponds to the `search_key` parameter in `locate_handle()`.
748+ ///
749+ /// Events can be unregistered from protocol interface notification by calling `close_event()`.
750+ pub fn register_protocol_notify (
751+ & self ,
752+ protocol : & Guid ,
753+ event : Event ,
754+ ) -> Result < ( Event , SearchType ) > {
755+ let mut key: MaybeUninit < ProtocolSearchKey > = MaybeUninit :: uninit ( ) ;
756+ // Safety: we clone `event` a couple times, but there will be only one left once we return.
757+ unsafe { ( self . register_protocol_notify ) ( protocol, event. unsafe_clone ( ) , key. as_mut_ptr ( ) ) }
758+ // Safety: as long as this call is successful, `key` will be valid.
759+ . into_with_val ( || unsafe {
760+ (
761+ event. unsafe_clone ( ) ,
762+ SearchType :: ByRegisterNotify ( key. assume_init ( ) ) ,
763+ )
764+ } )
765+ }
766+
658767 /// Enumerates all handles installed on the system which match a certain query.
659768 ///
660769 /// You should first call this function with `None` for the output buffer,
@@ -677,8 +786,9 @@ impl BootServices {
677786
678787 // Obtain the needed data from the parameters.
679788 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 ( ) ) ,
789+ SearchType :: AllHandles => ( 0 , None , None ) ,
790+ SearchType :: ByRegisterNotify ( registration) => ( 1 , None , Some ( registration) ) ,
791+ SearchType :: ByProtocol ( guid) => ( 2 , Some ( guid) , None ) ,
682792 } ;
683793
684794 let status = unsafe { ( self . locate_handle ) ( ty, guid, key, & mut buffer_size, buffer) } ;
@@ -1095,8 +1205,9 @@ impl BootServices {
10951205
10961206 // Obtain the needed data from the parameters.
10971207 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 ( ) ) ,
1208+ SearchType :: AllHandles => ( 0 , None , None ) ,
1209+ SearchType :: ByRegisterNotify ( registration) => ( 1 , None , Some ( registration) ) ,
1210+ SearchType :: ByProtocol ( guid) => ( 2 , Some ( guid) , None ) ,
11001211 } ;
11011212
11021213 unsafe { ( self . locate_handle_buffer ) ( ty, guid, key, & mut num_handles, & mut buffer) }
@@ -1731,7 +1842,9 @@ pub enum SearchType<'guid> {
17311842 /// If the protocol implements the `Protocol` interface,
17321843 /// you can use the `from_proto` function to construct a new `SearchType`.
17331844 ByProtocol ( & ' guid Guid ) ,
1734- // TODO: add ByRegisterNotify once the corresponding function is implemented.
1845+ /// Return all handles that implement a protocol when an interface for that protocol
1846+ /// is (re)installed.
1847+ ByRegisterNotify ( ProtocolSearchKey ) ,
17351848}
17361849
17371850impl < ' guid > SearchType < ' guid > {
@@ -1844,3 +1957,19 @@ impl<'a> HandleBuffer<'a> {
18441957 unsafe { slice:: from_raw_parts ( self . buffer , self . count ) }
18451958 }
18461959}
1960+
1961+ newtype_enum ! {
1962+ /// Interface type of a protocol interface
1963+ ///
1964+ /// Only has one variant when this was written (v2.10 of the UEFI spec)
1965+ pub enum InterfaceType : i32 => {
1966+ /// Native interface
1967+ NATIVE_INTERFACE = 0 ,
1968+ }
1969+ }
1970+
1971+ /// Opaque pointer returned by [`BootServices::register_protocol_notify`] to be used
1972+ /// with [`BootServices::locate_handle`] via [`SearchType::ByRegisterNotify`].
1973+ #[ derive( Debug , Clone , Copy ) ]
1974+ #[ repr( transparent) ]
1975+ pub struct ProtocolSearchKey ( NonNull < c_void > ) ;
0 commit comments