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]

Reply via email to