|
@@ -1,5 +1,9 @@
|
|
|
//! 这个文件用于放置一些内核态访问用户态数据的函数
|
|
|
-use core::mem::size_of;
|
|
|
+
|
|
|
+use core::{
|
|
|
+ mem::size_of,
|
|
|
+ slice::{from_raw_parts, from_raw_parts_mut},
|
|
|
+};
|
|
|
|
|
|
use alloc::{string::String, vec::Vec};
|
|
|
|
|
@@ -139,3 +143,199 @@ pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>,
|
|
|
return Ok(buffer);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+pub struct UserBufferWriter<'a> {
|
|
|
+ buffer: &'a mut [u8],
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+pub struct UserBufferReader<'a> {
|
|
|
+ buffer: &'a [u8],
|
|
|
+}
|
|
|
+
|
|
|
+#[allow(dead_code)]
|
|
|
+impl<'a> UserBufferReader<'a> {
|
|
|
+ /// 构造一个指向用户空间位置的BufferReader,为了兼容类似传入 *const u8 的情况,使用单独的泛型来进行初始化
|
|
|
+ ///
|
|
|
+ /// @param addr 用户空间指针
|
|
|
+ /// @param len 缓冲区的字节长度
|
|
|
+ /// @param frm_user 代表是否要检验地址来自用户空间
|
|
|
+ /// @return 构造成功返回UserbufferReader实例,否则返回错误码
|
|
|
+ ///
|
|
|
+ pub fn new<U>(addr: *const U, len: usize, from_user: bool) -> Result<Self, SystemError> {
|
|
|
+ if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
|
|
|
+ return Err(SystemError::EFAULT);
|
|
|
+ }
|
|
|
+ return Ok(Self {
|
|
|
+ buffer: unsafe { core::slice::from_raw_parts(addr as *const u8, len) },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 从用户空间读取数据(到变量中)
|
|
|
+ ///
|
|
|
+ /// @param offset 字节偏移量
|
|
|
+ /// @return 返回用户空间数据的切片(对单个结构体就返回长度为一的切片)
|
|
|
+ ///
|
|
|
+ pub fn read_from_user<T>(&self, offset: usize) -> Result<&[T], SystemError> {
|
|
|
+ return self.convert_with_offset(&self.buffer, offset);
|
|
|
+ }
|
|
|
+ /// 从用户空间读取一个指定偏移量的数据(到变量中)
|
|
|
+ ///
|
|
|
+ /// @param offset 字节偏移量
|
|
|
+ /// @return 返回用户空间数据的引用
|
|
|
+ ///
|
|
|
+ pub fn read_one_from_user<T>(&self, offset: usize) -> Result<&T, SystemError> {
|
|
|
+ return self.convert_one_with_offset(&self.buffer, offset);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 从用户空间拷贝数据(到指定地址中)
|
|
|
+ ///
|
|
|
+ /// @param dst 目标地址指针
|
|
|
+ /// @return 拷贝成功的话返回拷贝的元素数量
|
|
|
+ ///
|
|
|
+ pub fn copy_from_user<T: core::marker::Copy>(
|
|
|
+ &self,
|
|
|
+ dst: &mut [T],
|
|
|
+ offset: usize,
|
|
|
+ ) -> Result<usize, SystemError> {
|
|
|
+ let data = self.convert_with_offset(&self.buffer, offset)?;
|
|
|
+ dst.copy_from_slice(data);
|
|
|
+ return Ok(dst.len());
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 从用户空间拷贝数据(到指定地址中)
|
|
|
+ ///
|
|
|
+ /// @param dst 目标地址指针
|
|
|
+ /// @return 拷贝成功的话返回拷贝的元素数量
|
|
|
+ ///
|
|
|
+ pub fn copy_one_from_user<T: core::marker::Copy>(
|
|
|
+ &self,
|
|
|
+ dst: &mut T,
|
|
|
+ offset: usize,
|
|
|
+ ) -> Result<(), SystemError> {
|
|
|
+ let data = self.convert_one_with_offset::<T>(&self.buffer, offset)?;
|
|
|
+ dst.clone_from(data);
|
|
|
+ return Ok(());
|
|
|
+ }
|
|
|
+
|
|
|
+ fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
|
|
|
+ if offset >= src.len() {
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
+ }
|
|
|
+ let byte_buffer: &[u8] = &src[offset..];
|
|
|
+ if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ let chunks = unsafe {
|
|
|
+ from_raw_parts(
|
|
|
+ byte_buffer.as_ptr() as *const T,
|
|
|
+ byte_buffer.len() / core::mem::size_of::<T>(),
|
|
|
+ )
|
|
|
+ };
|
|
|
+ return Ok(chunks);
|
|
|
+ }
|
|
|
+
|
|
|
+ fn convert_one_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&T, SystemError> {
|
|
|
+ if offset + core::mem::size_of::<T>() > src.len() {
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
+ }
|
|
|
+ let byte_buffer: &[u8] = &src[offset..offset + core::mem::size_of::<T>()];
|
|
|
+
|
|
|
+ let chunks = unsafe { from_raw_parts(byte_buffer.as_ptr() as *const T, 1) };
|
|
|
+ let data = &chunks[0];
|
|
|
+ return Ok(data);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[allow(dead_code)]
|
|
|
+impl<'a> UserBufferWriter<'a> {
|
|
|
+ /// 构造一个指向用户空间位置的BufferWriter
|
|
|
+ ///
|
|
|
+ /// @param addr 用户空间指针
|
|
|
+ /// @param len 缓冲区的字节长度
|
|
|
+ /// @return 构造成功返回UserbufferWriter实例,否则返回错误码
|
|
|
+ ///
|
|
|
+ pub fn new<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
|
|
|
+ if from_user
|
|
|
+ && verify_area(
|
|
|
+ VirtAddr::new(addr as usize),
|
|
|
+ (len * core::mem::size_of::<U>()) as usize,
|
|
|
+ )
|
|
|
+ .is_err()
|
|
|
+ {
|
|
|
+ return Err(SystemError::EFAULT);
|
|
|
+ }
|
|
|
+ return Ok(Self {
|
|
|
+ buffer: unsafe {
|
|
|
+ core::slice::from_raw_parts_mut(addr as *mut u8, len * core::mem::size_of::<U>())
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 从指定地址写入数据到用户空间
|
|
|
+ ///
|
|
|
+ /// @param data 要写入的数据地址
|
|
|
+ /// @param offset 在UserBuffer中的字节偏移量
|
|
|
+ /// @return 返回写入元素的数量
|
|
|
+ ///
|
|
|
+ pub fn copy_to_user<T: core::marker::Copy>(
|
|
|
+ &'a mut self,
|
|
|
+ src: &'a [T],
|
|
|
+ offset: usize,
|
|
|
+ ) -> Result<usize, SystemError> {
|
|
|
+ let dst = Self::convert_with_offset(self.buffer, offset)?;
|
|
|
+ dst.copy_from_slice(&src);
|
|
|
+ return Ok(src.len());
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 从指定地址写入一个数据到用户空间
|
|
|
+ ///
|
|
|
+ /// @param data 要写入的数据地址
|
|
|
+ /// @param offset 在UserBuffer中的字节偏移量
|
|
|
+ /// @return 返回写入元素的数量
|
|
|
+ ///
|
|
|
+ pub fn copy_one_to_user<T: core::marker::Copy>(
|
|
|
+ &'a mut self,
|
|
|
+ src: &'a T,
|
|
|
+ offset: usize,
|
|
|
+ ) -> Result<(), SystemError> {
|
|
|
+ let dst = Self::convert_one_with_offset::<T>(self.buffer, offset)?;
|
|
|
+ dst.clone_from(src);
|
|
|
+ return Ok(());
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn buffer<T>(&'a mut self, offset: usize) -> Result<&mut [T], SystemError> {
|
|
|
+ Ok(Self::convert_with_offset::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)?)
|
|
|
+ }
|
|
|
+
|
|
|
+ fn convert_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut [T], SystemError> {
|
|
|
+ if offset >= src.len() {
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
+ }
|
|
|
+ let byte_buffer: &mut [u8] = &mut src[offset..];
|
|
|
+ if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ let chunks = unsafe {
|
|
|
+ from_raw_parts_mut(
|
|
|
+ byte_buffer.as_mut_ptr() as *mut T,
|
|
|
+ byte_buffer.len() / core::mem::size_of::<T>(),
|
|
|
+ )
|
|
|
+ };
|
|
|
+ return Ok(chunks);
|
|
|
+ }
|
|
|
+
|
|
|
+ fn convert_one_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut T, SystemError> {
|
|
|
+ if offset + core::mem::size_of::<T>() > src.len() {
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
+ }
|
|
|
+ let byte_buffer: &mut [u8] = &mut src[offset..offset + core::mem::size_of::<T>()];
|
|
|
+
|
|
|
+ let chunks = unsafe { from_raw_parts_mut(byte_buffer.as_mut_ptr() as *mut T, 1) };
|
|
|
+ let data = &mut chunks[0];
|
|
|
+ return Ok(data);
|
|
|
+ }
|
|
|
+}
|