@@ -23,6 +23,8 @@ use core::fmt;
2323use core:: iter:: Step ;
2424use core:: ops:: { Add , AddAssign , Sub , SubAssign } ;
2525
26+ use crate :: fs:: FileSystemError ;
27+
2628use super :: page_table:: { PageOffset , PageTableIndex } ;
2729use super :: { PageSize , Size4KiB , VmFrame } ;
2830
@@ -52,14 +54,28 @@ pub struct VirtAddr(u64);
5254#[ repr( transparent) ]
5355pub struct PhysAddr ( u64 ) ;
5456
55- /// A passed `u64` was not a valid virtual address.
56- ///
57- /// This means that bits 48 to 64 are not
58- /// a valid sign extension and are not null either. So automatic sign extension would have
59- /// overwritten possibly meaningful bits. This likely indicates a bug, for example an invalid
60- /// address calculation.
61- #[ derive( Debug ) ]
62- pub struct VirtAddrNotValid ( u64 ) ;
57+ #[ derive( Copy , Clone , Debug ) ]
58+ pub enum ReadErr {
59+ Null ,
60+ NotAligned ,
61+ }
62+
63+ impl From < ReadErr > for FileSystemError {
64+ fn from ( _: ReadErr ) -> Self {
65+ // `FileSystemError::NotSupported` will be converted to `EINVAL` on
66+ // syscall error conversion.
67+ FileSystemError :: NotSupported
68+ }
69+ }
70+
71+ impl From < ReadErr > for aero_syscall:: SyscallError {
72+ fn from ( value : ReadErr ) -> Self {
73+ match value {
74+ ReadErr :: Null => Self :: EINVAL ,
75+ ReadErr :: NotAligned => Self :: EACCES ,
76+ }
77+ }
78+ }
6379
6480impl VirtAddr {
6581 /// Creates a new canonical virtual address.
@@ -99,20 +115,15 @@ impl VirtAddr {
99115 ///
100116 /// ## Example
101117 /// ```no_run
102- /// let address: &mut SomeStruct = VirtAddr::new(0xcafebabe)
103- /// .read_mut::<SomeStruct>();
104- /// .ok_or(AeroSyscallError::EFAULT)?;
118+ /// let address: &mut SomeStruct = VirtAddr::new(0xcafebabe).read_mut::<SomeStruct>()?;
105119 /// ```
106- pub fn read_mut < ' struc , T : Sized > ( & self ) -> Option < & ' struc mut T > {
107- if self . validate_read :: < T > ( ) {
108- Some ( unsafe { & mut * ( self . as_mut_ptr ( ) as * mut T ) } )
109- } else {
110- None
111- }
120+ pub fn read_mut < ' a , T : Sized > ( & self ) -> Result < & ' a mut T , ReadErr > {
121+ self . validate_read :: < T > ( ) ?;
122+ Ok ( unsafe { & mut * ( self . as_mut_ptr ( ) as * mut T ) } )
112123 }
113124
114125 pub fn as_bytes_mut ( & self , size_bytes : usize ) -> & mut [ u8 ] {
115- assert ! ( self . validate_read:: <& [ u8 ] >( ) ) ;
126+ self . validate_read :: < & [ u8 ] > ( ) . unwrap ( ) ;
116127 unsafe { core:: slice:: from_raw_parts_mut ( self . as_mut_ptr ( ) , size_bytes) }
117128 }
118129
@@ -122,10 +133,17 @@ impl VirtAddr {
122133 }
123134
124135 /// Returns if the address is valid to read `sizeof(T)` bytes at the address.
125- fn validate_read < T : Sized > ( & self ) -> bool {
136+ fn validate_read < T : Sized > ( & self ) -> Result < ( ) , ReadErr > {
126137 // FIXME: (*self + core::mem::size_of::<T>()) <= crate::arch::task::userland_last_address()
127- // // in-range
128- self . 0 != 0 // non-null
138+ let raw = self . as_ptr :: < T > ( ) ;
139+
140+ if raw. is_null ( ) {
141+ return Err ( ReadErr :: Null ) ;
142+ } else if !raw. is_aligned ( ) {
143+ return Err ( ReadErr :: NotAligned ) ;
144+ }
145+
146+ Ok ( ( ) )
129147 }
130148
131149 /// Aligns the virtual address downwards to the given alignment.
0 commit comments