@@ -128,17 +128,35 @@ 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 : & 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 ,
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 : extern "efiapi" fn (
152
+ protocol : & Guid ,
153
+ event : Event ,
154
+ registration : * mut ProtocolSearchKey ,
155
+ ) -> Status ,
138
156
locate_handle : unsafe extern "efiapi" fn (
139
157
search_ty : i32 ,
140
- proto : * const Guid ,
141
- key : * mut c_void ,
158
+ proto : Option < & Guid > ,
159
+ key : Option < ProtocolSearchKey > ,
142
160
buf_sz : & mut usize ,
143
161
buf : * mut MaybeUninit < Handle > ,
144
162
) -> Status ,
@@ -221,8 +239,8 @@ pub struct BootServices {
221
239
) -> Status ,
222
240
locate_handle_buffer : unsafe extern "efiapi" fn (
223
241
search_ty : i32 ,
224
- proto : * const Guid ,
225
- key : * const c_void ,
242
+ proto : Option < & Guid > ,
243
+ key : Option < ProtocolSearchKey > ,
226
244
no_handles : & mut usize ,
227
245
buf : & mut * mut Handle ,
228
246
) -> Status ,
@@ -618,6 +636,72 @@ impl BootServices {
618
636
}
619
637
}
620
638
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
+
621
705
/// Query a handle for a certain protocol.
622
706
///
623
707
/// This function attempts to get the protocol implementation of a handle,
@@ -655,6 +739,31 @@ impl BootServices {
655
739
} )
656
740
}
657
741
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
+
658
767
/// Enumerates all handles installed on the system which match a certain query.
659
768
///
660
769
/// You should first call this function with `None` for the output buffer,
@@ -677,8 +786,9 @@ impl BootServices {
677
786
678
787
// Obtain the needed data from the parameters.
679
788
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 ) ,
682
792
} ;
683
793
684
794
let status = unsafe { ( self . locate_handle ) ( ty, guid, key, & mut buffer_size, buffer) } ;
@@ -1095,8 +1205,9 @@ impl BootServices {
1095
1205
1096
1206
// Obtain the needed data from the parameters.
1097
1207
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 ) ,
1100
1211
} ;
1101
1212
1102
1213
unsafe { ( self . locate_handle_buffer ) ( ty, guid, key, & mut num_handles, & mut buffer) }
@@ -1731,7 +1842,9 @@ pub enum SearchType<'guid> {
1731
1842
/// If the protocol implements the `Protocol` interface,
1732
1843
/// you can use the `from_proto` function to construct a new `SearchType`.
1733
1844
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 ) ,
1735
1848
}
1736
1849
1737
1850
impl < ' guid > SearchType < ' guid > {
@@ -1844,3 +1957,19 @@ impl<'a> HandleBuffer<'a> {
1844
1957
unsafe { slice:: from_raw_parts ( self . buffer , self . count ) }
1845
1958
}
1846
1959
}
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