Skip to content

Commit 30cace0

Browse files
committed
optee_teec: extension: fix macro errors
* Fix usage of Rust types as return values in FFI functions. * Standardize the function signature to require returning a Result. * Use inner functions in generated code to prevent unexpected early returns. * Fix example: supp_plugin-rs.
1 parent cf0f662 commit 30cace0

File tree

12 files changed

+119
-70
lines changed

12 files changed

+119
-70
lines changed

examples/supp_plugin-rs/host/src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use optee_teec::{Context, Operation, ParamTmpRef, Session, Uuid};
19-
use optee_teec::{ParamNone};
20-
use proto::{TA_UUID, Command};
18+
use optee_teec::{Context, ErrorKind, Operation, ParamNone, ParamTmpRef, Session, Uuid};
19+
use proto::{Command, TA_UUID};
2120

2221
fn ping_ta(session: &mut Session) -> optee_teec::Result<()> {
2322
let test_data = [0x36u8; 10];
@@ -34,7 +33,10 @@ fn ping_ta(session: &mut Session) -> optee_teec::Result<()> {
3433

3534
fn main() -> optee_teec::Result<()> {
3635
let mut ctx = Context::new()?;
37-
let uuid = Uuid::parse_str(TA_UUID).unwrap();
36+
let uuid = Uuid::parse_str(TA_UUID).map_err(|err| {
37+
println!("Invalid TA_UUID: {:?}", err);
38+
ErrorKind::BadParameters
39+
})?;
3840
let mut session = ctx.open_session(uuid)?;
3941

4042
ping_ta(&mut session)?;

examples/supp_plugin-rs/plugin/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ edition = "2018"
2828
libc = "0.2.48"
2929
proto = { path = "../proto" }
3030
optee-teec = { path = "../../../optee-teec" }
31-
optee-teec-sys = { path = "../../../optee-teec/optee-teec-sys" }
3231

33-
[build_dependencies]
32+
[build-dependencies]
3433
uuid = { version = "0.8" }
3534
proto = { path = "../proto" }
3635

examples/supp_plugin-rs/plugin/build.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use proto;
1918
use std::env;
2019
use std::fs::File;
2120
use std::io::Write;
22-
use std::path::{PathBuf};
21+
use std::path::PathBuf;
2322
use uuid::Uuid;
2423

2524
fn main() -> std::io::Result<()> {
@@ -33,7 +32,7 @@ fn main() -> std::io::Result<()> {
3332
write!(buffer, "\n")?;
3433
write!(
3534
buffer,
36-
"const PLUGIN_UUID_STRUCT: optee_teec_sys::TEEC_UUID = optee_teec_sys::TEEC_UUID {{
35+
"const PLUGIN_UUID_STRUCT: optee_teec::optee_teec_sys::TEEC_UUID = optee_teec::optee_teec_sys::TEEC_UUID {{
3736
timeLow: {:#x},
3837
timeMid: {:#x},
3938
timeHiAndVersion: {:#x},

examples/supp_plugin-rs/plugin/plugin_static.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
// under the License.
1717

1818
#[no_mangle]
19-
pub static mut plugin_method: PluginMethod = PluginMethod {
20-
name: plugin_name.as_ptr() as *const c_char,
19+
pub static mut plugin_method: optee_teec::PluginMethod = optee_teec::PluginMethod {
20+
name: plugin_name.as_ptr(),
2121
uuid: PLUGIN_UUID_STRUCT,
2222
init: _plugin_init,
2323
invoke: _plugin_invoke,

examples/supp_plugin-rs/plugin/src/lib.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,40 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use libc::{c_char};
19-
use optee_teec::{PluginMethod, PluginParameters};
20-
use optee_teec::{plugin_init, plugin_invoke};
21-
use proto::{PluginCommand};
18+
use optee_teec::{plugin_init, plugin_invoke, ErrorKind, PluginParameters};
19+
use proto::PluginCommand;
2220

2321
#[plugin_init]
24-
fn init() {
25-
println!("*plugin*: init");
22+
fn init() -> optee_teec::Result<()> {
23+
println!("*plugin*: init, version: {}", env!("CARGO_PKG_VERSION"));
24+
Ok(())
2625
}
2726

2827
#[plugin_invoke]
29-
fn invoke(params: &mut PluginParameters) {
28+
fn invoke(params: &mut PluginParameters) -> optee_teec::Result<()> {
3029
println!("*plugin*: invoke");
3130
match PluginCommand::from(params.cmd) {
3231
PluginCommand::Print => {
33-
println!("*plugin*: receive value: {:?} length {:?}", params.inout, params.inout.len());
32+
println!(
33+
"*plugin*: receive value: {:?} length {:?}",
34+
params.inout,
35+
params.inout.len()
36+
);
3437

35-
let send_slice: [u8;9] = [0x40;9];
38+
let send_slice: [u8; 9] = [0x40; 9];
3639
params.set_buf_from_slice(&send_slice)?;
37-
println!("*plugin*: send value: {:?} length {:?} to ta", send_slice, send_slice.len());
40+
println!(
41+
"*plugin*: send value: {:?} length {:?} to ta",
42+
send_slice,
43+
send_slice.len()
44+
);
45+
Ok(())
46+
}
47+
_ => {
48+
println!("Unsupported plugin command: {:?}", params.cmd);
49+
Err(ErrorKind::BadParameters.into())
3850
}
39-
_ => println!("Unsupported plugin command: {:?}", params.cmd),
4051
}
4152
}
4253

43-
4454
include!(concat!(env!("OUT_DIR"), "/plugin_static.rs"));

examples/supp_plugin-rs/proto/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub enum Command {
2727
}
2828

2929
// If Uuid::parse_str() returns an InvalidLength error, there may be an extra
30-
// newline in your uuid.txt file. You can remove it by running
30+
// newline in your uuid.txt file. You can remove it by running
3131
// `truncate -s 36 ta_uuid.txt`.
3232
pub const TA_UUID: &str = &include_str!("../../ta_uuid.txt");
3333

@@ -42,6 +42,6 @@ pub enum PluginCommand {
4242

4343
pub const PLUGIN_SUBCMD_NULL: u32 = 0xFFFFFFFF;
4444
// If Uuid::parse_str() returns an InvalidLength error, there may be an extra
45-
// newline in your uuid.txt file. You can remove it by running
45+
// newline in your uuid.txt file. You can remove it by running
4646
// `truncate -s 36 plugin_uuid.txt`.
4747
pub const PLUGIN_UUID: &str = &include_str!("../../plugin_uuid.txt");

examples/supp_plugin-rs/ta/build.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use proto;
19-
use optee_utee_build::{TaConfig, RustEdition, Error};
18+
use optee_utee_build::{Error, RustEdition, TaConfig};
2019

2120
fn main() -> Result<(), Error> {
2221
let ta_config = TaConfig::new_default_with_cargo_env(proto::TA_UUID)?;

examples/supp_plugin-rs/ta/src/main.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020

2121
extern crate alloc;
2222

23+
use optee_utee::LoadablePlugin;
2324
use optee_utee::{
2425
ta_close_session, ta_create, ta_destroy, ta_invoke_command, ta_open_session, trace_println,
2526
};
26-
use optee_utee::{Error, ErrorKind, Parameters, Result, Uuid};
27-
use optee_utee::{LoadablePlugin};
27+
use optee_utee::{ErrorKind, Parameters, Result, Uuid};
2828
use proto::{Command, PluginCommand, PLUGIN_SUBCMD_NULL, PLUGIN_UUID};
2929

3030
#[ta_create]
@@ -52,26 +52,32 @@ fn destroy() {
5252
#[ta_invoke_command]
5353
fn invoke_command(cmd_id: u32, params: &mut Parameters) -> Result<()> {
5454
trace_println!("[+] TA invoke command");
55-
let mut p0 = unsafe { params.0.as_memref().unwrap() };
55+
let mut p0 = unsafe { params.0.as_memref()? };
5656
let inbuf = p0.buffer().to_vec();
57-
trace_println!("[+] TA received value {:?} then send to plugin", p0.buffer());
58-
let uuid = Uuid::parse_str(PLUGIN_UUID).unwrap();
57+
trace_println!(
58+
"[+] TA received value {:?} then send to plugin",
59+
p0.buffer()
60+
);
61+
let uuid = Uuid::parse_str(PLUGIN_UUID).map_err(|err| {
62+
trace_println!("Invalid PluginUuid: {:?}", err);
63+
ErrorKind::BadParameters
64+
})?;
5965

6066
match Command::from(cmd_id) {
6167
Command::Ping => {
62-
let mut plugin = LoadablePlugin::new(&uuid);
63-
let outbuf = plugin.invoke(
64-
PluginCommand::Print as u32,
65-
PLUGIN_SUBCMD_NULL,
66-
&inbuf
67-
).unwrap();
68+
let plugin = LoadablePlugin::new(&uuid);
69+
let outbuf = plugin.invoke(PluginCommand::Print as u32, PLUGIN_SUBCMD_NULL, &inbuf)?;
6870

69-
trace_println!("[+] TA received out value {:?} outlen {:?}", outbuf, outbuf.len());
71+
trace_println!(
72+
"[+] TA received out value {:?} outlen {:?}",
73+
outbuf,
74+
outbuf.len()
75+
);
7076
trace_println!("[+] TA call invoke_supp_plugin finished");
7177

7278
Ok(())
7379
}
74-
_ => Err(Error::new(ErrorKind::BadParameters)),
80+
_ => Err(ErrorKind::BadParameters.into()),
7581
}
7682
}
7783

optee-teec/macros/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ edition = "2018"
2828
proc-macro = true
2929

3030
[dependencies]
31-
quote = "0.6"
32-
syn = { version = "0.15", features = ["full"] }
31+
quote = "1.0"
32+
syn = { version = "2.0", features = ["full"] }
3333

3434
# The newer versions of these crates require rustc 1.81, while our custom
3535
# patched STD version is 1.80, causing compatibility issues. To resolve this,

optee-teec/macros/src/lib.rs

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
extern crate proc_macro;
2121

2222
use proc_macro::TokenStream;
23-
use quote::quote;
23+
use quote::{quote, ToTokens};
2424
use syn::parse_macro_input;
2525
use syn::spanned::Spanned;
2626

@@ -34,38 +34,57 @@ pub fn plugin_init(_args: TokenStream, input: TokenStream) -> TokenStream {
3434
let f = parse_macro_input!(input as syn::ItemFn);
3535
let f_vis = &f.vis;
3636
let f_block = &f.block;
37-
let f_decl = &f.decl;
38-
let f_inputs = &f_decl.inputs;
37+
let f_sig = &f.sig;
38+
let f_inputs = &f_sig.inputs;
3939

4040
// check the function signature
41-
let valid_signature = f.constness.is_none()
41+
let valid_signature = f_sig.constness.is_none()
4242
&& match f_vis {
4343
syn::Visibility::Inherited => true,
4444
_ => false,
4545
}
46-
&& f.abi.is_none()
46+
&& f_sig.abi.is_none()
4747
&& f_inputs.len() == 0
48-
&& f.decl.generics.where_clause.is_none()
49-
&& f.decl.variadic.is_none();
48+
&& f_sig.generics.where_clause.is_none()
49+
&& f_sig.variadic.is_none()
50+
&& check_return_type(&f);
5051

5152
if !valid_signature {
5253
return syn::parse::Error::new(
5354
f.span(),
54-
"`#[plugin_init]` function must have signature `fn()`",
55+
"`#[plugin_init]` function must have signature `fn() -> optee_teec::Result<()>`",
5556
)
5657
.to_compile_error()
5758
.into();
5859
}
5960

6061
quote!(
6162
#[no_mangle]
62-
pub fn _plugin_init() -> optee_teec::Result<()> {
63-
#f_block
64-
Ok(())
63+
pub fn _plugin_init() -> optee_teec::optee_teec_sys::TEEC_Result {
64+
fn inner() -> optee_teec::Result<()> {
65+
#f_block
66+
}
67+
match inner() {
68+
Ok(()) => optee_teec::optee_teec_sys::TEEC_SUCCESS,
69+
Err(err) => err.raw_code(),
70+
}
6571
}
6672
)
6773
.into()
74+
}
6875

76+
// check if return_type of the function is `optee_teec::Result<()>`
77+
fn check_return_type(item_fn: &syn::ItemFn) -> bool {
78+
if let syn::ReturnType::Type(_, return_type) = item_fn.sig.output.to_owned() {
79+
if let syn::Type::Path(path) = return_type.as_ref() {
80+
let expected_type = quote! { optee_teec::Result<()> };
81+
let actual_type = path.path.to_token_stream();
82+
if expected_type.to_string() == actual_type.to_string() {
83+
return true;
84+
}
85+
}
86+
}
87+
return false;
6988
}
7089

7190
/// Attribute to declare the invoke function of a plugin
@@ -78,50 +97,62 @@ pub fn plugin_invoke(_args: TokenStream, input: TokenStream) -> TokenStream {
7897
let f = parse_macro_input!(input as syn::ItemFn);
7998
let f_vis = &f.vis;
8099
let f_block = &f.block;
81-
let f_decl = &f.decl;
82-
let f_inputs = &f_decl.inputs;
100+
let f_sig = &f.sig;
101+
let f_inputs = &f_sig.inputs;
83102

84103
// check the function signature
85-
let valid_signature = f.constness.is_none()
104+
let valid_signature = f_sig.constness.is_none()
86105
&& match f_vis {
87106
syn::Visibility::Inherited => true,
88107
_ => false,
89108
}
90-
&& f.abi.is_none()
109+
&& f_sig.abi.is_none()
91110
&& f_inputs.len() == 1
92-
&& f.decl.generics.where_clause.is_none()
93-
&& f.decl.variadic.is_none();
111+
&& f_sig.generics.where_clause.is_none()
112+
&& f_sig.variadic.is_none()
113+
&& check_return_type(&f);
94114

95115
if !valid_signature {
96116
return syn::parse::Error::new(
97117
f.span(),
98-
"`#[plugin_invoke]` function must have signature `fn(params: &mut PluginParamters)`",
118+
concat!(
119+
"`#[plugin_invoke]` function must have signature",
120+
" `fn(params: &mut PluginParameters) -> optee_teec::Result<()>`"
121+
),
99122
)
100123
.to_compile_error()
101124
.into();
102125
}
103126

127+
let params = f_inputs
128+
.first()
129+
.expect("we have already verified its len")
130+
.into_token_stream();
131+
104132
quote!(
105133
#[no_mangle]
106134
pub fn _plugin_invoke(
107135
cmd: u32,
108136
sub_cmd: u32,
109-
data: *mut c_char,
137+
data: *mut core::ffi::c_char,
110138
in_len: u32,
111139
out_len: *mut u32
112-
) -> optee_teec::Result<()> {
140+
) -> optee_teec::optee_teec_sys::TEEC_Result {
141+
fn inner(#params) -> optee_teec::Result<()> {
142+
#f_block
143+
}
113144
let mut inbuf = unsafe { std::slice::from_raw_parts_mut(data, in_len as usize) };
114-
let mut params = PluginParameters::new(cmd, sub_cmd, inbuf);
115-
#f_block
145+
let mut params = optee_teec::PluginParameters::new(cmd, sub_cmd, inbuf);
146+
if let Err(err) = inner(&mut params) {
147+
return err.raw_code();
148+
};
116149
let outslice = params.get_out_slice();
117150
unsafe {
118151
*out_len = outslice.len() as u32;
119152
std::ptr::copy(outslice.as_ptr(), data, outslice.len());
120-
}
121-
122-
Ok(())
153+
};
154+
return optee_teec::optee_teec_sys::TEEC_SUCCESS;
123155
}
124156
)
125157
.into()
126-
127158
}

0 commit comments

Comments
 (0)