1Coding Guidelines 2================= 3 4This document provides some additional guidelines to consider when writing 5|TF-A| code. These are not intended to be strictly-enforced rules like the 6contents of the :ref:`Coding Style`. 7 8Automatic Editor Configuration 9------------------------------ 10 11Many of the rules given below (such as indentation size, use of tabs, and 12newlines) can be set automatically using the `EditorConfig`_ configuration file 13in the root of the repository: ``.editorconfig``. With a supported editor, the 14rules set out in this file can be automatically applied when you are editing 15files in the |TF-A| repository. 16 17Several editors include built-in support for EditorConfig files, and many others 18support its functionality through plugins. 19 20Use of the EditorConfig file is suggested but is not required. 21 22 23Automatic Compliance Checking 24----------------------------- 25 26To assist with coding style compliance, the project Makefile contains two 27targets which both utilise the `checkpatch.pl` script that ships with the Linux 28source tree. The project also defines certain *checkpatch* options in the 29``.checkpatch.conf`` file in the top-level directory. 30 31.. note:: 32 Checkpatch errors will gate upstream merging of pull requests. 33 Checkpatch warnings will not gate merging but should be reviewed and fixed if 34 possible. 35 36To check the entire source tree, you must first download copies of 37``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available 38in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH`` 39environment variable to point to ``checkpatch.pl`` (with the other 2 files in 40the same directory) and build the `checkcodebase` target: 41 42.. code:: shell 43 44 make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase 45 46To just check the style on the files that differ between your local branch and 47the remote master, use: 48 49.. code:: shell 50 51 make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch 52 53If you wish to check your patch against something other than the remote master, 54set the ``BASE_COMMIT`` variable to your desired branch. By default, 55``BASE_COMMIT`` is set to ``origin/master``. 56 57Ignored Checkpatch Warnings 58^^^^^^^^^^^^^^^^^^^^^^^^^^^ 59 60Some checkpatch warnings in the TF codebase are deliberately ignored. These 61include: 62 63- ``**WARNING: line over 80 characters**``: Although the codebase should 64 generally conform to the 80 character limit this is overly restrictive in some 65 cases. 66 67- ``**WARNING: Use of volatile is usually wrong``: see 68 `Why the “volatile” type class should not be used`_ . Although this document 69 contains some very useful information, there are several legimate uses of the 70 volatile keyword within the TF codebase. 71 72Performance considerations 73-------------------------- 74 75Avoid printf and use logging macros 76^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 77 78``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``) 79which wrap ``tf_log`` and which allow the logging call to be compiled-out 80depending on the ``make`` command. Use these macros to avoid print statements 81being compiled unconditionally into the binary. 82 83Each logging macro has a numerical log level: 84 85.. code:: c 86 87 #define LOG_LEVEL_NONE 0 88 #define LOG_LEVEL_ERROR 10 89 #define LOG_LEVEL_NOTICE 20 90 #define LOG_LEVEL_WARNING 30 91 #define LOG_LEVEL_INFO 40 92 #define LOG_LEVEL_VERBOSE 50 93 94By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will 95be compiled into debug builds and all statements with a log level 96``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be 97overridden from the command line or by the platform makefile (although it may be 98necessary to clean the build directory first). For example, to enable 99``VERBOSE`` logging on FVP: 100 101``make PLAT=fvp LOG_LEVEL=50 all`` 102 103Use const data where possible 104^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 105 106For example, the following code: 107 108.. code:: c 109 110 struct my_struct { 111 int arg1; 112 int arg2; 113 }; 114 115 void init(struct my_struct *ptr); 116 117 void main(void) 118 { 119 struct my_struct x; 120 x.arg1 = 1; 121 x.arg2 = 2; 122 init(&x); 123 } 124 125is better written as: 126 127.. code:: c 128 129 struct my_struct { 130 int arg1; 131 int arg2; 132 }; 133 134 void init(const struct my_struct *ptr); 135 136 void main(void) 137 { 138 const struct my_struct x = { 1, 2 }; 139 init(&x); 140 } 141 142This allows the linker to put the data in a read-only data section instead of a 143writeable data section, which may result in a smaller and faster binary. Note 144that this may require dependent functions (``init()`` in the above example) to 145have ``const`` arguments, assuming they don't need to modify the data. 146 147Libc functions that are banned or to be used with caution 148--------------------------------------------------------- 149 150Below is a list of functions that present security risks and either must not be 151used (Banned) or are discouraged from use and must be used with care (Caution). 152 153+------------------------+-----------+--------------------------------------+ 154| libc function | Status | Comments | 155+========================+===========+======================================+ 156| ``strcpy, wcscpy``, | Banned | use strlcpy instead | 157| ``strncpy`` | | | 158+------------------------+-----------+--------------------------------------+ 159| ``strcat, wcscat``, | Banned | use strlcat instead | 160| ``strncat`` | | | 161+------------------------+-----------+--------------------------------------+ 162| ``sprintf, vsprintf`` | Banned | use snprintf, vsnprintf | 163| | | instead | 164+------------------------+-----------+--------------------------------------+ 165| ``snprintf`` | Caution | ensure result fits in buffer | 166| | | i.e : snprintf(buf,size...) < size | 167+------------------------+-----------+--------------------------------------+ 168| ``vsnprintf`` | Caution | inspect va_list match types | 169| | | specified in format string | 170+------------------------+-----------+--------------------------------------+ 171| ``strtok`` | Banned | use strtok_r or strsep instead | 172+------------------------+-----------+--------------------------------------+ 173| ``strtok_r, strsep`` | Caution | inspect for terminated input buffer | 174+------------------------+-----------+--------------------------------------+ 175| ``ato*`` | Banned | use equivalent strto* functions | 176+------------------------+-----------+--------------------------------------+ 177| ``*toa`` | Banned | Use snprintf instead | 178+------------------------+-----------+--------------------------------------+ 179 180The `libc` component in the codebase will not add support for the banned APIs. 181 182Error handling and robustness 183----------------------------- 184 185Using CASSERT to check for compile time data errors 186^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 187 188Where possible, use the ``CASSERT`` macro to check the validity of data known at 189compile time instead of checking validity at runtime, to avoid unnecessary 190runtime code. 191 192For example, this can be used to check that the assembler's and compiler's views 193of the size of an array is the same. 194 195.. code:: c 196 197 #include <cassert.h> 198 199 define MY_STRUCT_SIZE 8 /* Used by assembler source files */ 200 201 struct my_struct { 202 uint32_t arg1; 203 uint32_t arg2; 204 }; 205 206 CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch); 207 208 209If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would 210emit an error like this: 211 212:: 213 214 my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative 215 216 217Using assert() to check for programming errors 218^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 219 220In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be 221treated as a tightly integrated package; the image builder should be aware of 222and responsible for all functionality within the image, even if code within that 223image is provided by multiple entities. This allows us to be more aggressive in 224interpreting invalid state or bad function arguments as programming errors using 225``assert()``, including arguments passed across platform porting interfaces. 226This is in contrast to code in a Linux environment, which is less tightly 227integrated and may attempt to be more defensive by passing the error back up the 228call stack. 229 230Where possible, badly written TF code should fail early using ``assert()``. This 231helps reduce the amount of untested conditional code. By default these 232statements are not compiled into release builds, although this can be overridden 233using the ``ENABLE_ASSERTIONS`` build flag. 234 235Examples: 236 237- Bad argument supplied to library function 238- Bad argument provided by platform porting function 239- Internal secure world image state is inconsistent 240 241 242Handling integration errors 243^^^^^^^^^^^^^^^^^^^^^^^^^^^ 244 245Each secure world image may be provided by a different entity (for example, a 246Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32 247image and the OEM/SoC vendor may provide the other images). 248 249An image may contain bugs that are only visible when the images are integrated. 250The system integrator may not even have access to the debug variants of all the 251images in order to check if asserts are firing. For example, the release variant 252of BL1 may have already been burnt into the SoC. Therefore, TF code that detects 253an integration error should _not_ consider this a programming error, and should 254always take action, even in release builds. 255 256If an integration error is considered non-critical it should be treated as a 257recoverable error. If the error is considered critical it should be treated as 258an unexpected unrecoverable error. 259 260Handling recoverable errors 261^^^^^^^^^^^^^^^^^^^^^^^^^^^ 262 263The secure world **must not** crash when supplied with bad data from an external 264source. For example, data from the normal world or a hardware device. Similarly, 265the secure world **must not** crash if it detects a non-critical problem within 266itself or the system. It must make every effort to recover from the problem by 267emitting a ``WARN`` message, performing any necessary error handling and 268continuing. 269 270Examples: 271 272- Secure world receives SMC from normal world with bad arguments. 273- Secure world receives SMC from normal world at an unexpected time. 274- BL31 receives SMC from BL32 with bad arguments. 275- BL31 receives SMC from BL32 at unexpected time. 276- Secure world receives recoverable error from hardware device. Retrying the 277 operation may help here. 278- Non-critical secure world service is not functioning correctly. 279- BL31 SPD discovers minor configuration problem with corresponding SP. 280 281Handling unrecoverable errors 282^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 283 284In some cases it may not be possible for the secure world to recover from an 285error. This situation should be handled in one of the following ways: 286 2871. If the unrecoverable error is unexpected then emit an ``ERROR`` message and 288 call ``panic()``. This will end up calling the platform-specific function 289 ``plat_panic_handler()``. 2902. If the unrecoverable error is expected to occur in certain circumstances, 291 then emit an ``ERROR`` message and call the platform-specific function 292 ``plat_error_handler()``. 293 294Cases 1 and 2 are subtly different. A platform may implement 295``plat_panic_handler`` and ``plat_error_handler`` in the same way (for example, 296by waiting for a secure watchdog to time-out or by invoking an interface on the 297platform's power controller to reset the platform). However, 298``plat_error_handler`` may take additional action for some errors (for example, 299it may set a flag so the platform resets into a different mode). Also, 300``plat_panic_handler()`` may implement additional debug functionality (for 301example, invoking a hardware breakpoint). 302 303Examples of unexpected unrecoverable errors: 304 305- BL32 receives an unexpected SMC response from BL31 that it is unable to 306 recover from. 307- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding 308 Trusted OS, which is critical for platform operation. 309- Secure world discovers that a critical hardware device is an unexpected and 310 unrecoverable state. 311- Secure world receives an unexpected and unrecoverable error from a critical 312 hardware device. 313- Secure world discovers that it is running on unsupported hardware. 314 315Examples of expected unrecoverable errors: 316 317- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk. 318- BL1/BL2 fails to authenticate the next image due to an invalid certificate. 319- Secure world continuously receives recoverable errors from a hardware device 320 but is unable to proceed without a valid response. 321 322Handling critical unresponsiveness 323^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 324 325If the secure world is waiting for a response from an external source (for 326example, the normal world or a hardware device) which is critical for continued 327operation, it must not wait indefinitely. It must have a mechanism (for example, 328a secure watchdog) for resetting itself and/or the external source to prevent 329the system from executing in this state indefinitely. 330 331Examples: 332 333- BL1 is waiting for the normal world to raise an SMC to proceed to the next 334 stage of the secure firmware update process. 335- A Trusted OS is waiting for a response from a proxy in the normal world that 336 is critical for continued operation. 337- Secure world is waiting for a hardware response that is critical for continued 338 operation. 339 340Use of built-in *C* and *libc* data types 341----------------------------------------- 342 343The |TF-A| codebase should be kept as portable as possible, especially since 344both 64-bit and 32-bit platforms are supported. To help with this, the following 345data type usage guidelines should be followed: 346 347- Where possible, use the built-in *C* data types for variable storage (for 348 example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99* 349 types. Most code is typically only concerned with the minimum size of the 350 data stored, which the built-in *C* types guarantee. 351 352- Avoid using the exact-size standard *C99* types in general (for example, 353 ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the 354 compiler from making optimizations. There are legitimate uses for them, 355 for example to represent data of a known structure. When using them in struct 356 definitions, consider how padding in the struct will work across architectures. 357 For example, extra padding may be introduced in |AArch32| systems if a struct 358 member crosses a 32-bit boundary. 359 360- Use ``int`` as the default integer type - it's likely to be the fastest on all 361 systems. Also this can be assumed to be 32-bit as a consequence of the 362 `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call 363 Standard for the Arm 64-bit Architecture`_ . 364 365- Avoid use of ``short`` as this may end up being slower than ``int`` in some 366 systems. If a variable must be exactly 16-bit, use ``int16_t`` or 367 ``uint16_t``. 368 369- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given 370 that `int` is 32-bit on Arm platforms, there is no use for it. For integers of 371 at least 64-bit, use ``long long``. 372 373- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data. 374 375- Use ``unsigned`` for integers that can never be negative (counts, 376 indices, sizes, etc). TF intends to comply with MISRA "essential type" coding 377 rules (10.X), where signed and unsigned types are considered different 378 essential types. Choosing the correct type will aid this. MISRA static 379 analysers will pick up any implicit signed/unsigned conversions that may lead 380 to unexpected behaviour. 381 382- For pointer types: 383 384 - If an argument in a function declaration is pointing to a known type then 385 simply use a pointer to that type (for example: ``struct my_struct *``). 386 387 - If a variable (including an argument in a function declaration) is pointing 388 to a general, memory-mapped address, an array of pointers or another 389 structure that is likely to require pointer arithmetic then use 390 ``uintptr_t``. This will reduce the amount of casting required in the code. 391 Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it 392 may work but is less portable. 393 394 - For other pointer arguments in a function declaration, use ``void *``. This 395 includes pointers to types that are abstracted away from the known API and 396 pointers to arbitrary data. This allows the calling function to pass a 397 pointer argument to the function without any explicit casting (the cast to 398 ``void *`` is implicit). The function implementation can then do the 399 appropriate casting to a specific type. 400 401 - Avoid pointer arithmetic generally (as this violates MISRA C 2012 rule 402 18.4) and especially on void pointers (as this is only supported via 403 language extensions and is considered non-standard). In TF-A, setting the 404 ``W`` build flag to ``W=3`` enables the *-Wpointer-arith* compiler flag and 405 this will emit warnings where pointer arithmetic is used. 406 407 - Use ``ptrdiff_t`` to compare the difference between 2 pointers. 408 409- Use ``size_t`` when storing the ``sizeof()`` something. 410 411- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that 412 can also return an error code; the signed type allows for a negative return 413 code in case of error. This practice should be used sparingly. 414 415- Use ``u_register_t`` when it's important to store the contents of a register 416 in its native size (32-bit in |AArch32| and 64-bit in |AArch64|). This is not a 417 standard *C99* type but is widely available in libc implementations, 418 including the FreeBSD version included with the TF codebase. Where possible, 419 cast the variable to a more appropriate type before interpreting the data. For 420 example, the following struct in ``ep_info.h`` could use this type to minimize 421 the storage required for the set of registers: 422 423.. code:: c 424 425 typedef struct aapcs64_params { 426 u_register_t arg0; 427 u_register_t arg1; 428 u_register_t arg2; 429 u_register_t arg3; 430 u_register_t arg4; 431 u_register_t arg5; 432 u_register_t arg6; 433 u_register_t arg7; 434 } aapcs64_params_t; 435 436If some code wants to operate on ``arg0`` and knows that it represents a 32-bit 437unsigned integer on all systems, cast it to ``unsigned int``. 438 439These guidelines should be updated if additional types are needed. 440 441-------------- 442 443*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.* 444 445.. _`Linux master tree`: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ 446.. _`Procedure Call Standard for the Arm Architecture`: https://developer.arm.com/docs/ihi0042/latest/ 447.. _`Procedure Call Standard for the Arm 64-bit Architecture`: https://developer.arm.com/docs/ihi0055/latest/ 448.. _`EditorConfig`: http://editorconfig.org/ 449.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html 450.. _`MISRA C:2012 Guidelines`: https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx 451.. _`a spreadsheet`: https://developer.trustedfirmware.org/file/download/lamajxif3w7c4mpjeoo5/PHID-FILE-fp7c7acszn6vliqomyhn/MISRA-and-TF-Analysis-v1.3.ods 452