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