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