optee-utee 0.0.1

TEE internal core API.
use crate::{Error, ErrorKind, Result};
use optee_utee_sys as raw;
use std::marker;

pub struct Parameters(pub Parameter, pub Parameter, pub Parameter, pub Parameter);

impl Parameters {
    pub fn from_raw(tee_params: &mut [raw::TEE_Param; 4], param_types: u32) -> Self {
        let (f0, f1, f2, f3) = ParamTypes::from(param_types).into_flags();
        let p0 = Parameter::from_raw(&mut tee_params[0], f0);
        let p1 = Parameter::from_raw(&mut tee_params[1], f1);
        let p2 = Parameter::from_raw(&mut tee_params[2], f2);
        let p3 = Parameter::from_raw(&mut tee_params[3], f3);

        Parameters(p0, p1, p2, p3)
    }
}

pub struct ParamValue<'parameter> {
    raw: *mut raw::Value,
    param_type: ParamType,
    _marker: marker::PhantomData<&'parameter mut u32>,
}

impl<'parameter> ParamValue<'parameter> {
    pub fn a(&self) -> u32 {
        unsafe { (*self.raw).a }
    }

    pub fn b(&self) -> u32 {
        unsafe { (*self.raw).b }
    }

    pub fn set_a(&mut self, a: u32) {
        unsafe { (*self.raw).a = a; }
    }

    pub fn set_b(&mut self, b: u32) {
        unsafe { (*self.raw).b = b; }
    }

    pub fn param_type(&self) -> ParamType {
        self.param_type
    }
}

pub struct ParamMemref<'parameter> {
    raw: *mut raw::Memref,
    param_type: ParamType,
    _marker: marker::PhantomData<&'parameter mut [u8]>,
}

impl<'parameter> ParamMemref<'parameter> {
    pub fn buffer(&mut self) -> &mut [u8] {
        unsafe {
            std::slice::from_raw_parts_mut((*self.raw).buffer as *mut u8, (*self.raw).size as usize)
        }
    }

    pub fn param_type(&self) -> ParamType {
        self.param_type
    }

    pub fn raw(&mut self) -> *mut raw::Memref {
        self.raw
    }

    pub fn set_updated_size(&mut self, size: u32) {
        unsafe { (*self.raw).size = size };
    }
}

pub struct Parameter {
    pub raw: *mut raw::TEE_Param,
    pub param_type: ParamType,
}

impl Parameter {
    pub fn from_raw(ptr: *mut raw::TEE_Param, param_type: ParamType) -> Self {
        Self {
            raw: ptr,
            param_type: param_type,
        }
    }

    pub unsafe fn as_value(&mut self) -> Result<ParamValue> {
        match self.param_type {
            ParamType::ValueInput | ParamType::ValueInout | ParamType::ValueOutput => {
                Ok(ParamValue {
                    raw: &mut (*self.raw).value,
                    param_type: self.param_type,
                    _marker: marker::PhantomData,
                })
            },
            _ => Err(Error::new(ErrorKind::BadParameters)),
        }
    }

    pub unsafe fn as_memref(&mut self) -> Result<ParamMemref> {
        match self.param_type {
            ParamType::MemrefInout | ParamType::MemrefInput | ParamType::MemrefOutput => {
                Ok(ParamMemref {
                    raw: &mut (*self.raw).memref,
                    param_type: self.param_type,
                    _marker: marker::PhantomData,
                })
            },
            _ => Err(Error::new(ErrorKind::BadParameters)),
        }
    }

    pub fn raw(&self) -> *mut raw::TEE_Param { self.raw }
}

pub struct ParamTypes(u32);

impl ParamTypes {
    pub fn into_flags(&self) -> (ParamType, ParamType, ParamType, ParamType) {
        (
            (0x000fu32 & self.0).into(),
            ((0x00f0u32 & self.0) >> 4).into(),
            ((0x0f00u32 & self.0) >> 8).into(),
            ((0xf000u32 & self.0) >> 12).into(),
        )
    }
}

impl From<u32> for ParamTypes {
    fn from(value: u32) -> Self {
        ParamTypes(value)
    }
}

#[derive(Copy, Clone)]
pub enum ParamType {
    None = 0,
    ValueInput = 1,
    ValueOutput = 2,
    ValueInout = 3,
    MemrefInput = 5,
    MemrefOutput = 6,
    MemrefInout = 7,
}

impl From<u32> for ParamType {
    fn from(value: u32) -> Self {
        match value {
            0 => ParamType::None,
            1 => ParamType::ValueInput,
            2 => ParamType::ValueOutput,
            3 => ParamType::ValueInout,
            5 => ParamType::MemrefInput,
            6 => ParamType::MemrefOutput,
            7 => ParamType::MemrefInout,
            _ => ParamType::None,
        }
    }
}