diff --git a/litebox_common_optee/src/lib.rs b/litebox_common_optee/src/lib.rs index 66a24be35..234080651 100644 --- a/litebox_common_optee/src/lib.rs +++ b/litebox_common_optee/src/lib.rs @@ -2025,7 +2025,7 @@ impl From<&OpteeSmcArgsPage> for OpteeSmcArgs { /// OP-TEE SMC call arguments. #[derive(Clone, Copy, Default, FromBytes)] pub struct OpteeSmcArgs { - args: [usize; Self::NUM_OPTEE_SMC_ARGS], + pub args: [usize; Self::NUM_OPTEE_SMC_ARGS], } impl OpteeSmcArgs { @@ -2050,6 +2050,19 @@ impl OpteeSmcArgs { } } + /// Get the shared memory reference and offset for the physical address of `OpteeMsgArgs`. + pub fn optee_regd_shm_ref_and_offset(&self) -> Result<(u64, usize), OpteeSmcReturnCode> { + // args[1]:args[2] contains the shared memory reference (pointer) + // and args[3] contains the offset within that shared memory. + if self.args[1] & 0xffff_ffff_0000_0000 == 0 && self.args[2] & 0xffff_ffff_0000_0000 == 0 { + let shm_ref = (self.args[1] << 32) | self.args[2]; + let offset = self.args[3]; + Ok((shm_ref as u64, offset)) + } else { + Err(OpteeSmcReturnCode::EBadAddr) + } + } + /// Set the return code of an OP-TEE SMC call pub fn set_return_code(&mut self, code: OpteeSmcReturnCode) { self.args[0] = code as usize; @@ -2121,6 +2134,7 @@ pub enum OpteeSmcResult<'a> { CallWithArg { msg_args: Box, rpc_args: Option>, + msg_args_phys_addr: u64, }, } diff --git a/litebox_runner_lvbs/src/lib.rs b/litebox_runner_lvbs/src/lib.rs index ed6302601..ffe2a040d 100644 --- a/litebox_runner_lvbs/src/lib.rs +++ b/litebox_runner_lvbs/src/lib.rs @@ -417,10 +417,6 @@ fn optee_smc_handler(smc_args_addr: usize) -> OpteeSmcArgs { let Ok(mut smc_args) = (unsafe { smc_args_ptr.read_at_offset(0) }) else { return make_error_response(OpteeSmcReturnCode::EBadAddr); }; - let Ok(msg_args_phys_addr) = smc_args.optee_msg_args_phys_addr() else { - smc_args.set_return_code(OpteeSmcReturnCode::EBadAddr); - return *smc_args; - }; let Ok(smc_result) = handle_optee_smc_args(&mut smc_args) else { smc_args.set_return_code(OpteeSmcReturnCode::EBadCmd); return *smc_args; @@ -428,6 +424,7 @@ fn optee_smc_handler(smc_args_addr: usize) -> OpteeSmcArgs { if let OpteeSmcResult::CallWithArg { msg_args, rpc_args: _, + msg_args_phys_addr, } = smc_result { let mut msg_args = *msg_args; diff --git a/litebox_shim_optee/src/msg_handler.rs b/litebox_shim_optee/src/msg_handler.rs index f0c70acf7..5ca6243aa 100644 --- a/litebox_shim_optee/src/msg_handler.rs +++ b/litebox_shim_optee/src/msg_handler.rs @@ -185,13 +185,38 @@ pub fn handle_optee_smc_args( Ok(OpteeSmcResult::CallWithArg { msg_args, rpc_args: None, + msg_args_phys_addr: msg_args_addr as u64, }) } - OpteeSmcFunction::CallWithRpcArg | OpteeSmcFunction::CallWithRegdArg => { + OpteeSmcFunction::CallWithRpcArg => { let msg_args_addr = smc.optee_msg_args_phys_addr()?; let msg_args_addr: usize = msg_args_addr.truncate(); let (msg_args, rpc_args) = read_optee_msg_args_from_phys(msg_args_addr, true)?; - Ok(OpteeSmcResult::CallWithArg { msg_args, rpc_args }) + Ok(OpteeSmcResult::CallWithArg { + msg_args, + rpc_args, + msg_args_phys_addr: msg_args_addr as u64, + }) + } + OpteeSmcFunction::CallWithRegdArg => { + // `OpteeMsgArgs` is located at the offset specified in args[3] within the shared memory region pointed by args[1]:args[2]. + let (shm_ref, offset) = smc.optee_regd_shm_ref_and_offset()?; + let shm_info = shm_ref_map() + .get(shm_ref) + .ok_or(OpteeSmcReturnCode::EBadAddr)?; + let page_index = (shm_info.page_offset + offset) / PAGE_SIZE; + let offset_in_page = (shm_info.page_offset + offset) % PAGE_SIZE; + if page_index >= shm_info.page_addrs.len() { + return Err(OpteeSmcReturnCode::EBadAddr); + } + let msg_args_addr = shm_info.page_addrs[page_index].as_usize() + offset_in_page; + + let (msg_args, rpc_args) = read_optee_msg_args_from_phys(msg_args_addr, true)?; + Ok(OpteeSmcResult::CallWithArg { + msg_args, + rpc_args, + msg_args_phys_addr: msg_args_addr as u64, + }) } OpteeSmcFunction::ExchangeCapabilities => { // TODO: update the below when we support more features