xref: /rk3399_ARM-atf/docs/process/coding-guidelines.rst (revision 40d553cfde38d4f68449c62967cd1ce0d6478750)
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