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