@@ -43,21 +43,22 @@ static IMAGE_HANDLE: GlobalImageHandle = GlobalImageHandle {
43
43
/// # Accessing protocols
44
44
///
45
45
/// Protocols can be opened using several methods of `BootServices`. Most
46
- /// commonly, [`open_protocol`] should be used. This returns a
46
+ /// commonly, [`open_protocol_exclusive`] should be used. This ensures that
47
+ /// nothing else can use the protocol until it is closed, and returns a
47
48
/// [`ScopedProtocol`] that takes care of closing the protocol when it is
48
- /// dropped. If the protocol is opened in [`Exclusive`] mode, UEFI ensures that
49
- /// nothing else can use the protocol until it is closed.
49
+ /// dropped.
50
50
///
51
51
/// Other methods for opening protocols:
52
52
///
53
+ /// * [`open_protocol`]
53
54
/// * [`get_image_file_system`]
54
55
/// * [`handle_protocol`]
55
56
/// * [`locate_protocol`]
56
57
///
57
58
/// For protocol definitions, see the [`proto`] module.
58
59
///
59
60
/// [`proto`]: crate::proto
60
- /// [`Exclusive `]: OpenProtocolAttributes::Exclusive
61
+ /// [`open_protocol_exclusive `]: BootServices::open_protocol_exclusive
61
62
/// [`open_protocol`]: BootServices::open_protocol
62
63
/// [`get_image_file_system`]: BootServices::get_image_file_system
63
64
/// [`locate_protocol`]: BootServices::locate_protocol
@@ -623,7 +624,7 @@ impl BootServices {
623
624
/// based on the protocol GUID.
624
625
///
625
626
/// It is recommended that all new drivers and applications use
626
- /// [`open_protocol`] instead of `handle_protocol`.
627
+ /// [`open_protocol_exclusive`] or [` open_protocol`] instead of `handle_protocol`.
627
628
///
628
629
/// UEFI protocols are neither thread-safe nor reentrant, but the firmware
629
630
/// provides no mechanism to protect against concurrent usage. Such
@@ -635,10 +636,14 @@ impl BootServices {
635
636
/// This method is unsafe because the handle database is not
636
637
/// notified that the handle and protocol are in use; there is no
637
638
/// guarantee that they will remain valid for the duration of their
638
- /// use. Use [`open_protocol`] instead.
639
+ /// use. Use [`open_protocol_exclusive`] if possible, otherwise use
640
+ /// [`open_protocol`].
639
641
///
640
642
/// [`open_protocol`]: BootServices::open_protocol
641
- #[ deprecated( note = "it is recommended to use `open_protocol` instead" ) ]
643
+ /// [`open_protocol_exclusive`]: BootServices::open_protocol_exclusive
644
+ #[ deprecated(
645
+ note = "it is recommended to use `open_protocol_exclusive` or `open_protocol` instead"
646
+ ) ]
642
647
pub unsafe fn handle_protocol < P : ProtocolPointer + ?Sized > (
643
648
& self ,
644
649
handle : Handle ,
@@ -737,14 +742,7 @@ impl BootServices {
737
742
/// # let boot_services: &BootServices = get_fake_val();
738
743
/// # let image_handle: Handle = get_fake_val();
739
744
/// let handle = boot_services.get_handle_for_protocol::<DevicePathToText>()?;
740
- /// let device_path_to_text = boot_services.open_protocol::<DevicePathToText>(
741
- /// OpenProtocolParams {
742
- /// handle,
743
- /// agent: image_handle,
744
- /// controller: None,
745
- /// },
746
- /// OpenProtocolAttributes::Exclusive,
747
- /// )?;
745
+ /// let device_path_to_text = boot_services.open_protocol_exclusive::<DevicePathToText>(handle)?;
748
746
/// # Ok(())
749
747
/// # }
750
748
/// ```
@@ -963,11 +961,14 @@ impl BootServices {
963
961
964
962
/// Open a protocol interface for a handle.
965
963
///
964
+ /// See also [`open_protocol_exclusive`], which provides a safe
965
+ /// subset of this functionality.
966
+ ///
966
967
/// This function attempts to get the protocol implementation of a
967
968
/// handle, based on the protocol GUID. It is an extended version of
968
969
/// [`handle_protocol`]. It is recommended that all
969
- /// new drivers and applications use `open_protocol` instead of
970
- /// `handle_protocol`.
970
+ /// new drivers and applications use `open_protocol_exclusive` or
971
+ /// `open_protocol` instead of ` handle_protocol`.
971
972
///
972
973
/// See [`OpenProtocolParams`] and [`OpenProtocolAttributes`] for
973
974
/// details of the input parameters.
@@ -980,8 +981,19 @@ impl BootServices {
980
981
/// protections must be implemented by user-level code, for example via a
981
982
/// global `HashSet`.
982
983
///
984
+ /// # Safety
985
+ ///
986
+ /// This function is unsafe because it can be used to open a
987
+ /// protocol in ways that don't get tracked by the UEFI
988
+ /// implementation. This could allow the protocol to be removed from
989
+ /// a handle, or for the handle to be deleted entirely, while a
990
+ /// reference to the protocol is still active. The caller is
991
+ /// responsible for ensuring that the handle and protocol remain
992
+ /// valid until the `ScopedProtocol` is dropped.
993
+ ///
983
994
/// [`handle_protocol`]: BootServices::handle_protocol
984
- pub fn open_protocol < P : ProtocolPointer + ?Sized > (
995
+ /// [`open_protocol_exclusive`]: BootServices::open_protocol_exclusive
996
+ pub unsafe fn open_protocol < P : ProtocolPointer + ?Sized > (
985
997
& self ,
986
998
params : OpenProtocolParams ,
987
999
attributes : OpenProtocolAttributes ,
@@ -995,7 +1007,7 @@ impl BootServices {
995
1007
params. controller ,
996
1008
attributes as u32 ,
997
1009
)
998
- . into_with_val ( || unsafe {
1010
+ . into_with_val ( || {
999
1011
let interface = P :: mut_ptr_from_ffi ( interface) as * const UnsafeCell < P > ;
1000
1012
1001
1013
#[ allow( deprecated) ]
@@ -1017,14 +1029,19 @@ impl BootServices {
1017
1029
& self ,
1018
1030
handle : Handle ,
1019
1031
) -> Result < ScopedProtocol < P > > {
1020
- self . open_protocol :: < P > (
1021
- OpenProtocolParams {
1022
- handle,
1023
- agent : self . image_handle ( ) ,
1024
- controller : None ,
1025
- } ,
1026
- OpenProtocolAttributes :: Exclusive ,
1027
- )
1032
+ // Safety: opening in exclusive mode with the correct agent
1033
+ // handle set ensures that the protocol cannot be modified or
1034
+ // removed while it is open, so this usage is safe.
1035
+ unsafe {
1036
+ self . open_protocol :: < P > (
1037
+ OpenProtocolParams {
1038
+ handle,
1039
+ agent : self . image_handle ( ) ,
1040
+ controller : None ,
1041
+ } ,
1042
+ OpenProtocolAttributes :: Exclusive ,
1043
+ )
1044
+ }
1028
1045
}
1029
1046
1030
1047
/// Test whether a handle supports a protocol.
@@ -1099,9 +1116,15 @@ impl BootServices {
1099
1116
/// This method is unsafe because the handle database is not
1100
1117
/// notified that the handle and protocol are in use; there is no
1101
1118
/// guarantee that they will remain valid for the duration of their
1102
- /// use. Use [`BootServices::get_handle_for_protocol`] and
1103
- /// [`BootServices::open_protocol`] instead.
1104
- #[ deprecated( note = "it is recommended to use `open_protocol` instead" ) ]
1119
+ /// use. Use [`get_handle_for_protocol`] and either
1120
+ /// [`open_protocol_exclusive`] or [`open_protocol`] instead.
1121
+ ///
1122
+ /// [`get_handle_for_protocol`]: BootServices::get_handle_for_protocol
1123
+ /// [`open_protocol`]: BootServices::open_protocol
1124
+ /// [`open_protocol_exclusive`]: BootServices::open_protocol_exclusive
1125
+ #[ deprecated(
1126
+ note = "it is recommended to use `open_protocol_exclusive` or `open_protocol` instead"
1127
+ ) ]
1105
1128
pub unsafe fn locate_protocol < P : ProtocolPointer + ?Sized > ( & self ) -> Result < & UnsafeCell < P > > {
1106
1129
let mut ptr = ptr:: null_mut ( ) ;
1107
1130
( self . locate_protocol ) ( & P :: GUID , ptr:: null_mut ( ) , & mut ptr) . into_with_val ( || {
@@ -1166,34 +1189,13 @@ impl BootServices {
1166
1189
& self ,
1167
1190
image_handle : Handle ,
1168
1191
) -> Result < ScopedProtocol < SimpleFileSystem > > {
1169
- let loaded_image = self . open_protocol :: < LoadedImage > (
1170
- OpenProtocolParams {
1171
- handle : image_handle,
1172
- agent : image_handle,
1173
- controller : None ,
1174
- } ,
1175
- OpenProtocolAttributes :: Exclusive ,
1176
- ) ?;
1177
-
1178
- let device_path = self . open_protocol :: < DevicePath > (
1179
- OpenProtocolParams {
1180
- handle : loaded_image. device ( ) ,
1181
- agent : image_handle,
1182
- controller : None ,
1183
- } ,
1184
- OpenProtocolAttributes :: Exclusive ,
1185
- ) ?;
1192
+ let loaded_image = self . open_protocol_exclusive :: < LoadedImage > ( image_handle) ?;
1193
+
1194
+ let device_path = self . open_protocol_exclusive :: < DevicePath > ( loaded_image. device ( ) ) ?;
1186
1195
1187
1196
let device_handle = self . locate_device_path :: < SimpleFileSystem > ( & mut & * device_path) ?;
1188
1197
1189
- self . open_protocol :: < SimpleFileSystem > (
1190
- OpenProtocolParams {
1191
- handle : device_handle,
1192
- agent : image_handle,
1193
- controller : None ,
1194
- } ,
1195
- OpenProtocolAttributes :: Exclusive ,
1196
- )
1198
+ self . open_protocol_exclusive ( device_handle)
1197
1199
}
1198
1200
}
1199
1201
0 commit comments