Skip to content

Commit b4bffd8

Browse files
author
Maciej Falkowski
committed
rust: iomem: add try_memcpy_fromio method for IoMem<T>
This patch adds only runtime-checked bindings version of `memcpy_fromio()` function prefixed with `try_` similarly to read/write methods of `IoMem<T>` that is `readx` and `try_readx`. Signed-off-by: Maciej Falkowski <[email protected]>
1 parent 35cf3a5 commit b4bffd8

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

rust/helpers.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ void rust_helper_writeq_relaxed(u64 value, volatile void __iomem *addr)
182182
}
183183
EXPORT_SYMBOL_GPL(rust_helper_writeq_relaxed);
184184
#endif
185+
186+
void rust_helper_memcpy_fromio(void *to, const volatile void __iomem *from, long count)
187+
{
188+
memcpy_fromio(to, from, count);
189+
}
190+
EXPORT_SYMBOL_GPL(rust_helper_memcpy_fromio);
191+
185192
void rust_helper___spin_lock_init(spinlock_t *lock, const char *name,
186193
struct lock_class_key *key)
187194
{

rust/kernel/io_mem.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,46 @@ impl<const SIZE: usize> IoMem<SIZE> {
187187
crate::build_assert!(Self::offset_ok::<T>(offset), "IoMem offset overflow");
188188
}
189189

190+
/// Copy memory block from an i/o memory by filling the specified buffer with it.
191+
///
192+
/// # Examples
193+
/// ```
194+
/// # use kernel::prelude::*;
195+
/// use kernel::io_mem::{self, IoMem, Resource};
196+
///
197+
/// fn test(res: Resource) -> Result {
198+
/// // Create an i/o memory block of at least 100 bytes.
199+
/// let mem = unsafe { IoMem::<100>::try_new(res) }?;
200+
///
201+
/// let mut buffer: [u8; 32] = [0; 32];
202+
///
203+
/// // Memcpy 16 bytes from an offset 10 of i/o memory block into the buffer.
204+
/// mem.try_memcpy_fromio(&mut buffer[..16], 10)?;
205+
///
206+
/// Ok(())
207+
/// }
208+
/// ```
209+
pub fn try_memcpy_fromio(&self, buffer: &mut [u8], offset: usize) -> Result {
210+
if !Self::offset_ok_of_val::<[u8]>(offset, buffer) {
211+
return Err(EINVAL);
212+
}
213+
214+
let ptr = self.ptr.wrapping_add(offset);
215+
216+
// SAFETY:
217+
// - The type invariants guarantee that `ptr` is a valid pointer.
218+
// - The bounds of `buffer` are checked with a call to `offset_ok_of_val()`.
219+
// go out of bounds they match `count` above.
220+
unsafe {
221+
bindings::memcpy_fromio(
222+
buffer.as_mut_ptr() as *mut _,
223+
ptr as *const _,
224+
buffer.len() as _,
225+
)
226+
};
227+
Ok(())
228+
}
229+
190230
define_read!(readb, try_readb, u8);
191231
define_read!(readw, try_readw, u16);
192232
define_read!(readl, try_readl, u32);

0 commit comments

Comments
 (0)