1Trusted Firmware-A Coding Guidelines 2==================================== 3 4 5 6.. contents:: 7 8The following sections contain TF coding guidelines. They are continually 9evolving and should not be considered "set in stone". Feel free to question them 10and provide feedback. 11 12Some of the guidelines may also apply to other codebases. 13 14**Note:** the existing TF codebase does not necessarily comply with all the 15below guidelines but the intent is for it to do so eventually. 16 17Checkpatch overrides 18-------------------- 19 20Some checkpatch warnings in the TF codebase are deliberately ignored. These 21include: 22 23- ``**WARNING: line over 80 characters**``: Although the codebase should 24 generally conform to the 80 character limit this is overly restrictive in some 25 cases. 26 27- ``**WARNING: Use of volatile is usually wrong``: see 28 `Why the “volatile” type class should not be used`_ . Although this document 29 contains some very useful information, there are several legimate uses of the 30 volatile keyword within the TF codebase. 31 32Headers and inclusion 33--------------------- 34 35Header guards 36^^^^^^^^^^^^^ 37 38For a header file called "some_driver.h" the style used by the Trusted Firmware 39is: 40 41.. code:: c 42 43 #ifndef SOME_DRIVER_H 44 #define SOME_DRIVER_H 45 46 <header content> 47 48 #endif /* SOME_DRIVER_H */ 49 50Include statement ordering 51^^^^^^^^^^^^^^^^^^^^^^^^^^ 52 53All header files that are included by a source file must use the following, 54grouped ordering. This is to improve readability (by making it easier to quickly 55read through the list of headers) and maintainability. 56 57#. *System* includes: Header files from the standard *C* library, such as 58 ``stddef.h`` and ``string.h``. 59 60#. *Project* includes: Header files under the ``include/`` directory within TF 61 are *project* includes. 62 63#. *Platform* includes: Header files relating to a single, specific platform, 64 and which are located under the ``plat/<platform_name>`` directory within TF, 65 are *platform* includes. 66 67Within each group, ``#include`` statements must be in alphabetical order, 68taking both the file and directory names into account. 69 70Groups must be separated by a single blank line for clarity. 71 72The example below illustrates the ordering rules using some contrived header 73file names; this type of name reuse should be otherwise avoided. 74 75.. code:: c 76 77 #include <string.h> 78 79 #include <a_dir/example/a_header.h> 80 #include <a_dir/example/b_header.h> 81 #include <a_dir/test/a_header.h> 82 #include <b_dir/example/a_header.h> 83 84 #include "./a_header.h" 85 86Include statement variants 87^^^^^^^^^^^^^^^^^^^^^^^^^^ 88 89Two variants of the ``#include`` directive are acceptable in the TF codebase. 90Correct use of the two styles improves readability by suggesting the location 91of the included header and reducing ambiguity in cases where generic and 92platform-specific headers share a name. 93 94For header files that are in the same directory as the source file that is 95including them, use the ``"..."`` variant. 96 97For header files that are **not** in the same directory as the source file that 98is including them, use the ``<...>`` variant. 99 100Example (bl1_fwu.c): 101 102.. code:: c 103 104 #include <assert.h> 105 #include <errno.h> 106 #include <string.h> 107 108 #include "bl1_private.h" 109 110Platform include paths 111^^^^^^^^^^^^^^^^^^^^^^ 112 113Platforms are allowed to add more include paths to be passed to the compiler. 114The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in 115particular for the file ``platform_def.h``. 116 117Example: 118 119.. code:: c 120 121 PLAT_INCLUDES += -Iinclude/plat/myplat/include 122 123Types and typedefs 124------------------ 125 126Use of built-in *C* and *libc* data types 127^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 128 129The TF codebase should be kept as portable as possible, especially since both 13064-bit and 32-bit platforms are supported. To help with this, the following data 131type usage guidelines should be followed: 132 133- Where possible, use the built-in *C* data types for variable storage (for 134 example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99* 135 types. Most code is typically only concerned with the minimum size of the 136 data stored, which the built-in *C* types guarantee. 137 138- Avoid using the exact-size standard *C99* types in general (for example, 139 ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the 140 compiler from making optimizations. There are legitimate uses for them, 141 for example to represent data of a known structure. When using them in struct 142 definitions, consider how padding in the struct will work across architectures. 143 For example, extra padding may be introduced in AArch32 systems if a struct 144 member crosses a 32-bit boundary. 145 146- Use ``int`` as the default integer type - it's likely to be the fastest on all 147 systems. Also this can be assumed to be 32-bit as a consequence of the 148 `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call 149 Standard for the Arm 64-bit Architecture`_ . 150 151- Avoid use of ``short`` as this may end up being slower than ``int`` in some 152 systems. If a variable must be exactly 16-bit, use ``int16_t`` or 153 ``uint16_t``. 154 155- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given 156 that `int` is 32-bit on Arm platforms, there is no use for it. For integers of 157 at least 64-bit, use ``long long``. 158 159- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data. 160 161- Use ``unsigned`` for integers that can never be negative (counts, 162 indices, sizes, etc). TF intends to comply with MISRA "essential type" coding 163 rules (10.X), where signed and unsigned types are considered different 164 essential types. Choosing the correct type will aid this. MISRA static 165 analysers will pick up any implicit signed/unsigned conversions that may lead 166 to unexpected behaviour. 167 168- For pointer types: 169 170 - If an argument in a function declaration is pointing to a known type then 171 simply use a pointer to that type (for example: ``struct my_struct *``). 172 173 - If a variable (including an argument in a function declaration) is pointing 174 to a general, memory-mapped address, an array of pointers or another 175 structure that is likely to require pointer arithmetic then use 176 ``uintptr_t``. This will reduce the amount of casting required in the code. 177 Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it 178 may work but is less portable. 179 180 - For other pointer arguments in a function declaration, use ``void *``. This 181 includes pointers to types that are abstracted away from the known API and 182 pointers to arbitrary data. This allows the calling function to pass a 183 pointer argument to the function without any explicit casting (the cast to 184 ``void *`` is implicit). The function implementation can then do the 185 appropriate casting to a specific type. 186 187 - Use ``ptrdiff_t`` to compare the difference between 2 pointers. 188 189- Use ``size_t`` when storing the ``sizeof()`` something. 190 191- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that 192 can also return an error code; the signed type allows for a negative return 193 code in case of error. This practice should be used sparingly. 194 195- Use ``u_register_t`` when it's important to store the contents of a register 196 in its native size (32-bit in AArch32 and 64-bit in AArch64). This is not a 197 standard *C99* type but is widely available in libc implementations, 198 including the FreeBSD version included with the TF codebase. Where possible, 199 cast the variable to a more appropriate type before interpreting the data. For 200 example, the following struct in ``ep_info.h`` could use this type to minimize 201 the storage required for the set of registers: 202 203.. code:: c 204 205 typedef struct aapcs64_params { 206 u_register_t arg0; 207 u_register_t arg1; 208 u_register_t arg2; 209 u_register_t arg3; 210 u_register_t arg4; 211 u_register_t arg5; 212 u_register_t arg6; 213 u_register_t arg7; 214 } aapcs64_params_t; 215 216If some code wants to operate on ``arg0`` and knows that it represents a 32-bit 217unsigned integer on all systems, cast it to ``unsigned int``. 218 219These guidelines should be updated if additional types are needed. 220 221Avoid anonymous typedefs of structs/enums in headers 222^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 223 224For example, the following definition: 225 226.. code:: c 227 228 typedef struct { 229 int arg1; 230 int arg2; 231 } my_struct_t; 232 233 234is better written as: 235 236.. code:: c 237 238 struct my_struct { 239 int arg1; 240 int arg2; 241 }; 242 243This allows function declarations in other header files that depend on the 244struct/enum to forward declare the struct/enum instead of including the 245entire header: 246 247.. code:: c 248 249 #include <my_struct.h> 250 void my_func(my_struct_t *arg); 251 252instead of: 253 254.. code:: c 255 256 struct my_struct; 257 void my_func(struct my_struct *arg); 258 259Some TF definitions use both a struct/enum name **and** a typedef name. This 260is discouraged for new definitions as it makes it difficult for TF to comply 261with MISRA rule 8.3, which states that "All declarations of an object or 262function shall use the same names and type qualifiers". 263 264The Linux coding standards also discourage new typedefs and checkpatch emits 265a warning for this. 266 267Existing typedefs will be retained for compatibility. 268 269Error handling and robustness 270----------------------------- 271 272Using CASSERT to check for compile time data errors 273^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 274 275Where possible, use the ``CASSERT`` macro to check the validity of data known at 276compile time instead of checking validity at runtime, to avoid unnecessary 277runtime code. 278 279For example, this can be used to check that the assembler's and compiler's views 280of the size of an array is the same. 281 282.. code:: c 283 284 #include <cassert.h> 285 286 define MY_STRUCT_SIZE 8 /* Used by assembler source files */ 287 288 struct my_struct { 289 uint32_t arg1; 290 uint32_t arg2; 291 }; 292 293 CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch); 294 295 296If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would 297emit an error like this: 298 299.. code:: c 300 301 my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative 302 303 304Using assert() to check for programming errors 305^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 306 307In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be 308treated as a tightly integrated package; the image builder should be aware of 309and responsible for all functionality within the image, even if code within that 310image is provided by multiple entities. This allows us to be more aggressive in 311interpreting invalid state or bad function arguments as programming errors using 312``assert()``, including arguments passed across platform porting interfaces. 313This is in contrast to code in a Linux environment, which is less tightly 314integrated and may attempt to be more defensive by passing the error back up the 315call stack. 316 317Where possible, badly written TF code should fail early using ``assert()``. This 318helps reduce the amount of untested conditional code. By default these 319statements are not compiled into release builds, although this can be overridden 320using the ``ENABLE_ASSERTIONS`` build flag. 321 322Examples: 323 324- Bad argument supplied to library function 325- Bad argument provided by platform porting function 326- Internal secure world image state is inconsistent 327 328 329Handling integration errors 330^^^^^^^^^^^^^^^^^^^^^^^^^^^ 331 332Each secure world image may be provided by a different entity (for example, a 333Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32 334image and the OEM/SoC vendor may provide the other images). 335 336An image may contain bugs that are only visible when the images are integrated. 337The system integrator may not even have access to the debug variants of all the 338images in order to check if asserts are firing. For example, the release variant 339of BL1 may have already been burnt into the SoC. Therefore, TF code that detects 340an integration error should _not_ consider this a programming error, and should 341always take action, even in release builds. 342 343If an integration error is considered non-critical it should be treated as a 344recoverable error. If the error is considered critical it should be treated as 345an unexpected unrecoverable error. 346 347Handling recoverable errors 348^^^^^^^^^^^^^^^^^^^^^^^^^^^ 349 350The secure world **must not** crash when supplied with bad data from an external 351source. For example, data from the normal world or a hardware device. Similarly, 352the secure world **must not** crash if it detects a non-critical problem within 353itself or the system. It must make every effort to recover from the problem by 354emitting a ``WARN`` message, performing any necessary error handling and 355continuing. 356 357Examples: 358 359- Secure world receives SMC from normal world with bad arguments. 360- Secure world receives SMC from normal world at an unexpected time. 361- BL31 receives SMC from BL32 with bad arguments. 362- BL31 receives SMC from BL32 at unexpected time. 363- Secure world receives recoverable error from hardware device. Retrying the 364 operation may help here. 365- Non-critical secure world service is not functioning correctly. 366- BL31 SPD discovers minor configuration problem with corresponding SP. 367 368Handling unrecoverable errors 369^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 370 371In some cases it may not be possible for the secure world to recover from an 372error. This situation should be handled in one of the following ways: 373 3741. If the unrecoverable error is unexpected then emit an ``ERROR`` message and 375 call ``panic()``. This will end up calling the platform-specific function 376 ``plat_panic_handler()``. 3772. If the unrecoverable error is expected to occur in certain circumstances, 378 then emit an ``ERROR`` message and call the platform-specific function 379 ``plat_error_handler()``. 380 381Cases 1 and 2 are subtly different. A platform may implement ``plat_panic_handler`` 382and ``plat_error_handler`` in the same way (for example, by waiting for a secure 383watchdog to time-out or by invoking an interface on the platform's power 384controller to reset the platform). However, ``plat_error_handler`` may take 385additional action for some errors (for example, it may set a flag so the 386platform resets into a different mode). Also, ``plat_panic_handler()`` may 387implement additional debug functionality (for example, invoking a hardware 388breakpoint). 389 390Examples of unexpected unrecoverable errors: 391 392- BL32 receives an unexpected SMC response from BL31 that it is unable to 393 recover from. 394- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding 395 Trusted OS, which is critical for platform operation. 396- Secure world discovers that a critical hardware device is an unexpected and 397 unrecoverable state. 398- Secure world receives an unexpected and unrecoverable error from a critical 399 hardware device. 400- Secure world discovers that it is running on unsupported hardware. 401 402Examples of expected unrecoverable errors: 403 404- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk. 405- BL1/BL2 fails to authenticate the next image due to an invalid certificate. 406- Secure world continuously receives recoverable errors from a hardware device 407 but is unable to proceed without a valid response. 408 409Handling critical unresponsiveness 410^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 411 412If the secure world is waiting for a response from an external source (for 413example, the normal world or a hardware device) which is critical for continued 414operation, it must not wait indefinitely. It must have a mechanism (for example, 415a secure watchdog) for resetting itself and/or the external source to prevent 416the system from executing in this state indefinitely. 417 418Examples: 419 420- BL1 is waiting for the normal world to raise an SMC to proceed to the next 421 stage of the secure firmware update process. 422- A Trusted OS is waiting for a response from a proxy in the normal world that 423 is critical for continued operation. 424- Secure world is waiting for a hardware response that is critical for continued 425 operation. 426 427Security considerations 428----------------------- 429 430Part of the security of a platform is handling errors correctly, as described in 431the previous section. There are several other security considerations covered in 432this section. 433 434Do not leak secrets to the normal world 435^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 436 437The secure world **must not** leak secrets to the normal world, for example in 438response to an SMC. 439 440Handling Denial of Service attacks 441^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 442 443The secure world **should never** crash or become unusable due to receiving too 444many normal world requests (a *Denial of Service* or *DoS* attack). It should 445have a mechanism for throttling or ignoring normal world requests. 446 447Performance considerations 448-------------------------- 449 450Avoid printf and use logging macros 451^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 452 453``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``) 454which wrap ``tf_log`` and which allow the logging call to be compiled-out 455depending on the ``make`` command. Use these macros to avoid print statements 456being compiled unconditionally into the binary. 457 458Each logging macro has a numerical log level: 459 460.. code:: c 461 462 #define LOG_LEVEL_NONE 0 463 #define LOG_LEVEL_ERROR 10 464 #define LOG_LEVEL_NOTICE 20 465 #define LOG_LEVEL_WARNING 30 466 #define LOG_LEVEL_INFO 40 467 #define LOG_LEVEL_VERBOSE 50 468 469 470By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will 471be compiled into debug builds and all statements with a log level 472``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be 473overridden from the command line or by the platform makefile (although it may be 474necessary to clean the build directory first). For example, to enable 475``VERBOSE`` logging on FVP: 476 477``make PLAT=fvp LOG_LEVEL=50 all`` 478 479Use const data where possible 480^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 481 482For example, the following code: 483 484.. code:: c 485 486 struct my_struct { 487 int arg1; 488 int arg2; 489 }; 490 491 void init(struct my_struct *ptr); 492 493 void main(void) 494 { 495 struct my_struct x; 496 x.arg1 = 1; 497 x.arg2 = 2; 498 init(&x); 499 } 500 501is better written as: 502 503.. code:: c 504 505 struct my_struct { 506 int arg1; 507 int arg2; 508 }; 509 510 void init(const struct my_struct *ptr); 511 512 void main(void) 513 { 514 const struct my_struct x = { 1, 2 }; 515 init(&x); 516 } 517 518This allows the linker to put the data in a read-only data section instead of a 519writeable data section, which may result in a smaller and faster binary. Note 520that this may require dependent functions (``init()`` in the above example) to 521have ``const`` arguments, assuming they don't need to modify the data. 522 523Library and driver code 524----------------------- 525 526TF library code (under ``lib/`` and ``include/lib``) is any code that provides a 527reusable interface to other code, potentially even to code outside of TF. 528 529In some systems drivers must conform to a specific driver framework to provide 530services to the rest of the system. TF has no driver framework and the 531distinction between a driver and library is somewhat subjective. 532 533A driver (under ``drivers/`` and ``include/drivers/``) is defined as code that 534interfaces with hardware via a memory mapped interface. 535 536Some drivers (for example, the Arm CCI driver in ``include/drivers/arm/cci.h``) 537provide a general purpose API to that specific hardware. Other drivers (for 538example, the Arm PL011 console driver in ``drivers/arm/pl011/pl011_console.S``) 539provide a specific hardware implementation of a more abstract library API. In 540the latter case there may potentially be multiple drivers for the same hardware 541device. 542 543Neither libraries nor drivers should depend on platform-specific code. If they 544require platform-specific data (for example, a base address) to operate then 545they should provide an initialization function that takes the platform-specific 546data as arguments. 547 548TF common code (under ``common/`` and ``include/common/``) is code that is re-used 549by other generic (non-platform-specific) TF code. It is effectively internal 550library code. 551 552.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html 553.. _`Procedure Call Standard for the Arm Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf 554.. _`Procedure Call Standard for the Arm 64-bit Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf 555