diff --git a/uefi/src/proto/scsi/pass_thru.rs b/uefi/src/proto/scsi/pass_thru.rs index 26d50c687..219377463 100644 --- a/uefi/src/proto/scsi/pass_thru.rs +++ b/uefi/src/proto/scsi/pass_thru.rs @@ -8,6 +8,7 @@ use crate::mem::{AlignedBuffer, PoolAllocation}; use crate::proto::device_path::PoolDevicePathNode; use crate::proto::unsafe_protocol; use core::alloc::LayoutError; +use core::cell::UnsafeCell; use core::ptr::{self, NonNull}; use uefi_raw::Status; use uefi_raw::protocol::device_path::DevicePathProtocol; @@ -42,7 +43,7 @@ impl Default for ScsiTargetLun { #[derive(Debug)] #[repr(transparent)] #[unsafe_protocol(ExtScsiPassThruProtocol::GUID)] -pub struct ExtScsiPassThru(ExtScsiPassThruProtocol); +pub struct ExtScsiPassThru(UnsafeCell); impl ExtScsiPassThru { /// Retrieves the mode structure for the Extended SCSI Pass Thru protocol. @@ -51,7 +52,7 @@ impl ExtScsiPassThru { /// The [`ExtScsiPassThruMode`] structure containing configuration details of the protocol. #[must_use] pub fn mode(&self) -> ExtScsiPassThruMode { - let mut mode = unsafe { (*self.0.passthru_mode).clone() }; + let mut mode = unsafe { (*(*self.0.get()).passthru_mode).clone() }; mode.io_align = mode.io_align.max(1); // 0 and 1 is the same, says UEFI spec mode } @@ -113,7 +114,7 @@ impl ExtScsiPassThru { /// - [`Status::DEVICE_ERROR`] A device error occurred while attempting to reset the SCSI channel. /// - [`Status::TIMEOUT`] A timeout occurred while attempting to reset the SCSI channel. pub fn reset_channel(&mut self) -> crate::Result<()> { - unsafe { (self.0.reset_channel)(&mut self.0).to_result() } + unsafe { ((*self.0.get()).reset_channel)(self.0.get()).to_result() } } } @@ -126,14 +127,10 @@ impl ExtScsiPassThru { /// You have to probe for availability before doing anything meaningful with it. #[derive(Clone, Debug)] pub struct ScsiDevice<'a> { - proto: &'a ExtScsiPassThruProtocol, + proto: &'a UnsafeCell, target_lun: ScsiTargetLun, } impl ScsiDevice<'_> { - const fn proto_mut(&mut self) -> *mut ExtScsiPassThruProtocol { - ptr::from_ref(self.proto).cast_mut() - } - /// Returns the SCSI target address of the potential device. #[must_use] pub const fn target(&self) -> &ScsiTarget { @@ -153,8 +150,8 @@ impl ScsiDevice<'_> { pub fn path_node(&self) -> crate::Result { unsafe { let mut path_ptr: *const DevicePathProtocol = ptr::null(); - (self.proto.build_device_path)( - self.proto, + ((*self.proto.get()).build_device_path)( + self.proto.get(), self.target().as_ptr(), self.lun(), &mut path_ptr, @@ -185,8 +182,12 @@ impl ScsiDevice<'_> { /// by `Target` and `Lun`. pub fn reset(&mut self) -> crate::Result<()> { unsafe { - (self.proto.reset_target_lun)(self.proto_mut(), self.target_lun.0.as_ptr(), self.lun()) - .to_result() + ((*self.proto.get()).reset_target_lun)( + self.proto.get(), + self.target_lun.0.as_ptr(), + self.lun(), + ) + .to_result() } } @@ -223,8 +224,8 @@ impl ScsiDevice<'_> { mut scsi_req: ScsiRequest<'req>, ) -> crate::Result> { unsafe { - (self.proto.pass_thru)( - self.proto_mut(), + ((*self.proto.get()).pass_thru)( + self.proto.get(), self.target_lun.0.as_ptr(), self.target_lun.1, &mut scsi_req.packet, @@ -238,7 +239,7 @@ impl ScsiDevice<'_> { /// An iterator over SCSI devices available on the channel. #[derive(Debug)] pub struct ScsiTargetLunIterator<'a> { - proto: &'a ExtScsiPassThruProtocol, + proto: &'a UnsafeCell, prev: ScsiTargetLun, } impl<'a> Iterator for ScsiTargetLunIterator<'a> { @@ -248,8 +249,13 @@ impl<'a> Iterator for ScsiTargetLunIterator<'a> { // get_next_target_lun() takes the target as a double ptr, meaning that the spec allows // the implementation to return us a new buffer (most impls don't actually seem to do though) let mut target: *mut u8 = self.prev.0.as_mut_ptr(); - let result = - unsafe { (self.proto.get_next_target_lun)(self.proto, &mut target, &mut self.prev.1) }; + let result = unsafe { + ((*self.proto.get()).get_next_target_lun)( + self.proto.get(), + &mut target, + &mut self.prev.1, + ) + }; if target != self.prev.0.as_mut_ptr() { // impl has returned us a new pointer instead of writing in our buffer, copy back unsafe {