|
| 1 | +--- |
| 2 | +permalink: /trustzone-sdk-docs/writing-rust-tas-using-optee-utee-build.md |
| 3 | +--- |
| 4 | + |
| 5 | +Currently we provide a `optee-utee-build` crate to simplify the compilcated building process of TA, and we recommend everyone use it in future developement. |
| 6 | + |
| 7 | +# Minimal Example |
| 8 | +Assuming currently we are developing a `hello_world` TA, and we want to build it with `optee-utee-build` crate, we can do it by following steps. |
| 9 | + |
| 10 | +Firstly, we should add `optee-utee-build` in `build-dependencies`: |
| 11 | +```shell |
| 12 | +cargo add --build optee-utee-build |
| 13 | +``` |
| 14 | + |
| 15 | +Secondly, we set a `ta_config` and call `optee-utee-build::build` with it in build.rs: |
| 16 | +```rust |
| 17 | +use proto; |
| 18 | +use optee_utee_build::{TAConfig, Error, RustEdition}; |
| 19 | + |
| 20 | +fn main() -> Result<(), Error> { |
| 21 | + let ta_config = TAConfig::new_standard_with_cargo_env(proto::UUID)?; |
| 22 | + optee_utee_build::build(RustEdition::Before2024, ta_config) |
| 23 | +} |
| 24 | +``` |
| 25 | +It will generate a `user_ta_header.rs` file and setup all the required configurations of the linker of rustc. |
| 26 | + |
| 27 | +Finally, we include the generated `user_ta_header.rs` in the source codes, normally we put it in `src/main.rs` |
| 28 | +```rust |
| 29 | +// src/main.rs |
| 30 | +include!(concat!(env!("OUT_DIR"), "/user_ta_header.rs")); |
| 31 | +``` |
| 32 | +After that, everything finished, we can start building the TA now. |
| 33 | + |
| 34 | +For full codes, you can check the [`hello_world-rs example`](https://github.com/apache/incubator-teaclave-trustzone-sdk/tree/main/examples/hello_world-rs/ta) |
| 35 | + |
| 36 | +# Explaination of Minimal Example |
| 37 | + |
| 38 | +### 1. The TAConfig |
| 39 | + |
| 40 | +This is a struct that use for the configuration of the TA we are developing, it has some public fields: |
| 41 | + |
| 42 | +|Field Name|Description| |
| 43 | +|----|----| |
| 44 | +|uuid|the identifier of current TA| |
| 45 | +|ta_flags|combination of some bitflags, check [this](https://github.com/OP-TEE/optee_os/blob/c2e42a8f03a5bb6b894ef85ae409f54760c1f50e/lib/libutee/include/user_ta_header.h#L13-L53) for available values| |
| 46 | +|ta_data_size|defines the size in bytes of the TA allocation pool| |
| 47 | +|ta_stack_size|defines the size in bytes of the stack used for TA execution| |
| 48 | +|ta_version|a version string of current TA, should be in semver format| |
| 49 | +|ta_description|the desciption of current TA| |
| 50 | +|trace_level|the default trace level of current TA, check [this](https://github.com/OP-TEE/optee_os/blob/c2e42a8f03a5bb6b894ef85ae409f54760c1f50e/lib/libutils/ext/include/trace_levels.h#L26-L31) for available values| |
| 51 | +|trace_ext|an extra prefix string when output trace log| |
| 52 | +|ta_framework_stack_size|defines the size in bytes of the stack used for Trusted Core Framework, currently used for trace framework and invoke command, should not be less than 2048| |
| 53 | +|ext_properties|the extra custom properties that will be added| |
| 54 | + |
| 55 | +We can construct the `TAConfig` by providing all of the public fields manually, or use our standard constructor. |
| 56 | +|Constructor|Description| |
| 57 | +|----|----| |
| 58 | +|new_standard|construct a standard TAConfig by providing uuid, ta_version and ta_description, with other configurations set to suggested values, you can update those configurations later| |
| 59 | +|new_standard_with_cargo_env|it's a constructor wrapped with new_standard, but take `version` and `description` from cargo.toml so simply providing a uuid as parameter is enough| |
| 60 | +### 2. The RustEdition |
| 61 | + |
| 62 | +The generated `user_ta_header.rs` must be different between `edition of 2024` and `edition before 2024`, and currently there is no official stable way to know what edition we are compiling with, so we provide a argument to set with. |
| 63 | + |
| 64 | +> #### What’s the difference? |
| 65 | +> the generated `user_ta_header.rs` file include some const variables and methods tagged with `no_mangle` and `link_section`, start from rust edition of 2024, they must be wrapped with unsafe, or rustc will output a compilation error(while before edition of 2024 it must not, or rustc will output a syntax error) |
| 66 | +
|
| 67 | +# Customization |
| 68 | + |
| 69 | +`optee-utee-build` provide some structs for flexible use. |
| 70 | + |
| 71 | +### 1. Builder |
| 72 | +Expect calling `build` function directly, you can also use Builder for customization. |
| 73 | + |
| 74 | +Usage: |
| 75 | +```Rust |
| 76 | +use proto; |
| 77 | +use optee_utee_build::{TAConfig, Builder, Error, RustEdition, LinkType}; |
| 78 | + |
| 79 | +fn main() -> Result<(), Error> { |
| 80 | + let ta_config = TAConfig::new_standard_with_cargo_env(proto::UUID)?; |
| 81 | + Builder::new(RustEdition::Before2024, ta_config) |
| 82 | + .out_dir("/tmp") |
| 83 | + .header_file_name("my_generated_user_ta_header.rs") |
| 84 | + .link_type(LinkType::CC) |
| 85 | + .build() |
| 86 | +} |
| 87 | +``` |
| 88 | +As you can see from the codes, there are some customizations of the builder: |
| 89 | +|Configuration|Description| |
| 90 | +|----|----| |
| 91 | +|out_dir|change directory of output files, default to OUT_DIR by cargo| |
| 92 | +|header_file_name|change name of output header file. default to `user_ta_header.rs`| |
| 93 | +|link_type|set link_type manually. <br/>there are some difference in parameters in linkers between `CC` and `LD` types, for example, `--sort-section` in `CC` types of linkers changes to `-Wl,--sort-section`, we will try to detect current linker that cargo using, you can use this function to set it manually if you think our detection mismatch.| |
| 94 | + |
| 95 | +### 2. Linker |
| 96 | +For some developers who want to use a hand-written `user_ta_header.rs` and just want `optee-utee-build` to handle the building stuff only, they can use the `Linker`, otherwise, try `Builder` instead. |
| 97 | + |
| 98 | +Usage: |
| 99 | +``` rust |
| 100 | +use optee_utee_build::{Linker, Error}; |
| 101 | +use std::env; |
| 102 | + |
| 103 | +fn main() -> Result<(), Error> { |
| 104 | + let out_dir = env::var("OUT_DIR")?; |
| 105 | + Linker::auto().link_all(out_dir)?; |
| 106 | + Ok(()) |
| 107 | +} |
| 108 | +``` |
| 109 | +When linking manually, developers construct a `Linker` and calling the `link_all` method by providing the out_dir, and linker will generate some required files (link script, etc, used by linker) into out_dir and handle all the linking stuff. |
| 110 | + |
| 111 | +In above codes, we use `auto` to construct the linker, it will detect current linker that cargo using automatically, you can use `new` function to construct the linker manually if you think our detection mismatch. |
| 112 | +```rust |
| 113 | +use optee_utee_build::{Linker, Error, LinkType}; |
| 114 | +use std::env; |
| 115 | + |
| 116 | +fn main() -> Result<(), Error> { |
| 117 | + let out_dir = env::var("OUT_DIR")?; |
| 118 | + Linker::new(LinkerType::CC).link_all(out_dir)?; |
| 119 | + Ok(()) |
| 120 | +} |
| 121 | +``` |
| 122 | + |
| 123 | +### 3. HeaderFileGenerator |
| 124 | +For some developers who want to do the linking themselves and just want `optee-utee-build` to generate a header file only, they can use the `HeaderFileGenerator`, otherwise, try `Builder` instead. |
| 125 | + |
| 126 | +Usage: |
| 127 | +```rust |
| 128 | +use optee_utee_build::{HeaderFileGenerator, TAConfig, RustEdition, Error}; |
| 129 | + |
| 130 | +fn main() -> Result<(), Error> { |
| 131 | + const UUID: &str = "26509cec-4a2b-4935-87ab-762d89fbf0b0"; |
| 132 | + let ta_config = TAConfig::new_standard(UUID, "0.1.0", "example")?; |
| 133 | + let codes = HeaderFileGenerator::new(RustEdition::Before2024).generate(&ta_config)?; |
| 134 | + Ok(std::io::Write("/tmp/user_ta_header.rs", codes.as_bytes())?) |
| 135 | +} |
| 136 | + |
| 137 | +``` |
| 138 | + |
| 139 | +# Migration Guide |
| 140 | +For developers still using `const configuration values` in `src/main.rs` and `custom build scripts` in `build.rs` (described in [\[migrating-to-new-building-env\]](https://github.com/apache/incubator-teaclave-trustzone-sdk/blob/main/docs/migrating-to-new-building-env.md)), they can upgrade to `optee-utee-build` by following step: |
| 141 | + |
| 142 | +Firstly, add `optee-utee-build` as `build-dependencies`: |
| 143 | +```shell |
| 144 | +cargo add --build optee-utee-build |
| 145 | +``` |
| 146 | + |
| 147 | +Secondly, in `build.rs`, remove codes of `custom build scripts`, and use `optee_utee_build::build` instead: |
| 148 | +```rust |
| 149 | +// ... other imports |
| 150 | +use optee_utee_build::{TAConfig, Error} |
| 151 | + |
| 152 | +fn main() -> Result<(), Error> { |
| 153 | + // should customize the ta_config with the same as const configuration values in your src/main.rs |
| 154 | + let ta_config = TAConfig::new_standard_with_cargo_env(proto::UUID)? |
| 155 | + .ta_stack_size(10 * 1024); |
| 156 | + optee_utee_build::build(RustEdition::Before2024, ta_config)?; |
| 157 | + |
| 158 | + // ... other build scripts |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +Thirdly, remove `const configuration values` in `src/main.rs`, keep the line of `include user_ta_header.rs` |
| 163 | +```rust |
| 164 | +/// ... other codes in src/main.rs |
| 165 | + |
| 166 | +/* remove const configuration values, move them to TAConfig in src/main.rs |
| 167 | +// TA configurations |
| 168 | +const TA_FLAGS: u32 = 0; |
| 169 | +const TA_DATA_SIZE: u32 = 32 * 1024; |
| 170 | +const TA_STACK_SIZE: u32 = 2 * 1024; |
| 171 | +const TA_VERSION: &[u8] = b"0.1\0"; |
| 172 | +const TA_DESCRIPTION: &[u8] = b"This is a hello world example.\0"; |
| 173 | +const EXT_PROP_VALUE_1: &[u8] = b"Hello World TA\0"; |
| 174 | +const EXT_PROP_VALUE_2: u32 = 0x0010; |
| 175 | +const TRACE_LEVEL: i32 = 4; |
| 176 | +const TRACE_EXT_PREFIX: &[u8] = b"TA\0"; |
| 177 | +const TA_FRAMEWORK_STACK_SIZE: u32 = 2048; |
| 178 | +*/ |
| 179 | + |
| 180 | +include!(concat!(env!("OUT_DIR"), "/user_ta_header.rs")); // keep this line |
| 181 | +``` |
| 182 | +Finally, delete the useless `ta_static.rs` and start building now. |
| 183 | + |
0 commit comments