1 // Copyright 2024, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Rust wrapper for `EFI_BLOCK_IO_PROTOCOL`. 16 17 use crate::efi_call; 18 use crate::protocol::{Protocol, ProtocolInfo}; 19 use efi_types::{EfiBlockIoMedia, EfiBlockIoProtocol, EfiGuid}; 20 use gbl_storage::SliceMaybeUninit; 21 use liberror::{Error, Result}; 22 23 /// EFI_BLOCK_IO_PROTOCOL 24 pub struct BlockIoProtocol; 25 26 impl ProtocolInfo for BlockIoProtocol { 27 type InterfaceType = EfiBlockIoProtocol; 28 29 const GUID: EfiGuid = 30 EfiGuid::new(0x964e5b21, 0x6459, 0x11d2, [0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b]); 31 } 32 33 // Protocol interface wrappers. 34 impl Protocol<'_, BlockIoProtocol> { 35 /// Wrapper of `EFI_BLOCK_IO_PROTOCOL.read_blocks()` read_blocks( &self, lba: u64, buffer: &mut (impl SliceMaybeUninit + ?Sized), ) -> Result<()>36 pub fn read_blocks( 37 &self, 38 lba: u64, 39 buffer: &mut (impl SliceMaybeUninit + ?Sized), 40 ) -> Result<()> { 41 // SAFETY: 42 // `self.interface()?` guarantees self.interface is non-null and points to a valid object 43 // established by `Protocol::new()`. 44 // `self.interface` is input parameter and will not be retained. It outlives the call. 45 // `buffer` remains valid during the call. 46 unsafe { 47 efi_call!( 48 self.interface()?.read_blocks, 49 self.interface, 50 self.media()?.media_id, 51 lba, 52 buffer.len(), 53 buffer.as_mut().as_mut_ptr() as *mut _ 54 ) 55 } 56 } 57 58 /// Wrapper of `EFI_BLOCK_IO_PROTOCOL.write_blocks()` write_blocks(&self, lba: u64, buffer: &mut [u8]) -> Result<()>59 pub fn write_blocks(&self, lba: u64, buffer: &mut [u8]) -> Result<()> { 60 // SAFETY: 61 // `self.interface()?` guarantees self.interface is non-null and points to a valid object 62 // established by `Protocol::new()`. 63 // `self.interface` is input parameter and will not be retained. It outlives the call. 64 // `buffer` remains valid during the call. 65 unsafe { 66 efi_call!( 67 self.interface()?.write_blocks, 68 self.interface, 69 self.media()?.media_id, 70 lba, 71 buffer.len(), 72 buffer.as_mut_ptr() as _ 73 ) 74 } 75 } 76 77 /// Wrapper of `EFI_BLOCK_IO_PROTOCOL.flush_blocks()` flush_blocks(&self) -> Result<()>78 pub fn flush_blocks(&self) -> Result<()> { 79 // SAFETY: 80 // `self.interface()?` guarantees `self.interface` is non-null and points to a valid object 81 // established by `Protocol::new()`. 82 // `self.interface` is input parameter and will not be retained. It outlives the call. 83 unsafe { efi_call!(self.interface()?.flush_blocks, self.interface) } 84 } 85 86 /// Wrapper of `EFI_BLOCK_IO_PROTOCOL.reset()` reset(&self, extended_verification: bool) -> Result<()>87 pub fn reset(&self, extended_verification: bool) -> Result<()> { 88 // SAFETY: 89 // `self.interface()?` guarantees `self.interface` is non-null and points to a valid object 90 // established by `Protocol::new()`. 91 // `self.interface` is input parameter and will not be retained. It outlives the call. 92 unsafe { efi_call!(self.interface()?.reset, self.interface, extended_verification) } 93 } 94 95 /// Get a copy to the EFI_BLOCK_IO_PROTOCOL.Media structure. media(&self) -> Result<EfiBlockIoMedia>96 pub fn media(&self) -> Result<EfiBlockIoMedia> { 97 let ptr = self.interface()?.media; 98 // SFETY: Pointers to EFI data structure. 99 Ok(*unsafe { ptr.as_ref() }.ok_or(Error::InvalidInput)?) 100 } 101 } 102