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