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