xref: /rk3399_ARM-atf/docs/process/coding-guidelines.rst (revision 665e71b8ea28162ec7737c1411bca3ea89e5957e)
1Coding Guidelines
2=================
3
4This document provides some additional guidelines to consider when writing
5|TF-A| code. These are not intended to be strictly-enforced rules like the
6contents of the :ref:`Coding Style`.
7
8Automatic Editor Configuration
9------------------------------
10
11Many of the rules given below (such as indentation size, use of tabs, and
12newlines) can be set automatically using the `EditorConfig`_ configuration file
13in the root of the repository: ``.editorconfig``. With a supported editor, the
14rules set out in this file can be automatically applied when you are editing
15files in the |TF-A| repository.
16
17Several editors include built-in support for EditorConfig files, and many others
18support its functionality through plugins.
19
20Use of the EditorConfig file is suggested but is not required.
21
22
23Automatic Compliance Checking
24-----------------------------
25
26To assist with coding style compliance, the project Makefile contains two
27targets which both utilise the `checkpatch.pl` script that ships with the Linux
28source tree. The project also defines certain *checkpatch* options in the
29``.checkpatch.conf`` file in the top-level directory.
30
31.. note::
32   Checkpatch errors will gate upstream merging of pull requests.
33   Checkpatch warnings will not gate merging but should be reviewed and fixed if
34   possible.
35
36To check the entire source tree, you must first download copies of
37``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available
38in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH``
39environment variable to point to ``checkpatch.pl`` (with the other 2 files in
40the same directory) and build the `checkcodebase` target:
41
42.. code:: shell
43
44    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkcodebase
45
46To just check the style on the files that differ between your local branch and
47the remote master, use:
48
49.. code:: shell
50
51    make CHECKPATCH=<path-to-linux>/linux/scripts/checkpatch.pl checkpatch
52
53If you wish to check your patch against something other than the remote master,
54set the ``BASE_COMMIT`` variable to your desired branch. By default,
55``BASE_COMMIT`` is set to ``origin/master``.
56
57Ignored Checkpatch Warnings
58^^^^^^^^^^^^^^^^^^^^^^^^^^^
59
60Some checkpatch warnings in the TF codebase are deliberately ignored. These
61include:
62
63- ``**WARNING: line over 80 characters**``: Although the codebase should
64  generally conform to the 80 character limit this is overly restrictive in some
65  cases.
66
67- ``**WARNING: Use of volatile is usually wrong``: see
68  `Why the “volatile” type class should not be used`_ . Although this document
69  contains some very useful information, there are several legimate uses of the
70  volatile keyword within the TF codebase.
71
72Performance considerations
73--------------------------
74
75Avoid printf and use logging macros
76^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77
78``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``)
79which wrap ``tf_log`` and which allow the logging call to be compiled-out
80depending on the ``make`` command. Use these macros to avoid print statements
81being compiled unconditionally into the binary.
82
83Each logging macro has a numerical log level:
84
85.. code:: c
86
87  #define LOG_LEVEL_NONE    0
88  #define LOG_LEVEL_ERROR   10
89  #define LOG_LEVEL_NOTICE  20
90  #define LOG_LEVEL_WARNING 30
91  #define LOG_LEVEL_INFO    40
92  #define LOG_LEVEL_VERBOSE 50
93
94By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will
95be compiled into debug builds and all statements with a log level
96``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be
97overridden from the command line or by the platform makefile (although it may be
98necessary to clean the build directory first). For example, to enable
99``VERBOSE`` logging on FVP:
100
101``make PLAT=fvp LOG_LEVEL=50 all``
102
103Use const data where possible
104^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
105
106For example, the following code:
107
108.. code:: c
109
110  struct my_struct {
111          int arg1;
112          int arg2;
113  };
114
115  void init(struct my_struct *ptr);
116
117  void main(void)
118  {
119          struct my_struct x;
120          x.arg1 = 1;
121          x.arg2 = 2;
122          init(&x);
123  }
124
125is better written as:
126
127.. code:: c
128
129  struct my_struct {
130          int arg1;
131          int arg2;
132  };
133
134  void init(const struct my_struct *ptr);
135
136  void main(void)
137  {
138          const struct my_struct x = { 1, 2 };
139          init(&x);
140  }
141
142This allows the linker to put the data in a read-only data section instead of a
143writeable data section, which may result in a smaller and faster binary. Note
144that this may require dependent functions (``init()`` in the above example) to
145have ``const`` arguments, assuming they don't need to modify the data.
146
147Libc functions that are banned or to be used with caution
148---------------------------------------------------------
149
150Below is a list of functions that present security risks and either must not be
151used (Banned) or are discouraged from use and must be used with care (Caution).
152
153+------------------------+-----------+--------------------------------------+
154|    libc function       | Status    | Comments                             |
155+========================+===========+======================================+
156| ``strcpy, wcscpy``,    | Banned    | use strlcpy instead                  |
157| ``strncpy``            |           |                                      |
158+------------------------+-----------+--------------------------------------+
159| ``strcat, wcscat``,    | Banned    | use strlcat instead                  |
160| ``strncat``            |           |                                      |
161+------------------------+-----------+--------------------------------------+
162| ``sprintf, vsprintf``  | Banned    | use snprintf, vsnprintf              |
163|                        |           | instead                              |
164+------------------------+-----------+--------------------------------------+
165| ``snprintf``           | Caution   | ensure result fits in buffer         |
166|                        |           | i.e : snprintf(buf,size...) < size   |
167+------------------------+-----------+--------------------------------------+
168| ``vsnprintf``          | Caution   | inspect va_list match types          |
169|                        |           | specified in format string           |
170+------------------------+-----------+--------------------------------------+
171| ``strtok``             | Banned    | use strtok_r or strsep instead       |
172+------------------------+-----------+--------------------------------------+
173| ``strtok_r, strsep``   | Caution   | inspect for terminated input buffer  |
174+------------------------+-----------+--------------------------------------+
175| ``ato*``               | Banned    | use equivalent strto* functions      |
176+------------------------+-----------+--------------------------------------+
177| ``*toa``               | Banned    | Use snprintf instead                 |
178+------------------------+-----------+--------------------------------------+
179
180The `libc` component in the codebase will not add support for the banned APIs.
181
182Error handling and robustness
183-----------------------------
184
185Using CASSERT to check for compile time data errors
186^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
187
188Where possible, use the ``CASSERT`` macro to check the validity of data known at
189compile time instead of checking validity at runtime, to avoid unnecessary
190runtime code.
191
192For example, this can be used to check that the assembler's and compiler's views
193of the size of an array is the same.
194
195.. code:: c
196
197  #include <cassert.h>
198
199  define MY_STRUCT_SIZE 8 /* Used by assembler source files */
200
201  struct my_struct {
202      uint32_t arg1;
203      uint32_t arg2;
204  };
205
206  CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch);
207
208
209If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would
210emit an error like this:
211
212::
213
214  my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative
215
216
217Using assert() to check for programming errors
218^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
219
220In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be
221treated as a tightly integrated package; the image builder should be aware of
222and responsible for all functionality within the image, even if code within that
223image is provided by multiple entities. This allows us to be more aggressive in
224interpreting invalid state or bad function arguments as programming errors using
225``assert()``, including arguments passed across platform porting interfaces.
226This is in contrast to code in a Linux environment, which is less tightly
227integrated and may attempt to be more defensive by passing the error back up the
228call stack.
229
230Where possible, badly written TF code should fail early using ``assert()``. This
231helps reduce the amount of untested conditional code. By default these
232statements are not compiled into release builds, although this can be overridden
233using the ``ENABLE_ASSERTIONS`` build flag.
234
235Examples:
236
237- Bad argument supplied to library function
238- Bad argument provided by platform porting function
239- Internal secure world image state is inconsistent
240
241
242Handling integration errors
243^^^^^^^^^^^^^^^^^^^^^^^^^^^
244
245Each secure world image may be provided by a different entity (for example, a
246Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32
247image and the OEM/SoC vendor may provide the other images).
248
249An image may contain bugs that are only visible when the images are integrated.
250The system integrator may not even have access to the debug variants of all the
251images in order to check if asserts are firing. For example, the release variant
252of BL1 may have already been burnt into the SoC. Therefore, TF code that detects
253an integration error should _not_ consider this a programming error, and should
254always take action, even in release builds.
255
256If an integration error is considered non-critical it should be treated as a
257recoverable error. If the error is considered critical it should be treated as
258an unexpected unrecoverable error.
259
260Handling recoverable errors
261^^^^^^^^^^^^^^^^^^^^^^^^^^^
262
263The secure world **must not** crash when supplied with bad data from an external
264source. For example, data from the normal world or a hardware device. Similarly,
265the secure world **must not** crash if it detects a non-critical problem within
266itself or the system. It must make every effort to recover from the problem by
267emitting a ``WARN`` message, performing any necessary error handling and
268continuing.
269
270Examples:
271
272- Secure world receives SMC from normal world with bad arguments.
273- Secure world receives SMC from normal world at an unexpected time.
274- BL31 receives SMC from BL32 with bad arguments.
275- BL31 receives SMC from BL32 at unexpected time.
276- Secure world receives recoverable error from hardware device. Retrying the
277  operation may help here.
278- Non-critical secure world service is not functioning correctly.
279- BL31 SPD discovers minor configuration problem with corresponding SP.
280
281Handling unrecoverable errors
282^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
283
284In some cases it may not be possible for the secure world to recover from an
285error. This situation should be handled in one of the following ways:
286
2871. If the unrecoverable error is unexpected then emit an ``ERROR`` message and
288   call ``panic()``. This will end up calling the platform-specific function
289   ``plat_panic_handler()``.
2902. If the unrecoverable error is expected to occur in certain circumstances,
291   then emit an ``ERROR`` message and call the platform-specific function
292   ``plat_error_handler()``.
293
294Cases 1 and 2 are subtly different. A platform may implement
295``plat_panic_handler`` and ``plat_error_handler`` in the same way (for example,
296by waiting for a secure watchdog to time-out or by invoking an interface on the
297platform's power controller to reset the platform). However,
298``plat_error_handler`` may take additional action for some errors (for example,
299it may set a flag so the platform resets into a different mode). Also,
300``plat_panic_handler()`` may implement additional debug functionality (for
301example, invoking a hardware breakpoint).
302
303Examples of unexpected unrecoverable errors:
304
305- BL32 receives an unexpected SMC response from BL31 that it is unable to
306  recover from.
307- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding
308  Trusted OS, which is critical for platform operation.
309- Secure world discovers that a critical hardware device is an unexpected and
310  unrecoverable state.
311- Secure world receives an unexpected and unrecoverable error from a critical
312  hardware device.
313- Secure world discovers that it is running on unsupported hardware.
314
315Examples of expected unrecoverable errors:
316
317- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk.
318- BL1/BL2 fails to authenticate the next image due to an invalid certificate.
319- Secure world continuously receives recoverable errors from a hardware device
320  but is unable to proceed without a valid response.
321
322Handling critical unresponsiveness
323^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
324
325If the secure world is waiting for a response from an external source (for
326example, the normal world or a hardware device) which is critical for continued
327operation, it must not wait indefinitely. It must have a mechanism (for example,
328a secure watchdog) for resetting itself and/or the external source to prevent
329the system from executing in this state indefinitely.
330
331Examples:
332
333- BL1 is waiting for the normal world to raise an SMC to proceed to the next
334  stage of the secure firmware update process.
335- A Trusted OS is waiting for a response from a proxy in the normal world that
336  is critical for continued operation.
337- Secure world is waiting for a hardware response that is critical for continued
338  operation.
339
340Use of built-in *C* and *libc* data types
341-----------------------------------------
342
343The |TF-A| codebase should be kept as portable as possible, especially since
344both 64-bit and 32-bit platforms are supported. To help with this, the following
345data type usage guidelines should be followed:
346
347- Where possible, use the built-in *C* data types for variable storage (for
348  example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99*
349  types. Most code is typically only concerned with the minimum size of the
350  data stored, which the built-in *C* types guarantee.
351
352- Avoid using the exact-size standard *C99* types in general (for example,
353  ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the
354  compiler from making optimizations. There are legitimate uses for them,
355  for example to represent data of a known structure. When using them in struct
356  definitions, consider how padding in the struct will work across architectures.
357  For example, extra padding may be introduced in |AArch32| systems if a struct
358  member crosses a 32-bit boundary.
359
360- Use ``int`` as the default integer type - it's likely to be the fastest on all
361  systems. Also this can be assumed to be 32-bit as a consequence of the
362  `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call
363  Standard for the Arm 64-bit Architecture`_ .
364
365- Avoid use of ``short`` as this may end up being slower than ``int`` in some
366  systems. If a variable must be exactly 16-bit, use ``int16_t`` or
367  ``uint16_t``.
368
369- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given
370  that `int` is 32-bit on Arm platforms, there is no use for it. For integers of
371  at least 64-bit, use ``long long``.
372
373- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data.
374
375- Use ``unsigned`` for integers that can never be negative (counts,
376  indices, sizes, etc). TF intends to comply with MISRA "essential type" coding
377  rules (10.X), where signed and unsigned types are considered different
378  essential types. Choosing the correct type will aid this. MISRA static
379  analysers will pick up any implicit signed/unsigned conversions that may lead
380  to unexpected behaviour.
381
382- For pointer types:
383
384  - If an argument in a function declaration is pointing to a known type then
385    simply use a pointer to that type (for example: ``struct my_struct *``).
386
387  - If a variable (including an argument in a function declaration) is pointing
388    to a general, memory-mapped address, an array of pointers or another
389    structure that is likely to require pointer arithmetic then use
390    ``uintptr_t``. This will reduce the amount of casting required in the code.
391    Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it
392    may work but is less portable.
393
394  - For other pointer arguments in a function declaration, use ``void *``. This
395    includes pointers to types that are abstracted away from the known API and
396    pointers to arbitrary data. This allows the calling function to pass a
397    pointer argument to the function without any explicit casting (the cast to
398    ``void *`` is implicit). The function implementation can then do the
399    appropriate casting to a specific type.
400
401  - Avoid pointer arithmetic generally (as this violates MISRA C 2012 rule
402    18.4) and especially on void pointers (as this is only supported via
403    language extensions and is considered non-standard). In TF-A, setting the
404    ``W`` build flag to ``W=3`` enables the *-Wpointer-arith* compiler flag and
405    this will emit warnings where pointer arithmetic is used.
406
407  - Use ``ptrdiff_t`` to compare the difference between 2 pointers.
408
409- Use ``size_t`` when storing the ``sizeof()`` something.
410
411- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that
412  can also return an error code; the signed type allows for a negative return
413  code in case of error. This practice should be used sparingly.
414
415- Use ``u_register_t`` when it's important to store the contents of a register
416  in its native size (32-bit in |AArch32| and 64-bit in |AArch64|). This is not a
417  standard *C99* type but is widely available in libc implementations,
418  including the FreeBSD version included with the TF codebase. Where possible,
419  cast the variable to a more appropriate type before interpreting the data. For
420  example, the following struct in ``ep_info.h`` could use this type to minimize
421  the storage required for the set of registers:
422
423.. code:: c
424
425    typedef struct aapcs64_params {
426            u_register_t arg0;
427            u_register_t arg1;
428            u_register_t arg2;
429            u_register_t arg3;
430            u_register_t arg4;
431            u_register_t arg5;
432            u_register_t arg6;
433            u_register_t arg7;
434    } aapcs64_params_t;
435
436If some code wants to operate on ``arg0`` and knows that it represents a 32-bit
437unsigned integer on all systems, cast it to ``unsigned int``.
438
439These guidelines should be updated if additional types are needed.
440
441--------------
442
443*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
444
445.. _`Linux master tree`: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/
446.. _`Procedure Call Standard for the Arm Architecture`: https://developer.arm.com/docs/ihi0042/latest/
447.. _`Procedure Call Standard for the Arm 64-bit Architecture`: https://developer.arm.com/docs/ihi0055/latest/
448.. _`EditorConfig`: http://editorconfig.org/
449.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html
450.. _`MISRA C:2012 Guidelines`: https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx
451.. _`a spreadsheet`: https://developer.trustedfirmware.org/file/download/lamajxif3w7c4mpjeoo5/PHID-FILE-fp7c7acszn6vliqomyhn/MISRA-and-TF-Analysis-v1.3.ods
452