1use crate::Error;
19use crate::{PropertyValue, TaConfig};
20use quote::{format_ident, quote};
21use std::str::FromStr;
22
23#[derive(Clone)]
25pub enum RustEdition {
26 Before2024,
27 Edition2024,
28}
29
30pub struct HeaderFileGenerator {
47 code: proc_macro2::TokenStream,
48 edition: RustEdition,
49}
50
51impl HeaderFileGenerator {
52 pub fn new(edition: RustEdition) -> Self {
53 Self {
54 code: quote!(),
55 edition,
56 }
57 }
58 pub fn generate(mut self, conf: &TaConfig) -> Result<String, Error> {
59 self.write_includes();
60 self.write_configurations(conf);
61 self.write_trace(conf);
62 self.write_properties(conf)?;
63 self.write_ta_head(conf)?;
64 self.write_ta_heap();
65
66 const LICENSE_STR: &str = include_str!("./license_str.txt");
67 let f = syn::parse2(self.code).unwrap();
68 let code_string = format!("{}\n{}", LICENSE_STR, prettyplease::unparse(&f));
72 Ok(code_string)
73 }
74}
75
76impl HeaderFileGenerator {
77 fn write_includes(&mut self) {
78 self.code.extend(quote! {
79 use core::ffi::*;
80 use core::mem;
81 use core::primitive::u64;
82 });
83 }
84
85 fn write_trace(&mut self, conf: &TaConfig) {
86 let trace_ext = string_to_binary_codes(&conf.trace_ext_prefix);
87 let trace_level = conf.trace_level;
88 let no_mangle_attribute = self.edition.no_mangle_attribute_codes();
89 self.code.extend(quote! {
90 #no_mangle_attribute
91 pub static mut trace_level: c_int = #trace_level;
92
93 #no_mangle_attribute
94 pub static trace_ext_prefix: &[u8] = #trace_ext;
95
96 #no_mangle_attribute
100 pub unsafe extern "C" fn tahead_get_trace_level() -> c_int {
101 unsafe { trace_level }
102 }
103 })
104 }
105 fn write_configurations(&mut self, conf: &TaConfig) {
106 let ta_version = string_to_binary_codes(&conf.ta_version);
107 let ta_description = string_to_binary_codes(&conf.ta_description);
108 let ta_flags = conf.ta_flags;
109 let ta_data_size = conf.ta_data_size;
110 let ta_stack_size = conf.ta_stack_size;
111 self.code.extend(quote! {
112 const TA_FLAGS: u32 = #ta_flags;
113 const TA_DATA_SIZE: u32 = #ta_data_size;
114 const TA_STACK_SIZE: u32 = #ta_stack_size;
115 const TA_VERSION: &[u8] = #ta_version;
116 const TA_DESCRIPTION: &[u8] = #ta_description;
117 });
118 }
119 fn write_properties(&mut self, conf: &TaConfig) -> Result<(), Error> {
120 let mut ext_property_codes =
121 Vec::<proc_macro2::TokenStream>::with_capacity(conf.ext_properties.len());
122 for (index, prop) in conf.ext_properties.iter().enumerate() {
123 let var_name = format!("EXT_PROP_VALUE_{}", index + 1);
124 let rust_type_name_codes = property_value_rust_type_declaration_codes(&prop.value);
125 let value_codes = property_value_data_codes(&prop.value)?;
126 let var_name_codes = format_ident!("{}", var_name);
127 self.code.extend(quote! {
128 const #var_name_codes: #rust_type_name_codes = #value_codes;
129 });
130 let prop_name_codes = string_to_binary_codes(&prop.name);
131 let utee_type_name_codes = property_value_utee_type_codes(&prop.value);
132 let utee_value_conv_codes = property_value_as_utee_value_codes(&var_name, &prop.value);
133 ext_property_codes.push(quote! {
134 optee_utee_sys::user_ta_property {
135 name: #prop_name_codes.as_ptr(),
136 prop_type: #utee_type_name_codes,
137 value: #utee_value_conv_codes,
138 }
139 });
140 }
141
142 const ORIGIN_PROPERTY_LEN: usize = 7;
143 let property_len = ORIGIN_PROPERTY_LEN + conf.ext_properties.len();
144 let no_mangle_attribute = self.edition.no_mangle_attribute_codes();
145 self.code.extend(quote! {
146 static FLAG_BOOL: bool = (TA_FLAGS & optee_utee_sys::TA_FLAG_SINGLE_INSTANCE) != 0;
147 static FLAG_MULTI: bool = (TA_FLAGS & optee_utee_sys::TA_FLAG_MULTI_SESSION) != 0;
148 static FLAG_INSTANCE: bool = (TA_FLAGS & optee_utee_sys::TA_FLAG_INSTANCE_KEEP_ALIVE) != 0;
149 #no_mangle_attribute
150 pub static ta_num_props: usize = #property_len;
151 #no_mangle_attribute
152 pub static ta_props: [optee_utee_sys::user_ta_property; #property_len] = [
153 optee_utee_sys::user_ta_property {
154 name: optee_utee_sys::TA_PROP_STR_SINGLE_INSTANCE,
155 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_BOOL,
156 value: &FLAG_BOOL as *const bool as *mut _,
157 },
158 optee_utee_sys::user_ta_property {
159 name: optee_utee_sys::TA_PROP_STR_MULTI_SESSION,
160 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_BOOL,
161 value: &FLAG_MULTI as *const bool as *mut _,
162 },
163 optee_utee_sys::user_ta_property {
164 name: optee_utee_sys::TA_PROP_STR_KEEP_ALIVE,
165 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_BOOL,
166 value: &FLAG_INSTANCE as *const bool as *mut _,
167 },
168 optee_utee_sys::user_ta_property {
169 name: optee_utee_sys::TA_PROP_STR_DATA_SIZE,
170 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_U32,
171 value: &TA_DATA_SIZE as *const u32 as *mut _,
172 },
173 optee_utee_sys::user_ta_property {
174 name: optee_utee_sys::TA_PROP_STR_STACK_SIZE,
175 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_U32,
176 value: &TA_STACK_SIZE as *const u32 as *mut _,
177 },
178 optee_utee_sys::user_ta_property {
179 name: optee_utee_sys::TA_PROP_STR_VERSION,
180 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_STRING,
181 value: TA_VERSION as *const [u8] as *mut _,
182 },
183 optee_utee_sys::user_ta_property {
184 name: optee_utee_sys::TA_PROP_STR_DESCRIPTION,
185 prop_type: optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_STRING,
186 value: TA_DESCRIPTION as *const [u8] as *mut _,
187 },
188 #(#ext_property_codes),*
189 ];
190 });
191
192 Ok(())
193 }
194 fn write_ta_head(&mut self, conf: &TaConfig) -> Result<(), Error> {
195 let uuid_value_codes = uuid_to_tee_uuid_value_codes(&conf.uuid)?;
196 let stack_size = conf.ta_stack_size + conf.ta_framework_stack_size;
197 let no_mangle_attribute = self.edition.no_mangle_attribute_codes();
198 let ta_head_session_attribute = self.edition.link_section_attribute_codes(".ta_head");
199 self.code.extend(quote! {
200 #no_mangle_attribute
201 #ta_head_session_attribute
202 pub static ta_head: optee_utee_sys::ta_head = optee_utee_sys::ta_head {
203 uuid: #uuid_value_codes,
204 stack_size: #stack_size,
205 flags: TA_FLAGS,
206 depr_entry: u64::MAX,
207 };
208 });
209
210 Ok(())
211 }
212 fn write_ta_heap(&mut self) {
213 let no_mangle_attribute = self.edition.no_mangle_attribute_codes();
214 let bss_session_attribute = self.edition.link_section_attribute_codes(".bss");
215 self.code.extend(quote! {
216 #no_mangle_attribute
217 #bss_session_attribute
218 pub static ta_heap: [u8; TA_DATA_SIZE as usize] = [0; TA_DATA_SIZE as usize];
219
220 #no_mangle_attribute
221 pub static ta_heap_size: usize = mem::size_of::<u8>() * TA_DATA_SIZE as usize;
222 })
223 }
224}
225
226fn property_value_data_codes(value: &PropertyValue) -> Result<proc_macro2::TokenStream, Error> {
227 match value {
228 PropertyValue::U32(v) => Ok(quote! { #v }),
229 PropertyValue::U64(v) => Ok(quote! { #v }),
230 PropertyValue::Bool(v) => Ok(quote! { #v }),
231 PropertyValue::Uuid(v) => uuid_to_tee_uuid_value_codes(v),
232 PropertyValue::Str(v) => Ok(string_to_binary_codes(v)),
233 PropertyValue::BinaryBlock(v) => Ok(string_to_binary_codes(v)),
234 PropertyValue::Identity(login, uuid) => {
235 identity_to_tee_identity_value_codes(login.clone(), &uuid)
236 }
237 }
238}
239
240fn uuid_to_tee_uuid_value_codes(uuid: &uuid::Uuid) -> Result<proc_macro2::TokenStream, Error> {
241 let (time_low, time_mid, time_hi_and_version, clock_seq_and_node) = uuid.as_fields();
242 Ok(quote! {
243 optee_utee_sys::TEE_UUID {
244 timeLow: #time_low,
245 timeMid: #time_mid,
246 timeHiAndVersion: #time_hi_and_version,
247 clockSeqAndNode: [#(#clock_seq_and_node),* ],
248 }
249 })
250}
251
252fn identity_to_tee_identity_value_codes(
253 login: u32,
254 uuid: &uuid::Uuid,
255) -> Result<proc_macro2::TokenStream, Error> {
256 let tee_uuid_codes = uuid_to_tee_uuid_value_codes(uuid)?;
257 Ok(quote! {
258 optee_utee_sys::TEE_Identity {
259 login: #login,
260 uuid: #tee_uuid_codes,
261 }
262 })
263}
264
265fn property_value_rust_type_declaration_codes(value: &PropertyValue) -> proc_macro2::TokenStream {
266 proc_macro2::TokenStream::from_str(match value {
267 PropertyValue::U32(_) => "u32",
268 PropertyValue::U64(_) => "u64",
269 PropertyValue::Bool(_) => "bool",
270 PropertyValue::Uuid(_) => "optee_utee_sys::TEE_UUID",
271 PropertyValue::Str(_) => "&[u8]",
272 PropertyValue::BinaryBlock(_) => "&[u8]",
273 PropertyValue::Identity(..) => "optee_utee_sys::TEE_Identity",
274 })
275 .unwrap()
276}
277
278fn property_value_as_utee_value_codes(
279 var_name: &str,
280 value: &PropertyValue,
281) -> proc_macro2::TokenStream {
282 proc_macro2::TokenStream::from_str(
283 match value {
284 PropertyValue::U32(_) => format!("&{} as *const u32 as *mut _", var_name),
285 PropertyValue::U64(_) => format!("&{} as *const u64 as *mut _", var_name),
286 PropertyValue::Bool(_) => format!("&{} as *const bool as *mut _", var_name),
287 PropertyValue::Uuid(_) => {
288 format!("&{} as *const optee_utee_sys::TEE_UUID as *mut _", var_name)
289 }
290 PropertyValue::Str(_) => format!("{} as *const [u8] as *mut _", var_name),
291 PropertyValue::BinaryBlock(_) => format!("{} as *const [u8] as *mut _", var_name),
292 PropertyValue::Identity(..) => format!(
293 "&{} as *const optee_utee_sys::TEE_Identity as *mut _",
294 var_name
295 ),
296 }
297 .as_str(),
298 )
299 .unwrap()
300}
301
302fn property_value_utee_type_codes(value: &PropertyValue) -> proc_macro2::TokenStream {
303 proc_macro2::TokenStream::from_str(match value {
304 PropertyValue::U32(_) => "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_U32",
305 PropertyValue::U64(_) => "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_U64",
306 PropertyValue::Bool(_) => "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_BOOL",
307 PropertyValue::Uuid(_) => "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_UUID",
308 PropertyValue::Str(_) => "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_STRING",
309 PropertyValue::BinaryBlock(_) => {
310 "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_BINARY_BLOCK"
311 }
312 PropertyValue::Identity(..) => {
313 "optee_utee_sys::user_ta_prop_type::USER_TA_PROP_TYPE_IDENTITY"
314 }
315 })
316 .unwrap()
317}
318
319fn string_to_binary_codes(s: &str) -> proc_macro2::TokenStream {
320 let wrapped = format!("b\"{}\\0\"", s);
321 proc_macro2::TokenStream::from_str(&wrapped).unwrap()
322}
323
324impl RustEdition {
325 fn no_mangle_attribute_codes(&self) -> proc_macro2::TokenStream {
326 match self {
327 RustEdition::Before2024 => quote! { #[no_mangle] },
328 RustEdition::Edition2024 => quote! { #[unsafe(no_mangle)] },
329 }
330 }
331 fn link_section_attribute_codes(&self, session_name: &str) -> proc_macro2::TokenStream {
332 match self {
333 RustEdition::Before2024 => quote! { #[link_section = #session_name] },
334 RustEdition::Edition2024 => quote! { #[unsafe(link_section = #session_name)] },
335 }
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 #[test]
344 fn test_edition_before_2024() {
345 let uuid = "26509cec-4a2b-4935-87ab-762d89fbf0b0";
346 let conf = TaConfig::new_default(uuid, "0.1.0", "test_before_2024")
347 .unwrap()
348 .ta_data_size(1024 * 1024);
349 let generator = HeaderFileGenerator::new(RustEdition::Before2024);
350 let codes = generator.generate(&conf).unwrap();
351 let exp_result = include_str!("../test_files/test_edition_before_2024_result.rs");
352 assert_eq!(codes, exp_result);
353 }
354 #[test]
355 fn test_edition_2024() {
356 let uuid = "26509cec-4a2b-4935-87ab-762d89fbf0b0";
357 let conf = TaConfig::new_default(uuid, "0.1.0", "test_edition_2024").unwrap();
358 let generator = HeaderFileGenerator::new(RustEdition::Edition2024);
359 let codes = generator.generate(&conf).unwrap();
360 let exp_result = include_str!("../test_files/test_edition_2024_result.rs");
361 assert_eq!(codes, exp_result);
362 }
363}