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