1extern crate alloc;
19extern crate proc_macro;
20
21use proc_macro::TokenStream;
22use quote::quote;
23use syn::parse_macro_input;
24use syn::spanned::Spanned;
25
26#[proc_macro_attribute]
35pub fn ta_create(_args: TokenStream, input: TokenStream) -> TokenStream {
36 let f = parse_macro_input!(input as syn::ItemFn);
37 let f_sig = &f.sig;
38 let f_ident = &f_sig.ident;
39
40 let valid_signature = f_sig.constness.is_none()
42 && matches!(f.vis, syn::Visibility::Inherited)
43 && f_sig.abi.is_none()
44 && f_sig.inputs.is_empty()
45 && f_sig.generics.where_clause.is_none()
46 && f_sig.variadic.is_none();
47
48 if !valid_signature {
49 return syn::parse::Error::new(
50 f.span(),
51 "`#[ta_crate]` function must have signature `fn() -> optee_utee::Result<()>`",
52 )
53 .to_compile_error()
54 .into();
55 }
56
57 quote!(
58 #[unsafe(no_mangle)]
59 pub extern "C" fn TA_CreateEntryPoint() -> optee_utee_sys::TEE_Result {
60 match #f_ident() {
61 Ok(_) => optee_utee_sys::TEE_SUCCESS,
62 Err(e) => e.raw_code()
63 }
64 }
65
66 #f
67 )
68 .into()
69}
70
71#[proc_macro_attribute]
80pub fn ta_destroy(_args: TokenStream, input: TokenStream) -> TokenStream {
81 let f = parse_macro_input!(input as syn::ItemFn);
82 let f_sig = &f.sig;
83 let f_ident = &f_sig.ident;
84
85 let valid_signature = f_sig.constness.is_none()
87 && matches!(f.vis, syn::Visibility::Inherited)
88 && f_sig.abi.is_none()
89 && f_sig.inputs.is_empty()
90 && f_sig.generics.where_clause.is_none()
91 && f_sig.variadic.is_none()
92 && matches!(f_sig.output, syn::ReturnType::Default);
93
94 if !valid_signature {
95 return syn::parse::Error::new(
96 f.span(),
97 "`#[ta_destroy]` function must have signature `fn()`",
98 )
99 .to_compile_error()
100 .into();
101 }
102
103 quote!(
104 #[unsafe(no_mangle)]
105 pub extern "C" fn TA_DestroyEntryPoint() {
106 #f_ident()
107 }
108
109 #f
110 )
111 .into()
112}
113
114#[proc_macro_attribute]
129pub fn ta_open_session(_args: TokenStream, input: TokenStream) -> TokenStream {
130 let f = parse_macro_input!(input as syn::ItemFn);
131 let f_sig = &f.sig;
132 let f_ident = &f_sig.ident;
133
134 let valid_signature = f_sig.constness.is_none()
136 && matches!(f.vis, syn::Visibility::Inherited)
137 && f_sig.abi.is_none()
138 && (f_sig.inputs.len() == 1 || f_sig.inputs.len() == 2)
139 && f_sig.generics.where_clause.is_none()
140 && f_sig.variadic.is_none();
141
142 if !valid_signature {
143 return syn::parse::Error::new(
144 f.span(),
145 "`#[ta_open_session]` function must have signature `fn(&mut Parameters) -> Result<()>` or `fn(&mut Parameters, &mut T) -> Result<()>`",
146 )
147 .to_compile_error()
148 .into();
149 }
150
151 match f_sig.inputs.len() {
152 1 => quote!(
153 #[unsafe(no_mangle)]
154 pub extern "C" fn TA_OpenSessionEntryPoint(
155 param_types: optee_utee::RawParamTypes,
156 params: &mut optee_utee::RawParams,
157 _: *mut *mut core::ffi::c_void,
158 ) -> optee_utee_sys::TEE_Result {
159 let mut parameters = Parameters::from_raw(params, param_types);
160 match #f_ident(&mut parameters) {
161 Ok(_) => optee_utee_sys::TEE_SUCCESS,
162 Err(e) => e.raw_code()
163 }
164 }
165
166 #f
167 )
168 .into(),
169
170 2 => {
171 let ctx_type = match extract_fn_arg_mut_ref_type(&f_sig.inputs[1]) {
172 Ok(v) => v,
173 Err(e) => return e.to_compile_error().into(),
174 };
175
176 quote!(
177 #[unsafe(no_mangle)]
180 pub unsafe extern "C" fn TA_OpenSessionEntryPoint(
181 param_types: optee_utee::RawParamTypes,
182 params: &mut optee_utee::RawParams,
183 sess_ctx: *mut *mut core::ffi::c_void,
184 ) -> optee_utee_sys::TEE_Result {
185 let mut parameters = Parameters::from_raw(params, param_types);
186 let mut ctx: #ctx_type = Default::default();
187 match #f_ident(&mut parameters, &mut ctx) {
188 Ok(_) =>
189 {
190 *sess_ctx = Box::into_raw(Box::new(ctx)) as _;
191 optee_utee_sys::TEE_SUCCESS
192 }
193 Err(e) => e.raw_code()
194 }
195 }
196
197 #f
198 )
199 .into()
200 }
201 _ => unreachable!(),
202 }
203}
204
205#[proc_macro_attribute]
218pub fn ta_close_session(_args: TokenStream, input: TokenStream) -> TokenStream {
219 let f = parse_macro_input!(input as syn::ItemFn);
220 let f_sig = &f.sig;
221 let f_ident = &f_sig.ident;
222
223 let valid_signature = f_sig.constness.is_none()
225 && matches!(f.vis, syn::Visibility::Inherited)
226 && f_sig.abi.is_none()
227 && (f_sig.inputs.is_empty() || f_sig.inputs.len() == 1)
228 && f_sig.generics.where_clause.is_none()
229 && f_sig.variadic.is_none()
230 && matches!(f_sig.output, syn::ReturnType::Default);
231
232 if !valid_signature {
233 return syn::parse::Error::new(
234 f.span(),
235 "`#[ta_close_session]` function must have signature `fn(&mut T)` or `fn()`",
236 )
237 .to_compile_error()
238 .into();
239 }
240
241 match f_sig.inputs.len() {
242 0 => quote!(
243 #[unsafe(no_mangle)]
244 pub extern "C" fn TA_CloseSessionEntryPoint(_: *mut core::ffi::c_void) {
245 #f_ident()
246 }
247
248 #f
249 )
250 .into(),
251 1 => {
252 let ctx_type = match extract_fn_arg_mut_ref_type(&f_sig.inputs[0]) {
253 Ok(v) => v,
254 Err(e) => return e.to_compile_error().into(),
255 };
256
257 quote!(
258 #[unsafe(no_mangle)]
261 pub unsafe extern "C" fn TA_CloseSessionEntryPoint(sess_ctx: *mut core::ffi::c_void) {
262 if sess_ctx.is_null() {
263 panic!("sess_ctx is null");
264 }
265 let mut b = Box::from_raw(sess_ctx as *mut #ctx_type);
266 #f_ident(&mut b);
267 drop(b);
268 }
269
270 #f
271 )
272 .into()
273 }
274 _ => unreachable!(),
275 }
276}
277
278#[proc_macro_attribute]
291pub fn ta_invoke_command(_args: TokenStream, input: TokenStream) -> TokenStream {
292 let f = parse_macro_input!(input as syn::ItemFn);
293 let f_sig = &f.sig;
294 let f_ident = &f_sig.ident;
295
296 let valid_signature = f_sig.constness.is_none()
298 && matches!(f.vis, syn::Visibility::Inherited)
299 && f_sig.abi.is_none()
300 && (f_sig.inputs.len() == 2 || f_sig.inputs.len() == 3)
301 && f_sig.generics.where_clause.is_none()
302 && f_sig.variadic.is_none();
303
304 if !valid_signature {
305 return syn::parse::Error::new(
306 f.span(),
307 "`#[ta_invoke_command]` function must have signature `fn(&mut T, u32, &mut Parameters) -> Result<()>` or `fn(u32, &mut Parameters) -> Result<()>`",
308 )
309 .to_compile_error()
310 .into();
311 }
312
313 match f_sig.inputs.len() {
314 2 => quote!(
315 #[unsafe(no_mangle)]
316 pub extern "C" fn TA_InvokeCommandEntryPoint(
317 _: *mut core::ffi::c_void,
318 cmd_id: u32,
319 param_types: u32,
320 params: &mut optee_utee::RawParams,
321 ) -> optee_utee_sys::TEE_Result {
322 let mut parameters = Parameters::from_raw(params, param_types);
323 match #f_ident(cmd_id, &mut parameters) {
324 Ok(_) => {
325 optee_utee_sys::TEE_SUCCESS
326 },
327 Err(e) => e.raw_code()
328 }
329 }
330
331 #f
332 )
333 .into(),
334 3 => {
335 let ctx_type = match extract_fn_arg_mut_ref_type(&f_sig.inputs[0]) {
336 Ok(v) => v,
337 Err(e) => return e.to_compile_error().into(),
338 };
339
340 quote!(
341 #[unsafe(no_mangle)]
344 pub unsafe extern "C" fn TA_InvokeCommandEntryPoint(
345 sess_ctx: *mut core::ffi::c_void,
346 cmd_id: u32,
347 param_types: u32,
348 params: &mut optee_utee::RawParams,
349 ) -> optee_utee_sys::TEE_Result {
350 if sess_ctx.is_null() {
351 return optee_utee_sys::TEE_ERROR_SECURITY;
352 }
353 let mut parameters = Parameters::from_raw(params, param_types);
354 let mut b = Box::from_raw(sess_ctx as *mut #ctx_type);
355 match #f_ident(&mut b, cmd_id, &mut parameters) {
356 Ok(_) => {
357 core::mem::forget(b);
358 optee_utee_sys::TEE_SUCCESS
359 },
360 Err(e) => {
361 core::mem::forget(b);
362 e.raw_code()
363 }
364 }
365 }
366
367 #f
368 )
369 .into()
370 }
371 _ => unreachable!(),
372 }
373}
374
375fn extract_fn_arg_mut_ref_type(fn_arg: &syn::FnArg) -> Result<&syn::Type, syn::parse::Error> {
376 if let syn::FnArg::Typed(ty) = fn_arg
377 && let syn::Type::Reference(type_ref) = ty.ty.as_ref()
378 && type_ref.mutability.is_some()
379 {
380 return Ok(&*type_ref.elem);
381 };
382 Err(syn::parse::Error::new(
383 fn_arg.span(),
384 "this argument should have signature `_: &mut T`",
385 ))
386}