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