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