fn inner<S: Syscalls, CONFIG: allow_ro::Config>(
            driver_num: u32,
            buffer_num: u32,
            buffer: &[u8],
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Read-Only Allow. These arguments follow TRD104.
            let [r0, r1, r2, _] = unsafe {
                S::syscall4::<{ syscall_class::ALLOW_RO }>([
                    driver_num.into(),
                    buffer_num.into(),
                    buffer.as_ptr().into(),
                    buffer.len().into(),
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Read-Only Allow returns either Success
            // with 2 U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      panicing.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }

            // r0 indicates Success with 2 u32s. Confirm a zero buffer was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nozero_buffer is a no-op.
            let returned_buffer: (usize, usize) = (r1.into(), r2.into());
            if returned_buffer != (0, 0) {
                CONFIG::returned_nonzero_buffer(driver_num, buffer_num);
            }
            Ok(())
        }
// Inner function that does the majority of the work. This is not
// monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small.
//
// Security note: The syscall driver will retain read-only access to
// `*buffer` until this Allow ID is unallowed or overwritten via another
// Allow call. Therefore the caller must ensure the Allow ID is
// unallowed or overwritten before `*buffer` is deallocated, to avoid
// leaking newly-allocated information at the same address as `*buffer`.
Inner function that does the majority of the work. This is not
monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small.

Security note: The syscall driver will retain read-only access to
`*buffer` until this Allow ID is unallowed or overwritten via another
Allow call. Therefore the caller must ensure the Allow ID is
unallowed or overwritten before `*buffer` is deallocated, to avoid
leaking newly-allocated information at the same address as `*buffer`.
Inner function that does the majority of the work . This is not monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small . Security note : The syscall driver will retain read - only access to ` * buffer ` until this Allow ID is unallowed or overwritten via another Allow call . Therefore the caller must ensure the Allow ID is unallowed or overwritten before ` * buffer ` is deallocated to avoid leaking newly - allocated information at the same address as ` * buffer ` .
fn inner<S: Syscalls, CONFIG: allow_ro::Config>(
            driver_num: u32,
            buffer_num: u32,
            buffer: &[u8],
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Read-Only Allow. These arguments follow TRD104.
            let [r0, r1, r2, _] = unsafe {
                S::syscall4::<{ syscall_class::ALLOW_RO }>([
                    driver_num.into(),
                    buffer_num.into(),
                    buffer.as_ptr().into(),
                    buffer.len().into(),
                ])
            };
            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Read-Only Allow returns either Success
            // with 2 U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      panicing.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }
            // r0 indicates Success with 2 u32s. Confirm a zero buffer was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nozero_buffer is a no-op.
            let returned_buffer: (usize, usize) = (r1.into(), r2.into());
            if returned_buffer != (0, 0) {
                CONFIG::returned_nonzero_buffer(driver_num, buffer_num);
            }
            Ok(())
        }
fn inner < S : Syscalls , CONFIG : allow_ro :: Config > ( driver_num : u32 , buffer_num : u32 , buffer : & [ u8 ] , ) -> Result < ( ) , ErrorCode > { // Safety: syscall4's documentation indicates it can be used to call // Read-Only Allow. These arguments follow TRD104. let [ r0 , r1 , r2 , _ ] = unsafe { S :: syscall4 :: < { syscall_class :: ALLOW_RO } > ( [ driver_num . into ( ) , buffer_num . into ( ) , buffer . as_ptr ( ) . into ( ) , buffer . len ( ) . into ( ) , ] ) } ; let return_variant : ReturnVariant = r0 . as_u32 ( ) . into ( ) ; // TRD 104 guarantees that Read-Only Allow returns either Success // with 2 U32 or Failure with 2 U32. We check the return variant by // comparing against Failure with 2 U32 for 2 reasons: // //   1. On RISC-V with compressed instructions, it generates smaller //      code. FAILURE_2_U32 has value 2, which can be loaded into a //      register with a single compressed instruction, whereas //      loading SUCCESS_2_U32 uses an uncompressed instruction. //   2. In the event the kernel malfuctions and returns a different //      return variant, the success path is actually safer than the //      failure path. The failure path assumes that r1 contains an //      ErrorCode, and produces UB if it has an out of range value. //      Incorrectly assuming the call succeeded will not generate //      unsoundness, and will likely lead to the application //      panicing. if return_variant == return_variant :: FAILURE_2_U32 { // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32, // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. return Err ( unsafe { core :: mem :: transmute ( r1 . as_u32 ( ) as u16 ) } ) ; } // r0 indicates Success with 2 u32s. Confirm a zero buffer was // returned, and it if wasn't then call the configured function. // We're relying on the optimizer to remove this branch if // returned_nozero_buffer is a no-op. let returned_buffer : ( usize , usize ) = ( r1 . into ( ) , r2 . into ( ) ) ; if returned_buffer != ( 0 , 0 ) { CONFIG :: returned_nonzero_buffer ( driver_num , buffer_num ) ; } Ok ( ( ) ) }
Inner function that does the majority of the work.
Inner function that does the majority of the work .
driver_num
u32
buffer_num
u32
buffer
&[u8]
driver_num
u32
buffer_num
u32
buffer
&[u8]