This is an automated email from the ASF dual-hosted git repository. ivila pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/teaclave-trustzone-sdk.git
commit 4269d01163e386a9c8164d6a53e64a1af8fc6634 Author: ivila <[email protected]> AuthorDate: Tue Jun 23 16:56:12 2026 +0800 optee-utee: introduce typed parameter API with `FromRawParameter` trait Replace the legacy raw-pointer-based `Parameters` API with type-safe parameter wrappers: - Add `ParameterValue{Input,Output,Inout}` and `ParameterMemref{Input,Output,Inout}` in `parameter/{value,memref}.rs` with `Read`/`Write` traits - Add `ParameterAny` enum for conditional parameter types - Add `FromRawParameter<'a>` and `FromRawParameters<'a>` traits - Move old `Parameters`/`Parameter`/`ParamValue`/`ParamMemref` to `parameter/deprecated.rs` and introduce `deprecated` crate. - Update `optee-utee-macros` to generate code via `FromRawParameters` trait instead of hardcoded `Parameters::from_raw` - Add `prelude` module re-exporting all parameter types and TA macros --- crates/Cargo.toml | 2 +- crates/optee-utee-macros/src/lib.rs | 189 ++++++++++---- crates/optee-utee-sys/src/tee_api_defines.rs | 4 + crates/optee-utee/src/lib.rs | 50 +++- .../src/{parameter.rs => parameter/deprecated.rs} | 97 +++++-- crates/optee-utee/src/parameter/memref.rs | 207 +++++++++++++++ crates/optee-utee/src/parameter/mod.rs | 290 +++++++++++++++++++++ crates/optee-utee/src/parameter/none.rs | 28 ++ crates/optee-utee/src/parameter/value.rs | 143 ++++++++++ crates/optee-utee/src/tee_parameter.rs | 2 +- 10 files changed, 921 insertions(+), 91 deletions(-) diff --git a/crates/Cargo.toml b/crates/Cargo.toml index 91c5ad2..d81ef01 100644 --- a/crates/Cargo.toml +++ b/crates/Cargo.toml @@ -50,7 +50,7 @@ optee-utee-macros = { version = "0.9.0", path = "optee-utee-macros" } optee-utee-sys = { version = "0.9.0", path = "optee-utee-sys" } bitflags = "2.11.0" -num_enum = "0.7.6" +num_enum = { version = "0.7.6", default-features = false } uuid = { version = "1.23", default-features = false } hex = { version = "0.4", default-features = false, features = ["alloc"] } quote = "1.0" diff --git a/crates/optee-utee-macros/src/lib.rs b/crates/optee-utee-macros/src/lib.rs index 0fa2927..4ba9e59 100644 --- a/crates/optee-utee-macros/src/lib.rs +++ b/crates/optee-utee-macros/src/lib.rs @@ -111,19 +111,44 @@ pub fn ta_destroy(_args: TokenStream, input: TokenStream) -> TokenStream { .into() } -/// Attribute to declare the entry point of opening a session. Pointer to -/// session context pointer (*mut *mut T) can be defined as an optional -/// parameter. +/// Attribute to declare the entry point of opening a session. +/// +/// The `params` argument may be any type that implements +/// `optee_utee::FromRawParameters` (`optee_utee::ParametersAny`, a 4-tuple +/// of typed wrappers, `optee_utee::Parameters`, etc.) +/// +/// A session context `&mut T` can be defined as an optional second parameter; +/// `T` must implement `Default`. /// /// # Examples /// -/// ``` no_run +/// ```ignore +/// // Old deprecated Parameters /// #[ta_open_session] /// fn open_session(params: &mut Parameters) -> Result<()> { } /// -/// // T is the sess_ctx struct and is required to implement default trait +/// // New typed parameters +/// use optee_utee::prelude::*; +/// #[ta_open_session] +/// fn open_session(params: &mut ( +/// ParameterNone, +/// ParameterMemrefInput<'_>, +/// ParameterValueOutput<'_>, +/// ParameterMemrefOutput<'_>, +/// )) -> Result<()> { } +/// // use ParametersAny and check types with match later. /// #[ta_open_session] -/// fn open_session(params: &mut Parameters, sess_ctx: &mut T) -> Result<()> { } +/// fn open_session( +/// cmd_id: u32, +/// params: &mut ParametersAny, +/// ) -> Result<()> { } +/// +/// // With session context +/// #[ta_open_session] +/// fn open_session( +/// params: &mut Parameters, +/// sess_ctx: &mut T, +/// ) -> Result<()> { } /// ``` #[proc_macro_attribute] pub fn ta_open_session(_args: TokenStream, input: TokenStream) -> TokenStream { @@ -142,30 +167,37 @@ pub fn ta_open_session(_args: TokenStream, input: TokenStream) -> TokenStream { if !valid_signature { return syn::parse::Error::new( f.span(), - "`#[ta_open_session]` function must have signature `fn(&mut Parameters) -> Result<()>` or `fn(&mut Parameters, &mut T) -> Result<()>`", + "`#[ta_open_session]` function must have signature `fn(&mut P) -> Result<()>` or `fn(&mut P, &mut T) -> Result<()>`", ) .to_compile_error() .into(); } match f_sig.inputs.len() { - 1 => quote!( - #[unsafe(no_mangle)] - pub extern "C" fn TA_OpenSessionEntryPoint( - param_types: optee_utee::RawParamTypes, - params: &mut optee_utee::RawParams, - _: *mut *mut core::ffi::c_void, - ) -> optee_utee_sys::TEE_Result { - let mut parameters = Parameters::from_raw(params, param_types); - match #f_ident(&mut parameters) { - Ok(_) => optee_utee_sys::TEE_SUCCESS, - Err(e) => e.raw_code() + 1 => { + let tokens = quote!( + #[unsafe(no_mangle)] + pub extern "C" fn TA_OpenSessionEntryPoint( + param_types: optee_utee::RawParamTypes, + params: &mut optee_utee::RawParams, + _: *mut *mut core::ffi::c_void, + ) -> optee_utee_sys::TEE_Result { + let mut parameters = match unsafe { + optee_utee::FromRawParameters::from_raw(param_types, params) + } { + Ok(p) => p, + Err(e) => return e.raw_code(), + }; + match #f_ident(&mut parameters) { + Ok(_) => optee_utee_sys::TEE_SUCCESS, + Err(e) => e.raw_code() + } } - } - #f - ) - .into(), + #f + ); + tokens.into() + } 2 => { let ctx_type = match extract_fn_arg_mut_ref_type(&f_sig.inputs[1]) { @@ -174,20 +206,23 @@ pub fn ta_open_session(_args: TokenStream, input: TokenStream) -> TokenStream { }; quote!( - // To eliminate the clippy error: this public function might dereference a raw pointer but is not marked `unsafe` - // we just expand the unsafe block, but the session-related macros need refactoring in the future #[unsafe(no_mangle)] pub unsafe extern "C" fn TA_OpenSessionEntryPoint( param_types: optee_utee::RawParamTypes, params: &mut optee_utee::RawParams, sess_ctx: *mut *mut core::ffi::c_void, ) -> optee_utee_sys::TEE_Result { - let mut parameters = Parameters::from_raw(params, param_types); + let mut parameters = match unsafe { + optee_utee::FromRawParameters::from_raw(param_types, params) + } { + Ok(p) => p, + Err(e) => return e.raw_code(), + }; let mut ctx: #ctx_type = Default::default(); match #f_ident(&mut parameters, &mut ctx) { Ok(_) => { - *sess_ctx = Box::into_raw(Box::new(ctx)) as _; + *sess_ctx = alloc::boxed::Box::into_raw(alloc::boxed::Box::new(ctx)) as _; optee_utee_sys::TEE_SUCCESS } Err(e) => e.raw_code() @@ -262,7 +297,7 @@ pub fn ta_close_session(_args: TokenStream, input: TokenStream) -> TokenStream { if sess_ctx.is_null() { panic!("sess_ctx is null"); } - let mut b = Box::from_raw(sess_ctx as *mut #ctx_type); + let mut b = alloc::boxed::Box::from_raw(sess_ctx as *mut #ctx_type); #f_ident(&mut b); drop(b); } @@ -275,17 +310,49 @@ pub fn ta_close_session(_args: TokenStream, input: TokenStream) -> TokenStream { } } -/// Attribute to declare the entry point of invoking commands. Session context -/// reference (`&mut T`) can be defined as an optional parameter. +/// Attribute to declare the entry point of invoking commands. +/// +/// The `params` argument may be any type that implements +/// `optee_utee::FromRawParameters` (`optee_utee::ParametersAny`, a 4-tuple +/// of typed wrappers, `optee_utee::Parameters`, etc.) +/// +/// A session context `&mut T` can be defined as an optional first parameter +/// (before `cmd_id`). /// /// # Examples /// -/// ``` no_run +/// ```ignore +/// // Old deprecated Parameters (no session context) /// #[ta_invoke_command] -/// fn invoke_command(sess_ctx: &mut T, cmd_id: u32, params: &mut Parameters) -> Result<()> { } +/// fn invoke_command(cmd_id: u32, params: &mut Parameters) -> Result<()> { } /// +/// // New typed parameters +/// use optee_utee::prelude::*; +/// +/// // 4-tuple of typed wrappers /// #[ta_invoke_command] -/// fn invoke_command(cmd_id: u32, params: &mut Parameters) -> Result<()> { } +/// fn invoke_command( +/// cmd_id: u32, +/// params: &mut ( +/// ParameterNone, +/// ParameterMemrefInput<'_>, +/// ParameterValueOutput<'_>, +/// ParameterMemrefOutput<'_>, +/// ), +/// ) -> Result<()> { } +/// // use ParametersAny and check types with match later. +/// #[ta_invoke_command] +/// fn invoke_command( +/// cmd_id: u32, +/// params: &mut ParametersAny, +/// ) -> Result<()> { } +/// // With session context +/// #[ta_invoke_command] +/// fn invoke_command( +/// sess_ctx: &mut T, +/// cmd_id: u32, +/// params: &mut Parameters, +/// ) -> Result<()> { } /// ``` #[proc_macro_attribute] pub fn ta_invoke_command(_args: TokenStream, input: TokenStream) -> TokenStream { @@ -304,33 +371,40 @@ pub fn ta_invoke_command(_args: TokenStream, input: TokenStream) -> TokenStream if !valid_signature { return syn::parse::Error::new( f.span(), - "`#[ta_invoke_command]` function must have signature `fn(&mut T, u32, &mut Parameters) -> Result<()>` or `fn(u32, &mut Parameters) -> Result<()>`", + "`#[ta_invoke_command]` function must have signature `fn(u32, &mut P) -> Result<()>` or `fn(&mut T, u32, &mut P) -> Result<()>`", ) .to_compile_error() .into(); } match f_sig.inputs.len() { - 2 => quote!( - #[unsafe(no_mangle)] - pub extern "C" fn TA_InvokeCommandEntryPoint( - _: *mut core::ffi::c_void, - cmd_id: u32, - param_types: u32, - params: &mut optee_utee::RawParams, - ) -> optee_utee_sys::TEE_Result { - let mut parameters = Parameters::from_raw(params, param_types); - match #f_ident(cmd_id, &mut parameters) { - Ok(_) => { - optee_utee_sys::TEE_SUCCESS - }, - Err(e) => e.raw_code() + 2 => { + let tokens = quote!( + #[unsafe(no_mangle)] + pub extern "C" fn TA_InvokeCommandEntryPoint( + _: *mut core::ffi::c_void, + cmd_id: u32, + param_types: optee_utee::RawParamTypes, + params: &mut optee_utee::RawParams, + ) -> optee_utee_sys::TEE_Result { + let mut parameters = match unsafe { + optee_utee::FromRawParameters::from_raw(param_types, params) + } { + Ok(p) => p, + Err(e) => return e.raw_code(), + }; + match #f_ident(cmd_id, &mut parameters) { + Ok(_) => { + optee_utee_sys::TEE_SUCCESS + }, + Err(e) => e.raw_code() + } } - } - #f - ) - .into(), + #f + ); + tokens.into() + } 3 => { let ctx_type = match extract_fn_arg_mut_ref_type(&f_sig.inputs[0]) { Ok(v) => v, @@ -338,20 +412,23 @@ pub fn ta_invoke_command(_args: TokenStream, input: TokenStream) -> TokenStream }; quote!( - // To eliminate the clippy error: this public function might dereference a raw pointer but is not marked `unsafe` - // we just expand the unsafe block, but the session-related macros need refactoring in the future #[unsafe(no_mangle)] pub unsafe extern "C" fn TA_InvokeCommandEntryPoint( sess_ctx: *mut core::ffi::c_void, cmd_id: u32, - param_types: u32, + param_types: optee_utee::RawParamTypes, params: &mut optee_utee::RawParams, ) -> optee_utee_sys::TEE_Result { if sess_ctx.is_null() { return optee_utee_sys::TEE_ERROR_SECURITY; } - let mut parameters = Parameters::from_raw(params, param_types); - let mut b = Box::from_raw(sess_ctx as *mut #ctx_type); + let mut parameters = match unsafe { + optee_utee::FromRawParameters::from_raw(param_types, params) + } { + Ok(p) => p, + Err(e) => return e.raw_code(), + }; + let mut b = alloc::boxed::Box::from_raw(sess_ctx as *mut #ctx_type); match #f_ident(&mut b, cmd_id, &mut parameters) { Ok(_) => { core::mem::forget(b); diff --git a/crates/optee-utee-sys/src/tee_api_defines.rs b/crates/optee-utee-sys/src/tee_api_defines.rs index 2ad36bf..149b82b 100644 --- a/crates/optee-utee-sys/src/tee_api_defines.rs +++ b/crates/optee-utee-sys/src/tee_api_defines.rs @@ -472,4 +472,8 @@ pub fn TEE_PARAM_TYPES(t0: u32, t1: u32, t2: u32, t3: u32) -> u32 { t0 | t1 << 4 | t2 << 8 | t3 << 12 } +pub fn TEE_PARAM_TYPE_GET(t: u32, i: usize) -> u32 { + (t >> (i * 4)) & 0xF +} + pub const TEE_NUM_PARAMS: u32 = 4; diff --git a/crates/optee-utee/src/lib.rs b/crates/optee-utee/src/lib.rs index 08acf35..68894bf 100644 --- a/crates/optee-utee/src/lib.rs +++ b/crates/optee-utee/src/lib.rs @@ -57,22 +57,32 @@ mod unwind_stubs { extern "C" fn rust_eh_personality() {} } -pub use self::arithmetical::*; -pub use self::crypto_op::*; -pub use self::error::{Error, ErrorKind, Result}; -pub use self::extension::*; -pub use self::identity::{Identity, LoginType}; -pub use self::object::*; -pub use self::parameter::{ - ParamType, ParamTypes, Parameter, Parameters, RawParamType, RawParamTypes, RawParams, -}; -pub use self::ta_session::{TaSession, TaSessionBuilder}; -pub use self::tee_parameter::{ParamIndex, TeeParams}; -pub use self::time::*; -pub use self::uuid::*; +pub use arithmetical::*; +pub use crypto_op::*; +pub use error::{Error, ErrorKind, Result}; +pub use extension::*; +pub use identity::{Identity, LoginType}; +pub use object::*; pub use optee_utee_macros::{ ta_close_session, ta_create, ta_destroy, ta_invoke_command, ta_open_session, }; +pub use parameter::{ + FromRawParameter, FromRawParameters, ParamType, ParameterAny, ParametersAny, ParametersNone, + RawParamType, RawParamTypes, RawParams, deprecated, + memref::{ + ParameterMemrefInout, ParameterMemrefInput, ParameterMemrefOutput, ParameterMemrefRead, + ParameterMemrefWrite, + }, + none::ParameterNone, + value::{ + ParameterValueInout, ParameterValueInput, ParameterValueOutput, ParameterValueRead, + ParameterValueWrite, + }, +}; +pub use ta_session::{TaSession, TaSessionBuilder}; +pub use tee_parameter::{ParamIndex, TeeParams}; +pub use time::*; +pub use uuid::*; pub mod trace; #[macro_use] @@ -90,3 +100,17 @@ mod ta_session; mod tee_parameter; pub mod time; pub mod uuid; + +// Re-export optee_utee_sys so developers don't have to add it to their cargo +// dependencies. +pub use optee_utee_sys as raw; + +pub mod prelude { + pub use crate::{ + FromRawParameter, FromRawParameters, ParameterAny, ParameterMemrefInout, + ParameterMemrefInput, ParameterMemrefOutput, ParameterMemrefRead, ParameterMemrefWrite, + ParameterNone, ParameterValueInout, ParameterValueInput, ParameterValueOutput, + ParameterValueRead, ParameterValueWrite, ParametersAny, ParametersNone, ta_close_session, + ta_create, ta_destroy, ta_invoke_command, ta_open_session, trace_print, trace_println, + }; +} diff --git a/crates/optee-utee/src/parameter.rs b/crates/optee-utee/src/parameter/deprecated.rs similarity index 56% rename from crates/optee-utee/src/parameter.rs rename to crates/optee-utee/src/parameter/deprecated.rs index 38708eb..ded028e 100644 --- a/crates/optee-utee/src/parameter.rs +++ b/crates/optee-utee/src/parameter/deprecated.rs @@ -15,14 +15,53 @@ // specific language governing permissions and limitations // under the License. -use crate::{Error, ErrorKind, Result}; +//! Legacy raw-pointer-based parameter API (deprecated). +//! +//! The types in this module use raw `*mut TEE_Param` pointers and require +//! manual unsafe casts at every call site. **New code should use the typed +//! wrappers** instead: +//! +//! | Legacy type | Replacement | +//! |---|---| +//! | [`Parameters`] | Use [`FromRawParameters`] with a 4-tuple of typed wrappers (e.g. `(ParameterNone, ParameterMemrefInput, ParameterValueOutput, ParameterMemrefOutput)`) | +//! | [`Parameter`] | Use the concrete types: [`ParameterValueInput`](crate::ParameterValueInput), [`ParameterValueOutput`](crate::ParameterValueOutput), [`ParameterMemrefInput`](crate::ParameterMemrefInput), etc. | +//! | [`ParamValue`] | Use the concrete types: [`ParameterValueInput`](crate::ParameterValueInput), [`ParameterValueOutput`](crate::ParameterValueOutput), [`ParameterValueInout`](crate::ParameterValueInout), and the traits: [`ParameterValueRead`](crate::ParameterValueRead) and [`ParameterValueWrite`](crate::ParameterValueWrite) | +//! | [`ParamMemref`] | Use the concrete types: [`ParameterMemrefInput`](crate::ParameterMemrefInput), [`ParameterMemrefOutput`](crate::ParameterMemrefOutput), [`ParameterMemrefInout`](crate::ParameterMemrefInout), and the traits: [`ParameterMemrefRead`](crate::ParameterMemrefRead) and [`ParameterMemrefWrite`](crate::ParameterMemrefWrite) | +//! +//! # Example migration +//! +//! **Old (deprecated) code:** +//! +//! ```rust,ignore +//! fn invoke_command(cmd_id: u32, params: &mut Parameters) -> Result<()> { +//! let mut p0 = unsafe { params.0.as_memref()? }; +//! // extra codes here... +//! let data = p0.buffer(); +//! data.copy_from_slice(&output); +//! p0.set_updated_size(output.len()); +//! } +//! ``` +//! +//! **New code:** +//! +//! ```rust,ignore +//! use optee_utee::prelude::*; +//! +//! fn invoke_command(cmd_id: u32, params: &mut (ParameterMemrefInout, ...)) -> Result<()> { +//! let p0 = &mut params.0; +//! // extra codes here... +//! p0.write_at(0, output) +//! } +//! ``` + +use super::{ParamType, RawParamTypes, RawParams}; +use crate::{Error, ErrorKind, FromRawParameters, Result, raw}; use core::{marker, slice}; -use optee_utee_sys as raw; - -pub type RawParamType = u32; -pub type RawParamTypes = u32; -pub type RawParams = [raw::TEE_Param; 4]; +/// # Deprecated +/// +/// Use the typed wrappers with [`super::FromRawParameters`] instead. See the +/// [module-level documentation](self) for migration examples. pub struct Parameters(pub Parameter, pub Parameter, pub Parameter, pub Parameter); impl Parameters { @@ -37,6 +76,11 @@ impl Parameters { } } +/// # Deprecated +/// +/// Use [`super::value::ParameterValueRead`] (for `get_a/get_b`) and +/// [`super::value::ParameterValueWrite`] (for `set_a/set_b`) on the typed +/// wrappers ([`super::value::ParameterValueInput`], etc.) instead. pub struct ParamValue<'parameter> { raw: *mut raw::Value, param_type: ParamType, @@ -69,6 +113,13 @@ impl<'parameter> ParamValue<'parameter> { } } +/// Lightweight accessor for a memory-reference TEE parameter. +/// +/// # Deprecated +/// +/// Use [`super::memref::ParameterMemrefRead`] (for `get_buffer`) and +/// [`super::memref::ParameterMemrefWrite`] (for `get_buffer_mut`, +/// `set_updated_size`, `write_at`) on the typed wrappers instead. pub struct ParamMemref<'parameter> { raw: *mut raw::Memref, param_type: ParamType, @@ -93,6 +144,12 @@ impl<'parameter> ParamMemref<'parameter> { } } +/// # Deprecated +/// +/// Use the concrete typed wrappers +/// ([`super::value::ParameterValueInput`], [`super::memref::ParameterMemrefInput`], etc.) +/// instead. They encode the parameter type in the Rust type system, making +/// mismatched-type errors impossible at compile time. pub struct Parameter { pub raw: *mut raw::TEE_Param, pub param_type: ParamType, @@ -107,7 +164,9 @@ impl Parameter { } /// # Safety - /// The caller must ensure that the raw pointer is valid and points to a properly initialized TEE_Param. + /// + /// The caller must ensure that the raw pointer is valid and points to a + /// properly initialized `TEE_Param`. pub unsafe fn as_value(&mut self) -> Result<ParamValue<'_>> { match self.param_type { ParamType::ValueInput | ParamType::ValueInout | ParamType::ValueOutput => { @@ -122,7 +181,9 @@ impl Parameter { } /// # Safety - /// The caller must ensure that the raw pointer is valid and points to a properly initialized TEE_Param. + /// + /// The caller must ensure that the raw pointer is valid and points to a + /// properly initialized `TEE_Param`. pub unsafe fn as_memref(&mut self) -> Result<ParamMemref<'_>> { match self.param_type { ParamType::MemrefInout | ParamType::MemrefInput | ParamType::MemrefOutput => { @@ -141,6 +202,10 @@ impl Parameter { } } +/// # Deprecated +/// +/// Use the typed wrappers with [`super::FromRawParameters`] instead; they +/// extract the types implicitly via `TEE_PARAM_TYPE_GET`. pub struct ParamTypes(u32); impl ParamTypes { @@ -160,16 +225,8 @@ impl From<u32> for ParamTypes { } } -#[derive(Copy, Clone, num_enum::FromPrimitive, num_enum::IntoPrimitive)] -#[repr(u32)] -pub enum ParamType { - None = raw::TEE_PARAM_TYPE_NONE, - ValueInput = raw::TEE_PARAM_TYPE_VALUE_INPUT, - ValueOutput = raw::TEE_PARAM_TYPE_VALUE_OUTPUT, - ValueInout = raw::TEE_PARAM_TYPE_VALUE_INOUT, - MemrefInput = raw::TEE_PARAM_TYPE_MEMREF_INPUT, - MemrefOutput = raw::TEE_PARAM_TYPE_MEMREF_OUTPUT, - MemrefInout = raw::TEE_PARAM_TYPE_MEMREF_INOUT, - #[num_enum(catch_all)] - Unknown(u32), +impl<'a> FromRawParameters<'a> for Parameters { + unsafe fn from_raw(raw_types: RawParamTypes, raw_params: &'a mut RawParams) -> Result<Self> { + Ok(Self::from_raw(raw_params, raw_types)) + } } diff --git a/crates/optee-utee/src/parameter/memref.rs b/crates/optee-utee/src/parameter/memref.rs new file mode 100644 index 0000000..a34cc46 --- /dev/null +++ b/crates/optee-utee/src/parameter/memref.rs @@ -0,0 +1,207 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Type-safe wrappers for TEE memory-reference parameters. +//! +//! A *memref* (memory reference) parameter maps a shared-memory buffer +//! between the host and the TA. Unlike value parameters which carry two +//! `u32` values, memrefs can transport arbitrary byte sequences. +//! +//! This module provides: +//! +//! * [`ParameterMemrefRead`] trait for reading the buffer contents. +//! * [`ParameterMemrefWrite`] trait for writing into buffers and +//! reporting updated sizes. +//! * Three concrete wrappers encoding the data direction: +//! [`ParameterMemrefInput`], [`ParameterMemrefOutput`], +//! [`ParameterMemrefInout`]. +//! +//! # Direction guarantees +//! +//! | Type | Host → TA | TA → Host | +//! |---|---|---| +//! | `ParameterMemrefInput` | ✓ | ✗ | +//! | `ParameterMemrefOutput` | ✗ | ✓ | +//! | `ParameterMemrefInout` | ✓ | ✓ | + +use super::{FromRawParameter, ParamType, RawParamType, check_type_is}; +use crate::{ErrorKind, Result, raw::TEE_Param}; + +/// Read-only access to a memory-reference parameter's buffer. +/// +/// Implemented by [`ParameterMemrefInput`] and [`ParameterMemrefInout`]. +pub trait ParameterMemrefRead { + /// Returns the buffer contents as a byte slice. + /// + /// For `ParameterMemrefInput` the length is the original buffer size as + /// supplied by the host. For `ParameterMemrefInout` the length is the + /// full buffer capacity, not the number of valid bytes (which may have + /// been updated by a prior write). + fn get_buffer(&self) -> &[u8]; +} + +/// Write access to a memory-reference parameter's buffer. +/// +/// Implemented by [`ParameterMemrefOutput`] and [`ParameterMemrefInout`]. +pub trait ParameterMemrefWrite { + /// Returns a mutable byte slice representing the output buffer. + /// + /// After writing to the returned buffer, call + /// [`ParameterMemrefWrite::set_updated_size`] to report how many bytes were + /// produced. Otherwise the client application may observe an incorrect + /// output size. + fn get_buffer_mut(&mut self) -> &mut [u8]; + + /// Returns the maximum allowed buffer size (capacity). + fn get_capacity(&self) -> usize; + + /// Sets the updated size after bounds checking. + /// + /// Returns `ErrorKind::ShortBuffer` if `size > get_capacity()`. + fn set_updated_size(&mut self, size: usize) -> Result<()> { + if size > self.get_capacity() { + return Err(ErrorKind::ShortBuffer.into()); + } + unsafe { self.set_updated_size_unchecked(size) }; + Ok(()) + } + + /// Copies `data` into the buffer, then updates the reported size. + fn set_output<T: AsRef<[u8]>>(&mut self, data: T) -> Result<()> { + self.write_at(0, data) + } + + /// Copies `data` into the buffer at the given `offset`, then updates the + /// reported size to `offset + data.len()`. + /// + /// Returns `ErrorKind::ShortBuffer` if the new size would exceed + /// the buffer capacity. + fn write_at<T: AsRef<[u8]>>(&mut self, offset: usize, data: T) -> Result<()> { + let input = data.as_ref(); + let new_size = offset + input.len(); + if new_size > self.get_capacity() { + return Err(ErrorKind::ShortBuffer.into()); + } + let output = self.get_buffer_mut(); + output[offset..new_size].copy_from_slice(input); + unsafe { self.set_updated_size_unchecked(new_size) }; + Ok(()) + } + + /// Directly sets the updated size without bounds checking. + /// + /// # Safety + /// + /// The `size` must not exceed `get_capacity()`. Prefer + /// [`ParameterMemrefWrite::set_updated_size`] unless the caller has already + /// checked the bounds. + unsafe fn set_updated_size_unchecked(&mut self, size: usize); +} + +/// A memory-reference input parameter. +/// +/// The host passes a read-only buffer to the TA. The length is the +/// original buffer size as specified by the host. +pub struct ParameterMemrefInput<'a>(&'a TEE_Param); + +/// A memory-reference in/out parameter. +/// +/// The host passes a read-write buffer. The TA may read the initial contents, +/// overwrite them, and report the final number of valid bytes. +pub struct ParameterMemrefInout<'a> { + capacity: usize, + raw_param: &'a mut TEE_Param, +} + +/// A memory-reference output parameter. +/// +/// The host provides a write-only buffer. The TA fills the buffer and report +/// the final number of valid bytes via +/// [`ParameterMemrefWrite::set_updated_size`]. +pub struct ParameterMemrefOutput<'a> { + capacity: usize, + raw_param: &'a mut TEE_Param, +} + +impl<'a> FromRawParameter<'a> for ParameterMemrefInput<'a> { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::MemrefInput)?; + Ok(Self(raw_param)) + } +} +impl<'a> FromRawParameter<'a> for ParameterMemrefInout<'a> { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::MemrefInout)?; + Ok(Self { + capacity: unsafe { raw_param.memref.size }, + raw_param, + }) + } +} +impl<'a> FromRawParameter<'a> for ParameterMemrefOutput<'a> { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::MemrefOutput)?; + Ok(Self { + capacity: unsafe { raw_param.memref.size }, + raw_param, + }) + } +} + +impl<'a> ParameterMemrefWrite for ParameterMemrefInout<'a> { + fn get_buffer_mut(&mut self) -> &mut [u8] { + unsafe { + core::slice::from_raw_parts_mut(self.raw_param.memref.buffer as *mut u8, self.capacity) + } + } + fn get_capacity(&self) -> usize { + self.capacity + } + unsafe fn set_updated_size_unchecked(&mut self, size: usize) { + self.raw_param.memref.size = size; + } +} + +impl<'a> ParameterMemrefWrite for ParameterMemrefOutput<'a> { + fn get_buffer_mut(&mut self) -> &mut [u8] { + unsafe { + core::slice::from_raw_parts_mut(self.raw_param.memref.buffer as *mut u8, self.capacity) + } + } + fn get_capacity(&self) -> usize { + self.capacity + } + unsafe fn set_updated_size_unchecked(&mut self, size: usize) { + self.raw_param.memref.size = size; + } +} + +impl<'a> ParameterMemrefRead for ParameterMemrefInout<'a> { + fn get_buffer(&self) -> &[u8] { + unsafe { + core::slice::from_raw_parts(self.raw_param.memref.buffer as *const u8, self.capacity) + } + } +} + +impl<'a> ParameterMemrefRead for ParameterMemrefInput<'a> { + fn get_buffer(&self) -> &[u8] { + unsafe { + core::slice::from_raw_parts(self.0.memref.buffer as *const u8, self.0.memref.size) + } + } +} diff --git a/crates/optee-utee/src/parameter/mod.rs b/crates/optee-utee/src/parameter/mod.rs new file mode 100644 index 0000000..79422f0 --- /dev/null +++ b/crates/optee-utee/src/parameter/mod.rs @@ -0,0 +1,290 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! TEE parameter handling: conversion from raw OP-TEE parameter types into +//! type-safe Rust wrappers. +//! +//! # Overview +//! +//! OP-TEE passes up to four parameters between the host (Normal World) and +//! the TA (Trusted Application). Each parameter has an associated *type* tag +//! (e.g. value, memref) and a raw `TEE_Param` union. This module provides: +//! +//! * **`FromRawParameter`** – single-parameter conversion from a raw +//! `TEE_Param` into a typed Rust wrapper. +//! * **`FromRawParameters`** – batch conversion of all four parameters at once +//! (implemented for 4-tuples of `FromRawParameter` types). +//! * **Typed wrappers** – `ParameterNone`, `ParameterValueInput`, +//! `ParameterMemrefInput`, etc. +//! * **Type-erased wrapper** – [`ParameterAny`] for scenarios where the +//! developer cannot know the parameter type at compile time. +//! * **Legacy compatibility** – [`deprecated`] provides the old unsafe +//! pointer-based API; new code should use the typed wrappers instead. +//! +//! # Migration from the deprecated API +//! +//! If you currently use [`deprecated::Parameters`] and [`deprecated::Parameter`]: +//! +//! | Old pattern | New pattern | +//! |---|---| +//! | `params.0.as_value()?.a()` | `param.get_a()` via [`ParameterValueRead`](crate::ParameterValueRead] | +//! | `params.0.as_memref()?.buffer()` | `param.get_buffer()` or `param.get_buffer_mut()` via [`crate::ParameterMemrefRead`]/[`crate::ParameterMemrefWrite`] | +//! | `params.0.set_updated_size(n)` | `param.set_updated_size(n)` via [`crate::ParameterMemrefWrite`] | +//! +//! See the [`deprecated`] module for per-type migration notes. + +use crate::{ErrorKind, Result, raw}; + +pub mod deprecated; +pub mod memref; +pub mod none; +pub mod value; + +/// Raw parameter-type tag as passed by the TEE runtime. +/// Each of the four slots carries a 4-bit type-identifier. Use +/// `TEE_PARAM_TYPE_GET(raw_types, idx)` to extract one slot from +/// the `RawParamTypes` bit-field. +pub type RawParamType = u32; + +/// Together with a [`RawParams`] array this describes the name *and* content +/// of all four TEE parameters. +pub type RawParamTypes = u32; + +/// Array of four raw `TEE_Param` unions. +/// +/// Corresponds to the four parameter slots passed to every TA entry-point. +pub type RawParams = [raw::TEE_Param; raw::TEE_NUM_PARAMS as usize]; + +/// Convert a single raw parameter into a type-safe Rust wrapper. +/// +/// # Safety +/// +/// Implementors must validate that `raw_type` matches the expected parameter +/// type and that `raw_param` has been correctly initialized by the TEE +/// runtime before reading any fields. +pub trait FromRawParameter<'a>: Sized { + /// Construct `Self` from a raw parameter. + /// + /// # Safety + /// + /// Caller must ensure `raw_type` and `raw_param` are a consistent pair + /// delivered by a TEE entry-point invocation (e.g. `TA_InvokeCommandEntryPoint`). + #[allow(clippy::missing_safety_doc)] + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut raw::TEE_Param) -> Result<Self>; +} + +/// Convert all four raw parameters at once into a typed tuple. +/// +/// # Safety +/// +/// The same safety constraints as [`FromRawParameter`] apply to each slot. +pub trait FromRawParameters<'a>: Sized { + /// Construct `Self` from the full parameter array. + /// + /// # Safety + /// + /// Caller must ensure `raw_types` and `raw_param` come from the same + /// TEE entry-point invocation. + #[allow(clippy::missing_safety_doc)] + unsafe fn from_raw(raw_types: RawParamTypes, raw_params: &'a mut RawParams) -> Result<Self>; +} + +impl< + 'a, + A: FromRawParameter<'a>, + B: FromRawParameter<'a>, + C: FromRawParameter<'a>, + D: FromRawParameter<'a>, +> FromRawParameters<'a> for (A, B, C, D) +{ + unsafe fn from_raw(raw_types: RawParamTypes, raw_params: &'a mut RawParams) -> Result<Self> { + Ok(unsafe { + let [p0, p1, p2, p3] = raw_params; + ( + A::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 0), p0)?, + B::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 1), p1)?, + C::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 2), p2)?, + D::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 3), p3)?, + ) + }) + } +} + +/// Enumerates the seven standard TEE parameter types. +/// +/// This is the Rust-side mirror of the `TEE_PARAM_TYPE_*` constants defined +/// in the C header. The `Unknown(u32)` variant catches any +/// implementation-defined or invalid type tags. +#[derive(Copy, Clone, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[repr(u32)] +pub enum ParamType { + None = raw::TEE_PARAM_TYPE_NONE, + ValueInput = raw::TEE_PARAM_TYPE_VALUE_INPUT, + ValueOutput = raw::TEE_PARAM_TYPE_VALUE_OUTPUT, + ValueInout = raw::TEE_PARAM_TYPE_VALUE_INOUT, + MemrefInput = raw::TEE_PARAM_TYPE_MEMREF_INPUT, + MemrefOutput = raw::TEE_PARAM_TYPE_MEMREF_OUTPUT, + MemrefInout = raw::TEE_PARAM_TYPE_MEMREF_INOUT, + #[num_enum(catch_all)] + Unknown(u32), +} + +fn check_type_is(raw_type: RawParamType, exp_type: ParamType) -> Result<()> { + let exp_type: u32 = exp_type.into(); + if raw_type != exp_type { + return Err(ErrorKind::BadParameters.into()); + } + Ok(()) +} + +/// A type-erased parameter that dispatches to the correct concrete wrapper +/// based on the runtime type tag. +/// +/// # When to use +/// +/// Use `ParameterAny` when the parameter type is **not known at compile time** +/// and must be determined at runtime. Typical scenarios: +/// +/// * The command semantics allow multiple parameter types for the same slot +/// (e.g. "slot 0 may be `None` or `MemrefInput` depending on the command"). +/// * A library helper is designed to inspect parameters generically without +/// fixing the types in its signature. +/// +/// If you already know the expected type for a slot, prefer the concrete +/// wrappers from [`value`] and [`memref`] instead—they provide methods +/// specific to that type and avoid the match ceremony. +/// +/// # Example +/// +/// ```rust,ignore +/// use optee_utee::parameter::{ParameterAny, FromRawParameter}; +/// +/// match param { +/// ParameterAny::None => { /* no parameter */ } +/// ParameterAny::MemrefInput(p) => { +/// let data: &[u8] = p.get_buffer(); +/// // process data ... +/// } +/// ParameterAny::ValueInput(p) => { +/// let a = p.get_a(); +/// let b = p.get_b(); +/// // use a, b ... +/// } +/// _ => return Err(ErrorKind::BadParameters.into()), +/// } +/// ``` +pub enum ParameterAny<'a> { + None, + ValueInput(value::ParameterValueInput), + ValueInout(value::ParameterValueInout<'a>), + ValueOutput(value::ParameterValueOutput<'a>), + MemrefInput(memref::ParameterMemrefInput<'a>), + MemrefInout(memref::ParameterMemrefInout<'a>), + MemrefOutput(memref::ParameterMemrefOutput<'a>), + /// Unrecognized or implementation-defined type tag. + /// + /// Carries the raw `RawParamType` and a mutable reference to the + /// underlying `TEE_Param` so that the caller can handle it manually. + Unknown(RawParamType, &'a mut raw::TEE_Param), +} + +impl<'a> ParameterAny<'a> { + pub fn as_value_input(&self) -> Result<&value::ParameterValueInput> { + match &self { + Self::ValueInput(p) => Ok(p), + _ => Err(ErrorKind::BadParameters.into()), + } + } + pub fn as_value_output(&mut self) -> Result<&mut value::ParameterValueOutput<'a>> { + match self { + Self::ValueOutput(p) => Ok(p), + _ => Err(ErrorKind::BadParameters.into()), + } + } + pub fn as_value_inout(&mut self) -> Result<&mut value::ParameterValueInout<'a>> { + match self { + Self::ValueInout(p) => Ok(p), + _ => Err(ErrorKind::BadParameters.into()), + } + } + pub fn as_memref_input(&self) -> Result<&memref::ParameterMemrefInput<'a>> { + match self { + Self::MemrefInput(p) => Ok(p), + _ => Err(ErrorKind::BadParameters.into()), + } + } + pub fn as_memref_inout(&mut self) -> Result<&mut memref::ParameterMemrefInout<'a>> { + match self { + Self::MemrefInout(p) => Ok(p), + _ => Err(ErrorKind::BadParameters.into()), + } + } + pub fn as_memref_output(&mut self) -> Result<&mut memref::ParameterMemrefOutput<'a>> { + match self { + Self::MemrefOutput(p) => Ok(p), + _ => Err(ErrorKind::BadParameters.into()), + } + } + pub fn as_none(&self) -> Result<()> { + match self { + Self::None => Ok(()), + _ => Err(ErrorKind::BadParameters.into()), + } + } +} + +impl<'a> FromRawParameter<'a> for ParameterAny<'a> { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut raw::TEE_Param) -> Result<Self> { + unsafe { + match raw_type { + raw::TEE_PARAM_TYPE_NONE => Ok(Self::None), + raw::TEE_PARAM_TYPE_VALUE_INPUT => Ok(Self::ValueInput( + value::ParameterValueInput::from_raw(raw_type, raw_param)?, + )), + raw::TEE_PARAM_TYPE_VALUE_INOUT => Ok(Self::ValueInout( + value::ParameterValueInout::from_raw(raw_type, raw_param)?, + )), + raw::TEE_PARAM_TYPE_VALUE_OUTPUT => Ok(Self::ValueOutput( + value::ParameterValueOutput::from_raw(raw_type, raw_param)?, + )), + raw::TEE_PARAM_TYPE_MEMREF_INPUT => Ok(Self::MemrefInput( + memref::ParameterMemrefInput::from_raw(raw_type, raw_param)?, + )), + raw::TEE_PARAM_TYPE_MEMREF_INOUT => Ok(Self::MemrefInout( + memref::ParameterMemrefInout::from_raw(raw_type, raw_param)?, + )), + raw::TEE_PARAM_TYPE_MEMREF_OUTPUT => Ok(Self::MemrefOutput( + memref::ParameterMemrefOutput::from_raw(raw_type, raw_param)?, + )), + _ => Ok(Self::Unknown(raw_type, raw_param)), + } + } + } +} + +pub type ParametersAny<'a> = ( + ParameterAny<'a>, + ParameterAny<'a>, + ParameterAny<'a>, + ParameterAny<'a>, +); +pub type ParametersNone = ( + none::ParameterNone, + none::ParameterNone, + none::ParameterNone, + none::ParameterNone, +); diff --git a/crates/optee-utee/src/parameter/none.rs b/crates/optee-utee/src/parameter/none.rs new file mode 100644 index 0000000..405772d --- /dev/null +++ b/crates/optee-utee/src/parameter/none.rs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use super::{FromRawParameter, ParamType, RawParamType, check_type_is}; +use crate::{Result, raw::TEE_Param}; + +pub struct ParameterNone; + +impl<'a> FromRawParameter<'a> for ParameterNone { + unsafe fn from_raw(raw_type: RawParamType, _raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::None)?; + Ok(Self) + } +} diff --git a/crates/optee-utee/src/parameter/value.rs b/crates/optee-utee/src/parameter/value.rs new file mode 100644 index 0000000..22734f0 --- /dev/null +++ b/crates/optee-utee/src/parameter/value.rs @@ -0,0 +1,143 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Type-safe wrappers for TEE value-type parameters. +//! +//! A *value* parameter carries two `u32` fields (`a` and `b`) rather than a +//! shared memory buffer. +//! +//! This module provides: +//! +//! * [`ParameterValueRead`] / [`ParameterValueWrite`] traits for reading and +//! writing the two `u32` fields. +//! * Three concrete wrappers that encode the data direction in the type: +//! [`ParameterValueInput`], [`ParameterValueOutput`], +//! [`ParameterValueInout`]. +//! +//! # Direction guarantees +//! +//! | Type | Host → TA | TA → Host | +//! |---|---|---| +//! | `ParameterValueInput` | ✓ | ✗ | +//! | `ParameterValueOutput` | ✗ | ✓ | +//! | `ParameterValueInout` | ✓ | ✓ | + +use super::{FromRawParameter, ParamType, RawParamType, check_type_is}; +use crate::{Result, raw::TEE_Param}; + +/// Read-only access to the two `u32` fields of a value parameter. +/// +/// Implemented by [`ParameterValueInput`] and [`ParameterValueInout`]. +pub trait ParameterValueRead { + /// Returns the `a` field. + fn get_a(&self) -> u32; + /// Returns the `b` field. + fn get_b(&self) -> u32; +} + +/// Write access to the two `u32` fields of a value parameter. +/// +/// Implemented by [`ParameterValueOutput`] and [`ParameterValueInout`]. +/// Values written here will be read back by the host after the TA invocation +/// completes. +pub trait ParameterValueWrite { + /// Set the `a` field. + fn set_a(&mut self, a: u32); + /// Set the `b` field. + fn set_b(&mut self, b: u32); +} + +/// A value-type input parameter. +/// +/// The two `u32` values are copied out of the raw union at construction time, +pub struct ParameterValueInput { + a: u32, + b: u32, +} + +/// A value-type output parameter. +/// +/// Holds a mutable reference into the raw `TEE_Param` union. Values written +/// via [`ParameterValueWrite`] will be propagated back to the host. +pub struct ParameterValueOutput<'a>(&'a mut TEE_Param); + +/// A value-type in/out parameter. +/// +/// Combines the semantics of both [`ParameterValueInput`] and +/// [`ParameterValueOutput`]: the host initializes the values, and the TA may +/// both read and write them. +pub struct ParameterValueInout<'a>(&'a mut TEE_Param); + +impl<'a> FromRawParameter<'a> for ParameterValueInput { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::ValueInput)?; + Ok(Self { + a: unsafe { raw_param.value.a }, + b: unsafe { raw_param.value.b }, + }) + } +} + +impl<'a> FromRawParameter<'a> for ParameterValueOutput<'a> { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::ValueOutput)?; + Ok(Self(raw_param)) + } +} + +impl<'a> FromRawParameter<'a> for ParameterValueInout<'a> { + unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut TEE_Param) -> Result<Self> { + check_type_is(raw_type, ParamType::ValueInout)?; + Ok(Self(raw_param)) + } +} + +impl ParameterValueRead for ParameterValueInput { + fn get_a(&self) -> u32 { + self.a + } + fn get_b(&self) -> u32 { + self.b + } +} + +impl<'a> ParameterValueRead for ParameterValueInout<'a> { + fn get_a(&self) -> u32 { + unsafe { self.0.value.a } + } + fn get_b(&self) -> u32 { + unsafe { self.0.value.b } + } +} + +impl<'a> ParameterValueWrite for ParameterValueInout<'a> { + fn set_a(&mut self, a: u32) { + self.0.value.a = a; + } + fn set_b(&mut self, b: u32) { + self.0.value.b = b; + } +} + +impl<'a> ParameterValueWrite for ParameterValueOutput<'a> { + fn set_a(&mut self, a: u32) { + self.0.value.a = a; + } + fn set_b(&mut self, b: u32) { + self.0.value.b = b; + } +} diff --git a/crates/optee-utee/src/tee_parameter.rs b/crates/optee-utee/src/tee_parameter.rs index bce51c6..c01ebe0 100644 --- a/crates/optee-utee/src/tee_parameter.rs +++ b/crates/optee-utee/src/tee_parameter.rs @@ -109,7 +109,7 @@ impl<'a> Param<'a> { } fn get_raw_type(&self) -> u32 { - self.get_type() as u32 + self.get_type().into() } fn as_raw(&mut self) -> raw::TEE_Param { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
