GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
Alternative Boot Flows
|
||||
======================
|
||||
|
||||
EL3 payloads alternative boot flow
|
||||
----------------------------------
|
||||
|
||||
On a pre-production system, the ability to execute arbitrary, bare-metal code at
|
||||
the highest exception level is required. It allows full, direct access to the
|
||||
hardware, for example to run silicon soak tests.
|
||||
|
||||
Although it is possible to implement some baremetal secure firmware from
|
||||
scratch, this is a complex task on some platforms, depending on the level of
|
||||
configuration required to put the system in the expected state.
|
||||
|
||||
Rather than booting a baremetal application, a possible compromise is to boot
|
||||
``EL3 payloads`` through TF-A instead. This is implemented as an alternative
|
||||
boot flow, where a modified BL2 boots an EL3 payload, instead of loading the
|
||||
other BL images and passing control to BL31. It reduces the complexity of
|
||||
developing EL3 baremetal code by:
|
||||
|
||||
- putting the system into a known architectural state;
|
||||
- taking care of platform secure world initialization;
|
||||
- loading the SCP_BL2 image if required by the platform.
|
||||
|
||||
When booting an EL3 payload on Arm standard platforms, the configuration of the
|
||||
TrustZone controller is simplified such that only region 0 is enabled and is
|
||||
configured to permit secure access only. This gives full access to the whole
|
||||
DRAM to the EL3 payload.
|
||||
|
||||
The system is left in the same state as when entering BL31 in the default boot
|
||||
flow. In particular:
|
||||
|
||||
- Running in EL3;
|
||||
- Current state is AArch64;
|
||||
- Little-endian data access;
|
||||
- All exceptions disabled;
|
||||
- MMU disabled;
|
||||
- Caches disabled.
|
||||
|
||||
.. _alt_boot_flows_el3_payload:
|
||||
|
||||
Booting an EL3 payload
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The EL3 payload image is a standalone image and is not part of the FIP. It is
|
||||
not loaded by TF-A. Therefore, there are 2 possible scenarios:
|
||||
|
||||
- The EL3 payload may reside in non-volatile memory (NVM) and execute in
|
||||
place. In this case, booting it is just a matter of specifying the right
|
||||
address in NVM through ``EL3_PAYLOAD_BASE`` when building TF-A.
|
||||
|
||||
- The EL3 payload needs to be loaded in volatile memory (e.g. DRAM) at
|
||||
run-time.
|
||||
|
||||
To help in the latter scenario, the ``SPIN_ON_BL1_EXIT=1`` build option can be
|
||||
used. The infinite loop that it introduces in BL1 stops execution at the right
|
||||
moment for a debugger to take control of the target and load the payload (for
|
||||
example, over JTAG).
|
||||
|
||||
It is expected that this loading method will work in most cases, as a debugger
|
||||
connection is usually available in a pre-production system. The user is free to
|
||||
use any other platform-specific mechanism to load the EL3 payload, though.
|
||||
|
||||
|
||||
Preloaded BL33 alternative boot flow
|
||||
------------------------------------
|
||||
|
||||
Some platforms have the ability to preload BL33 into memory instead of relying
|
||||
on TF-A to load it. This may simplify packaging of the normal world code and
|
||||
improve performance in a development environment. When secure world cold boot
|
||||
is complete, TF-A simply jumps to a BL33 base address provided at build time.
|
||||
|
||||
For this option to be used, the ``PRELOADED_BL33_BASE`` build option has to be
|
||||
used when compiling TF-A. For example, the following command will create a FIP
|
||||
without a BL33 and prepare to jump to a BL33 image loaded at address
|
||||
0x80000000:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2019, Arm Limited. All rights reserved.*
|
||||
@@ -0,0 +1,980 @@
|
||||
Authentication Framework & Chain of Trust
|
||||
=========================================
|
||||
|
||||
The aim of this document is to describe the authentication framework
|
||||
implemented in Trusted Firmware-A (TF-A). This framework fulfills the
|
||||
following requirements:
|
||||
|
||||
#. It should be possible for a platform port to specify the Chain of Trust in
|
||||
terms of certificate hierarchy and the mechanisms used to verify a
|
||||
particular image/certificate.
|
||||
|
||||
#. The framework should distinguish between:
|
||||
|
||||
- The mechanism used to encode and transport information, e.g. DER encoded
|
||||
X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile
|
||||
counters.
|
||||
|
||||
- The mechanism used to verify the transported information i.e. the
|
||||
cryptographic libraries.
|
||||
|
||||
The framework has been designed following a modular approach illustrated in the
|
||||
next diagram:
|
||||
|
||||
::
|
||||
|
||||
+---------------+---------------+------------+
|
||||
| Trusted | Trusted | Trusted |
|
||||
| Firmware | Firmware | Firmware |
|
||||
| Generic | IO Framework | Platform |
|
||||
| Code i.e. | (IO) | Port |
|
||||
| BL1/BL2 (GEN) | | (PP) |
|
||||
+---------------+---------------+------------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
v v v
|
||||
+-----------+ +-----------+ +-----------+
|
||||
| | | | | Image |
|
||||
| Crypto | | Auth | | Parser |
|
||||
| Module |<->| Module |<->| Module |
|
||||
| (CM) | | (AM) | | (IPM) |
|
||||
| | | | | |
|
||||
+-----------+ +-----------+ +-----------+
|
||||
^ ^
|
||||
| |
|
||||
v v
|
||||
+----------------+ +-----------------+
|
||||
| Cryptographic | | Image Parser |
|
||||
| Libraries (CL) | | Libraries (IPL) |
|
||||
+----------------+ +-----------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
v v
|
||||
+-----------------+
|
||||
| Misc. Libs e.g. |
|
||||
| ASN.1 decoder |
|
||||
| |
|
||||
+-----------------+
|
||||
|
||||
DIAGRAM 1.
|
||||
|
||||
This document describes the inner details of the authentication framework and
|
||||
the abstraction mechanisms available to specify a Chain of Trust.
|
||||
|
||||
Framework design
|
||||
----------------
|
||||
|
||||
This section describes some aspects of the framework design and the rationale
|
||||
behind them. These aspects are key to verify a Chain of Trust.
|
||||
|
||||
Chain of Trust
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
A CoT is basically a sequence of authentication images which usually starts with
|
||||
a root of trust and culminates in a single data image. The following diagram
|
||||
illustrates how this maps to a CoT for the BL31 image described in the
|
||||
`TBBR-Client specification`_.
|
||||
|
||||
::
|
||||
|
||||
+------------------+ +-------------------+
|
||||
| ROTPK/ROTPK Hash |------>| Trusted Key |
|
||||
+------------------+ | Certificate |
|
||||
| (Auth Image) |
|
||||
/+-------------------+
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
L v
|
||||
+------------------+ +-------------------+
|
||||
| Trusted World |------>| BL31 Key |
|
||||
| Public Key | | Certificate |
|
||||
+------------------+ | (Auth Image) |
|
||||
+-------------------+
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ v
|
||||
+------------------+ L +-------------------+
|
||||
| BL31 Content |------>| BL31 Content |
|
||||
| Certificate PK | | Certificate |
|
||||
+------------------+ | (Auth Image) |
|
||||
+-------------------+
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ |
|
||||
/ v
|
||||
+------------------+ L +-------------------+
|
||||
| BL31 Hash |------>| BL31 Image |
|
||||
| | | (Data Image) |
|
||||
+------------------+ | |
|
||||
+-------------------+
|
||||
|
||||
DIAGRAM 2.
|
||||
|
||||
The root of trust is usually a public key (ROTPK) that has been burnt in the
|
||||
platform and cannot be modified.
|
||||
|
||||
Image types
|
||||
~~~~~~~~~~~
|
||||
|
||||
Images in a CoT are categorised as authentication and data images. An
|
||||
authentication image contains information to authenticate a data image or
|
||||
another authentication image. A data image is usually a boot loader binary, but
|
||||
it could be any other data that requires authentication.
|
||||
|
||||
Component responsibilities
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For every image in a Chain of Trust, the following high level operations are
|
||||
performed to verify it:
|
||||
|
||||
#. Allocate memory for the image either statically or at runtime.
|
||||
|
||||
#. Identify the image and load it in the allocated memory.
|
||||
|
||||
#. Check the integrity of the image as per its type.
|
||||
|
||||
#. Authenticate the image as per the cryptographic algorithms used.
|
||||
|
||||
#. If the image is an authentication image, extract the information that will
|
||||
be used to authenticate the next image in the CoT.
|
||||
|
||||
In Diagram 1, each component is responsible for one or more of these operations.
|
||||
The responsibilities are briefly described below.
|
||||
|
||||
TF-A Generic code and IO framework (GEN/IO)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
These components are responsible for initiating the authentication process for a
|
||||
particular image in BL1 or BL2. For each BL image that requires authentication,
|
||||
the Generic code asks recursively the Authentication module what is the parent
|
||||
image until either an authenticated image or the ROT is reached. Then the
|
||||
Generic code calls the IO framework to load the image and calls the
|
||||
Authentication module to authenticate it, following the CoT from ROT to Image.
|
||||
|
||||
TF-A Platform Port (PP)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The platform is responsible for:
|
||||
|
||||
#. Specifying the CoT for each image that needs to be authenticated. Details of
|
||||
how a CoT can be specified by the platform are explained later. The platform
|
||||
also specifies the authentication methods and the parsing method used for
|
||||
each image.
|
||||
|
||||
#. Statically allocating memory for each parameter in each image which is
|
||||
used for verifying the CoT, e.g. memory for public keys, hashes etc.
|
||||
|
||||
#. Providing the ROTPK or a hash of it.
|
||||
|
||||
#. Providing additional information to the IPM to enable it to identify and
|
||||
extract authentication parameters contained in an image, e.g. if the
|
||||
parameters are stored as X509v3 extensions, the corresponding OID must be
|
||||
provided.
|
||||
|
||||
#. Fulfill any other memory requirements of the IPM and the CM (not currently
|
||||
described in this document).
|
||||
|
||||
#. Export functions to verify an image which uses an authentication method that
|
||||
cannot be interpreted by the CM, e.g. if an image has to be verified using a
|
||||
NV counter, then the value of the counter to compare with can only be
|
||||
provided by the platform.
|
||||
|
||||
#. Export a custom IPM if a proprietary image format is being used (described
|
||||
later).
|
||||
|
||||
Authentication Module (AM)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is responsible for:
|
||||
|
||||
#. Providing the necessary abstraction mechanisms to describe a CoT. Amongst
|
||||
other things, the authentication and image parsing methods must be specified
|
||||
by the PP in the CoT.
|
||||
|
||||
#. Verifying the CoT passed by GEN by utilising functionality exported by the
|
||||
PP, IPM and CM.
|
||||
|
||||
#. Tracking which images have been verified. In case an image is a part of
|
||||
multiple CoTs then it should be verified only once e.g. the Trusted World
|
||||
Key Certificate in the TBBR-Client spec. contains information to verify
|
||||
SCP_BL2, BL31, BL32 each of which have a separate CoT. (This
|
||||
responsibility has not been described in this document but should be
|
||||
trivial to implement).
|
||||
|
||||
#. Reusing memory meant for a data image to verify authentication images e.g.
|
||||
in the CoT described in Diagram 2, each certificate can be loaded and
|
||||
verified in the memory reserved by the platform for the BL31 image. By the
|
||||
time BL31 (the data image) is loaded, all information to authenticate it
|
||||
will have been extracted from the parent image i.e. BL31 content
|
||||
certificate. It is assumed that the size of an authentication image will
|
||||
never exceed the size of a data image. It should be possible to verify this
|
||||
at build time using asserts.
|
||||
|
||||
Cryptographic Module (CM)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The CM is responsible for providing an API to:
|
||||
|
||||
#. Verify a digital signature.
|
||||
#. Verify a hash.
|
||||
|
||||
The CM does not include any cryptography related code, but it relies on an
|
||||
external library to perform the cryptographic operations. A Crypto-Library (CL)
|
||||
linking the CM and the external library must be implemented. The following
|
||||
functions must be provided by the CL:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void (*init)(void);
|
||||
int (*verify_signature)(void *data_ptr, unsigned int data_len,
|
||||
void *sig_ptr, unsigned int sig_len,
|
||||
void *sig_alg, unsigned int sig_alg_len,
|
||||
void *pk_ptr, unsigned int pk_len);
|
||||
int (*verify_hash)(void *data_ptr, unsigned int data_len,
|
||||
void *digest_info_ptr, unsigned int digest_info_len);
|
||||
|
||||
These functions are registered in the CM using the macro:
|
||||
|
||||
.. code:: c
|
||||
|
||||
REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash);
|
||||
|
||||
``_name`` must be a string containing the name of the CL. This name is used for
|
||||
debugging purposes.
|
||||
|
||||
Image Parser Module (IPM)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The IPM is responsible for:
|
||||
|
||||
#. Checking the integrity of each image loaded by the IO framework.
|
||||
#. Extracting parameters used for authenticating an image based upon a
|
||||
description provided by the platform in the CoT descriptor.
|
||||
|
||||
Images may have different formats (for example, authentication images could be
|
||||
x509v3 certificates, signed ELF files or any other platform specific format).
|
||||
The IPM allows to register an Image Parser Library (IPL) for every image format
|
||||
used in the CoT. This library must implement the specific methods to parse the
|
||||
image. The IPM obtains the image format from the CoT and calls the right IPL to
|
||||
check the image integrity and extract the authentication parameters.
|
||||
|
||||
See Section "Describing the image parsing methods" for more details about the
|
||||
mechanism the IPM provides to define and register IPLs.
|
||||
|
||||
Authentication methods
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The AM supports the following authentication methods:
|
||||
|
||||
#. Hash
|
||||
#. Digital signature
|
||||
|
||||
The platform may specify these methods in the CoT in case it decides to define
|
||||
a custom CoT instead of reusing a predefined one.
|
||||
|
||||
If a data image uses multiple methods, then all the methods must be a part of
|
||||
the same CoT. The number and type of parameters are method specific. These
|
||||
parameters should be obtained from the parent image using the IPM.
|
||||
|
||||
#. Hash
|
||||
|
||||
Parameters:
|
||||
|
||||
#. A pointer to data to hash
|
||||
#. Length of the data
|
||||
#. A pointer to the hash
|
||||
#. Length of the hash
|
||||
|
||||
The hash will be represented by the DER encoding of the following ASN.1
|
||||
type:
|
||||
|
||||
::
|
||||
|
||||
DigestInfo ::= SEQUENCE {
|
||||
digestAlgorithm DigestAlgorithmIdentifier,
|
||||
digest Digest
|
||||
}
|
||||
|
||||
This ASN.1 structure makes it possible to remove any assumption about the
|
||||
type of hash algorithm used as this information accompanies the hash. This
|
||||
should allow the Cryptography Library (CL) to support multiple hash
|
||||
algorithm implementations.
|
||||
|
||||
#. Digital Signature
|
||||
|
||||
Parameters:
|
||||
|
||||
#. A pointer to data to sign
|
||||
#. Length of the data
|
||||
#. Public Key Algorithm
|
||||
#. Public Key value
|
||||
#. Digital Signature Algorithm
|
||||
#. Digital Signature value
|
||||
|
||||
The Public Key parameters will be represented by the DER encoding of the
|
||||
following ASN.1 type:
|
||||
|
||||
::
|
||||
|
||||
SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}},
|
||||
subjectPublicKey BIT STRING }
|
||||
|
||||
The Digital Signature Algorithm will be represented by the DER encoding of
|
||||
the following ASN.1 types.
|
||||
|
||||
::
|
||||
|
||||
AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE {
|
||||
algorithm ALGORITHM.&id({IOSet}),
|
||||
parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
|
||||
}
|
||||
|
||||
The digital signature will be represented by:
|
||||
|
||||
::
|
||||
|
||||
signature ::= BIT STRING
|
||||
|
||||
The authentication framework will use the image descriptor to extract all the
|
||||
information related to authentication.
|
||||
|
||||
Specifying a Chain of Trust
|
||||
---------------------------
|
||||
|
||||
A CoT can be described as a set of image descriptors linked together in a
|
||||
particular order. The order dictates the sequence in which they must be
|
||||
verified. Each image has a set of properties which allow the AM to verify it.
|
||||
These properties are described below.
|
||||
|
||||
The PP is responsible for defining a single or multiple CoTs for a data image.
|
||||
Unless otherwise specified, the data structures described in the following
|
||||
sections are populated by the PP statically.
|
||||
|
||||
Describing the image parsing methods
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The parsing method refers to the format of a particular image. For example, an
|
||||
authentication image that represents a certificate could be in the X.509v3
|
||||
format. A data image that represents a boot loader stage could be in raw binary
|
||||
or ELF format. The IPM supports three parsing methods. An image has to use one
|
||||
of the three methods described below. An IPL is responsible for interpreting a
|
||||
single parsing method. There has to be one IPL for every method used by the
|
||||
platform.
|
||||
|
||||
#. Raw format: This format is effectively a nop as an image using this method
|
||||
is treated as being in raw binary format e.g. boot loader images used by
|
||||
TF-A. This method should only be used by data images.
|
||||
|
||||
#. X509V3 method: This method uses industry standards like X.509 to represent
|
||||
PKI certificates (authentication images). It is expected that open source
|
||||
libraries will be available which can be used to parse an image represented
|
||||
by this method. Such libraries can be used to write the corresponding IPL
|
||||
e.g. the X.509 parsing library code in mbed TLS.
|
||||
|
||||
#. Platform defined method: This method caters for platform specific
|
||||
proprietary standards to represent authentication or data images. For
|
||||
example, The signature of a data image could be appended to the data image
|
||||
raw binary. A header could be prepended to the combined blob to specify the
|
||||
extents of each component. The platform will have to implement the
|
||||
corresponding IPL to interpret such a format.
|
||||
|
||||
The following enum can be used to define these three methods.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef enum img_type_enum {
|
||||
IMG_RAW, /* Binary image */
|
||||
IMG_PLAT, /* Platform specific format */
|
||||
IMG_CERT, /* X509v3 certificate */
|
||||
IMG_MAX_TYPES,
|
||||
} img_type_t;
|
||||
|
||||
An IPL must provide functions with the following prototypes:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void init(void);
|
||||
int check_integrity(void *img, unsigned int img_len);
|
||||
int get_auth_param(const auth_param_type_desc_t *type_desc,
|
||||
void *img, unsigned int img_len,
|
||||
void **param, unsigned int *param_len);
|
||||
|
||||
An IPL for each type must be registered using the following macro:
|
||||
|
||||
.. code:: c
|
||||
|
||||
REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param)
|
||||
|
||||
- ``_type``: one of the types described above.
|
||||
- ``_name``: a string containing the IPL name for debugging purposes.
|
||||
- ``_init``: initialization function pointer.
|
||||
- ``_check_int``: check image integrity function pointer.
|
||||
- ``_get_param``: extract authentication parameter function pointer.
|
||||
|
||||
The ``init()`` function will be used to initialize the IPL.
|
||||
|
||||
The ``check_integrity()`` function is passed a pointer to the memory where the
|
||||
image has been loaded by the IO framework and the image length. It should ensure
|
||||
that the image is in the format corresponding to the parsing method and has not
|
||||
been tampered with. For example, RFC-2459 describes a validation sequence for an
|
||||
X.509 certificate.
|
||||
|
||||
The ``get_auth_param()`` function is passed a parameter descriptor containing
|
||||
information about the parameter (``type_desc`` and ``cookie``) to identify and
|
||||
extract the data corresponding to that parameter from an image. This data will
|
||||
be used to verify either the current or the next image in the CoT sequence.
|
||||
|
||||
Each image in the CoT will specify the parsing method it uses. This information
|
||||
will be used by the IPM to find the right parser descriptor for the image.
|
||||
|
||||
Describing the authentication method(s)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As part of the CoT, each image has to specify one or more authentication methods
|
||||
which will be used to verify it. As described in the Section "Authentication
|
||||
methods", there are three methods supported by the AM.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef enum {
|
||||
AUTH_METHOD_NONE,
|
||||
AUTH_METHOD_HASH,
|
||||
AUTH_METHOD_SIG,
|
||||
AUTH_METHOD_NUM
|
||||
} auth_method_type_t;
|
||||
|
||||
The AM defines the type of each parameter used by an authentication method. It
|
||||
uses this information to:
|
||||
|
||||
#. Specify to the ``get_auth_param()`` function exported by the IPM, which
|
||||
parameter should be extracted from an image.
|
||||
|
||||
#. Correctly marshall the parameters while calling the verification function
|
||||
exported by the CM and PP.
|
||||
|
||||
#. Extract authentication parameters from a parent image in order to verify a
|
||||
child image e.g. to verify the certificate image, the public key has to be
|
||||
obtained from the parent image.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef enum {
|
||||
AUTH_PARAM_NONE,
|
||||
AUTH_PARAM_RAW_DATA, /* Raw image data */
|
||||
AUTH_PARAM_SIG, /* The image signature */
|
||||
AUTH_PARAM_SIG_ALG, /* The image signature algorithm */
|
||||
AUTH_PARAM_HASH, /* A hash (including the algorithm) */
|
||||
AUTH_PARAM_PUB_KEY, /* A public key */
|
||||
} auth_param_type_t;
|
||||
|
||||
The AM defines the following structure to identify an authentication parameter
|
||||
required to verify an image.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_param_type_desc_s {
|
||||
auth_param_type_t type;
|
||||
void *cookie;
|
||||
} auth_param_type_desc_t;
|
||||
|
||||
``cookie`` is used by the platform to specify additional information to the IPM
|
||||
which enables it to uniquely identify the parameter that should be extracted
|
||||
from an image. For example, the hash of a BL3x image in its corresponding
|
||||
content certificate is stored in an X509v3 custom extension field. An extension
|
||||
field can only be identified using an OID. In this case, the ``cookie`` could
|
||||
contain the pointer to the OID defined by the platform for the hash extension
|
||||
field while the ``type`` field could be set to ``AUTH_PARAM_HASH``. A value of 0 for
|
||||
the ``cookie`` field means that it is not used.
|
||||
|
||||
For each method, the AM defines a structure with the parameters required to
|
||||
verify the image.
|
||||
|
||||
.. code:: c
|
||||
|
||||
/*
|
||||
* Parameters for authentication by hash matching
|
||||
*/
|
||||
typedef struct auth_method_param_hash_s {
|
||||
auth_param_type_desc_t *data; /* Data to hash */
|
||||
auth_param_type_desc_t *hash; /* Hash to match with */
|
||||
} auth_method_param_hash_t;
|
||||
|
||||
/*
|
||||
* Parameters for authentication by signature
|
||||
*/
|
||||
typedef struct auth_method_param_sig_s {
|
||||
auth_param_type_desc_t *pk; /* Public key */
|
||||
auth_param_type_desc_t *sig; /* Signature to check */
|
||||
auth_param_type_desc_t *alg; /* Signature algorithm */
|
||||
auth_param_type_desc_t *tbs; /* Data signed */
|
||||
} auth_method_param_sig_t;
|
||||
|
||||
The AM defines the following structure to describe an authentication method for
|
||||
verifying an image
|
||||
|
||||
.. code:: c
|
||||
|
||||
/*
|
||||
* Authentication method descriptor
|
||||
*/
|
||||
typedef struct auth_method_desc_s {
|
||||
auth_method_type_t type;
|
||||
union {
|
||||
auth_method_param_hash_t hash;
|
||||
auth_method_param_sig_t sig;
|
||||
} param;
|
||||
} auth_method_desc_t;
|
||||
|
||||
Using the method type specified in the ``type`` field, the AM finds out what field
|
||||
needs to access within the ``param`` union.
|
||||
|
||||
Storing Authentication parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A parameter described by ``auth_param_type_desc_t`` to verify an image could be
|
||||
obtained from either the image itself or its parent image. The memory allocated
|
||||
for loading the parent image will be reused for loading the child image. Hence
|
||||
parameters which are obtained from the parent for verifying a child image need
|
||||
to have memory allocated for them separately where they can be stored. This
|
||||
memory must be statically allocated by the platform port.
|
||||
|
||||
The AM defines the following structure to store the data corresponding to an
|
||||
authentication parameter.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_param_data_desc_s {
|
||||
void *auth_param_ptr;
|
||||
unsigned int auth_param_len;
|
||||
} auth_param_data_desc_t;
|
||||
|
||||
The ``auth_param_ptr`` field is initialized by the platform. The ``auth_param_len``
|
||||
field is used to specify the length of the data in the memory.
|
||||
|
||||
For parameters that can be obtained from the child image itself, the IPM is
|
||||
responsible for populating the ``auth_param_ptr`` and ``auth_param_len`` fields
|
||||
while executing the ``img_get_auth_param()`` function.
|
||||
|
||||
The AM defines the following structure to enable an image to describe the
|
||||
parameters that should be extracted from it and used to verify the next image
|
||||
(child) in a CoT.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_param_desc_s {
|
||||
auth_param_type_desc_t type_desc;
|
||||
auth_param_data_desc_t data;
|
||||
} auth_param_desc_t;
|
||||
|
||||
Describing an image in a CoT
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An image in a CoT is a consolidation of the following aspects of a CoT described
|
||||
above.
|
||||
|
||||
#. A unique identifier specified by the platform which allows the IO framework
|
||||
to locate the image in a FIP and load it in the memory reserved for the data
|
||||
image in the CoT.
|
||||
|
||||
#. A parsing method which is used by the AM to find the appropriate IPM.
|
||||
|
||||
#. Authentication methods and their parameters as described in the previous
|
||||
section. These are used to verify the current image.
|
||||
|
||||
#. Parameters which are used to verify the next image in the current CoT. These
|
||||
parameters are specified only by authentication images and can be extracted
|
||||
from the current image once it has been verified.
|
||||
|
||||
The following data structure describes an image in a CoT.
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct auth_img_desc_s {
|
||||
unsigned int img_id;
|
||||
const struct auth_img_desc_s *parent;
|
||||
img_type_t img_type;
|
||||
const auth_method_desc_t *const img_auth_methods;
|
||||
const auth_param_desc_t *const authenticated_data;
|
||||
} auth_img_desc_t;
|
||||
|
||||
A CoT is defined as an array of pointers to ``auth_image_desc_t`` structures
|
||||
linked together by the ``parent`` field. Those nodes with no parent must be
|
||||
authenticated using the ROTPK stored in the platform.
|
||||
|
||||
Implementation example
|
||||
----------------------
|
||||
|
||||
This section is a detailed guide explaining a trusted boot implementation using
|
||||
the authentication framework. This example corresponds to the Applicative
|
||||
Functional Mode (AFM) as specified in the TBBR-Client document. It is
|
||||
recommended to read this guide along with the source code.
|
||||
|
||||
The TBBR CoT
|
||||
~~~~~~~~~~~~
|
||||
|
||||
CoT specific to BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_bl1.c``
|
||||
and ``drivers/auth/tbbr/tbbr_cot_bl2.c`` respectively. The common CoT used across
|
||||
BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_common.c``.
|
||||
This CoT consists of an array of pointers to image descriptors and it is
|
||||
registered in the framework using the macro ``REGISTER_COT(cot_desc)``, where
|
||||
``cot_desc`` must be the name of the array (passing a pointer or any other
|
||||
type of indirection will cause the registration process to fail).
|
||||
|
||||
The number of images participating in the boot process depends on the CoT.
|
||||
There is, however, a minimum set of images that are mandatory in TF-A and thus
|
||||
all CoTs must present:
|
||||
|
||||
- ``BL2``
|
||||
- ``SCP_BL2`` (platform specific)
|
||||
- ``BL31``
|
||||
- ``BL32`` (optional)
|
||||
- ``BL33``
|
||||
|
||||
The TBBR specifies the additional certificates that must accompany these images
|
||||
for a proper authentication. Details about the TBBR CoT may be found in the
|
||||
:ref:`Trusted Board Boot` document.
|
||||
|
||||
Following the :ref:`Porting Guide`, a platform must provide unique
|
||||
identifiers for all the images and certificates that will be loaded during the
|
||||
boot process. If a platform is using the TBBR as a reference for trusted boot,
|
||||
these identifiers can be obtained from ``include/common/tbbr/tbbr_img_def.h``.
|
||||
Arm platforms include this file in ``include/plat/arm/common/arm_def.h``. Other
|
||||
platforms may also include this file or provide their own identifiers.
|
||||
|
||||
**Important**: the authentication module uses these identifiers to index the
|
||||
CoT array, so the descriptors location in the array must match the identifiers.
|
||||
|
||||
Each image descriptor must specify:
|
||||
|
||||
- ``img_id``: the corresponding image unique identifier defined by the platform.
|
||||
- ``img_type``: the image parser module uses the image type to call the proper
|
||||
parsing library to check the image integrity and extract the required
|
||||
authentication parameters. Three types of images are currently supported:
|
||||
|
||||
- ``IMG_RAW``: image is a raw binary. No parsing functions are available,
|
||||
other than reading the whole image.
|
||||
- ``IMG_PLAT``: image format is platform specific. The platform may use this
|
||||
type for custom images not directly supported by the authentication
|
||||
framework.
|
||||
- ``IMG_CERT``: image is an x509v3 certificate.
|
||||
|
||||
- ``parent``: pointer to the parent image descriptor. The parent will contain
|
||||
the information required to authenticate the current image. If the parent
|
||||
is NULL, the authentication parameters will be obtained from the platform
|
||||
(i.e. the BL2 and Trusted Key certificates are signed with the ROT private
|
||||
key, whose public part is stored in the platform).
|
||||
- ``img_auth_methods``: this points to an array which defines the
|
||||
authentication methods that must be checked to consider an image
|
||||
authenticated. Each method consists of a type and a list of parameter
|
||||
descriptors. A parameter descriptor consists of a type and a cookie which
|
||||
will point to specific information required to extract that parameter from
|
||||
the image (i.e. if the parameter is stored in an x509v3 extension, the
|
||||
cookie will point to the extension OID). Depending on the method type, a
|
||||
different number of parameters must be specified. This pointer should not be
|
||||
NULL.
|
||||
Supported methods are:
|
||||
|
||||
- ``AUTH_METHOD_HASH``: the hash of the image must match the hash extracted
|
||||
from the parent image. The following parameter descriptors must be
|
||||
specified:
|
||||
|
||||
- ``data``: data to be hashed (obtained from current image)
|
||||
- ``hash``: reference hash (obtained from parent image)
|
||||
|
||||
- ``AUTH_METHOD_SIG``: the image (usually a certificate) must be signed with
|
||||
the private key whose public part is extracted from the parent image (or
|
||||
the platform if the parent is NULL). The following parameter descriptors
|
||||
must be specified:
|
||||
|
||||
- ``pk``: the public key (obtained from parent image)
|
||||
- ``sig``: the digital signature (obtained from current image)
|
||||
- ``alg``: the signature algorithm used (obtained from current image)
|
||||
- ``data``: the data to be signed (obtained from current image)
|
||||
|
||||
- ``authenticated_data``: this array pointer indicates what authentication
|
||||
parameters must be extracted from an image once it has been authenticated.
|
||||
Each parameter consists of a parameter descriptor and the buffer
|
||||
address/size to store the parameter. The CoT is responsible for allocating
|
||||
the required memory to store the parameters. This pointer may be NULL.
|
||||
|
||||
In the ``tbbr_cot*.c`` file, a set of buffers are allocated to store the parameters
|
||||
extracted from the certificates. In the case of the TBBR CoT, these parameters
|
||||
are hashes and public keys. In DER format, an RSA-4096 public key requires 550
|
||||
bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication
|
||||
process, some of the buffers may be reused at different stages during the boot.
|
||||
|
||||
Next in that file, the parameter descriptors are defined. These descriptors will
|
||||
be used to extract the parameter data from the corresponding image.
|
||||
|
||||
Example: the BL31 Chain of Trust
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Four image descriptors form the BL31 Chain of Trust:
|
||||
|
||||
.. code:: c
|
||||
|
||||
static const auth_img_desc_t trusted_key_cert = {
|
||||
.img_id = TRUSTED_KEY_CERT_ID,
|
||||
.img_type = IMG_CERT,
|
||||
.parent = NULL,
|
||||
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_SIG,
|
||||
.param.sig = {
|
||||
.pk = &subject_pk,
|
||||
.sig = &sig,
|
||||
.alg = &sig_alg,
|
||||
.data = &raw_data
|
||||
}
|
||||
},
|
||||
[1] = {
|
||||
.type = AUTH_METHOD_NV_CTR,
|
||||
.param.nv_ctr = {
|
||||
.cert_nv_ctr = &trusted_nv_ctr,
|
||||
.plat_nv_ctr = &trusted_nv_ctr
|
||||
}
|
||||
}
|
||||
},
|
||||
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
|
||||
[0] = {
|
||||
.type_desc = &trusted_world_pk,
|
||||
.data = {
|
||||
.ptr = (void *)trusted_world_pk_buf,
|
||||
.len = (unsigned int)PK_DER_LEN
|
||||
}
|
||||
},
|
||||
[1] = {
|
||||
.type_desc = &non_trusted_world_pk,
|
||||
.data = {
|
||||
.ptr = (void *)non_trusted_world_pk_buf,
|
||||
.len = (unsigned int)PK_DER_LEN
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
static const auth_img_desc_t soc_fw_key_cert = {
|
||||
.img_id = SOC_FW_KEY_CERT_ID,
|
||||
.img_type = IMG_CERT,
|
||||
.parent = &trusted_key_cert,
|
||||
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_SIG,
|
||||
.param.sig = {
|
||||
.pk = &trusted_world_pk,
|
||||
.sig = &sig,
|
||||
.alg = &sig_alg,
|
||||
.data = &raw_data
|
||||
}
|
||||
},
|
||||
[1] = {
|
||||
.type = AUTH_METHOD_NV_CTR,
|
||||
.param.nv_ctr = {
|
||||
.cert_nv_ctr = &trusted_nv_ctr,
|
||||
.plat_nv_ctr = &trusted_nv_ctr
|
||||
}
|
||||
}
|
||||
},
|
||||
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
|
||||
[0] = {
|
||||
.type_desc = &soc_fw_content_pk,
|
||||
.data = {
|
||||
.ptr = (void *)content_pk_buf,
|
||||
.len = (unsigned int)PK_DER_LEN
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
static const auth_img_desc_t soc_fw_content_cert = {
|
||||
.img_id = SOC_FW_CONTENT_CERT_ID,
|
||||
.img_type = IMG_CERT,
|
||||
.parent = &soc_fw_key_cert,
|
||||
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_SIG,
|
||||
.param.sig = {
|
||||
.pk = &soc_fw_content_pk,
|
||||
.sig = &sig,
|
||||
.alg = &sig_alg,
|
||||
.data = &raw_data
|
||||
}
|
||||
},
|
||||
[1] = {
|
||||
.type = AUTH_METHOD_NV_CTR,
|
||||
.param.nv_ctr = {
|
||||
.cert_nv_ctr = &trusted_nv_ctr,
|
||||
.plat_nv_ctr = &trusted_nv_ctr
|
||||
}
|
||||
}
|
||||
},
|
||||
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
|
||||
[0] = {
|
||||
.type_desc = &soc_fw_hash,
|
||||
.data = {
|
||||
.ptr = (void *)soc_fw_hash_buf,
|
||||
.len = (unsigned int)HASH_DER_LEN
|
||||
}
|
||||
},
|
||||
[1] = {
|
||||
.type_desc = &soc_fw_config_hash,
|
||||
.data = {
|
||||
.ptr = (void *)soc_fw_config_hash_buf,
|
||||
.len = (unsigned int)HASH_DER_LEN
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
static const auth_img_desc_t bl31_image = {
|
||||
.img_id = BL31_IMAGE_ID,
|
||||
.img_type = IMG_RAW,
|
||||
.parent = &soc_fw_content_cert,
|
||||
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
|
||||
[0] = {
|
||||
.type = AUTH_METHOD_HASH,
|
||||
.param.hash = {
|
||||
.data = &raw_data,
|
||||
.hash = &soc_fw_hash
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
The **Trusted Key certificate** is signed with the ROT private key and contains
|
||||
the Trusted World public key and the Non-Trusted World public key as x509v3
|
||||
extensions. This must be specified in the image descriptor using the
|
||||
``img_auth_methods`` and ``authenticated_data`` arrays, respectively.
|
||||
|
||||
The Trusted Key certificate is authenticated by checking its digital signature
|
||||
using the ROTPK. Four parameters are required to check a signature: the public
|
||||
key, the algorithm, the signature and the data that has been signed. Therefore,
|
||||
four parameter descriptors must be specified with the authentication method:
|
||||
|
||||
- ``subject_pk``: parameter descriptor of type ``AUTH_PARAM_PUB_KEY``. This type
|
||||
is used to extract a public key from the parent image. If the cookie is an
|
||||
OID, the key is extracted from the corresponding x509v3 extension. If the
|
||||
cookie is NULL, the subject public key is retrieved. In this case, because
|
||||
the parent image is NULL, the public key is obtained from the platform
|
||||
(this key will be the ROTPK).
|
||||
- ``sig``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to extract
|
||||
the signature from the certificate.
|
||||
- ``sig_alg``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to
|
||||
extract the signature algorithm from the certificate.
|
||||
- ``raw_data``: parameter descriptor of type ``AUTH_PARAM_RAW_DATA``. It is used
|
||||
to extract the data to be signed from the certificate.
|
||||
|
||||
Once the signature has been checked and the certificate authenticated, the
|
||||
Trusted World public key needs to be extracted from the certificate. A new entry
|
||||
is created in the ``authenticated_data`` array for that purpose. In that entry,
|
||||
the corresponding parameter descriptor must be specified along with the buffer
|
||||
address to store the parameter value. In this case, the ``trusted_world_pk``
|
||||
descriptor is used to extract the public key from an x509v3 extension with OID
|
||||
``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as
|
||||
parameter in the signature authentication method. The key is stored in the
|
||||
``trusted_world_pk_buf`` buffer.
|
||||
|
||||
The **BL31 Key certificate** is authenticated by checking its digital signature
|
||||
using the Trusted World public key obtained previously from the Trusted Key
|
||||
certificate. In the image descriptor, we specify a single authentication method
|
||||
by signature whose public key is the ``trusted_world_pk``. Once this certificate
|
||||
has been authenticated, we have to extract the BL31 public key, stored in the
|
||||
extension specified by ``soc_fw_content_pk``. This key will be copied to the
|
||||
``content_pk_buf`` buffer.
|
||||
|
||||
The **BL31 certificate** is authenticated by checking its digital signature
|
||||
using the BL31 public key obtained previously from the BL31 Key certificate.
|
||||
We specify the authentication method using ``soc_fw_content_pk`` as public key.
|
||||
After authentication, we need to extract the BL31 hash, stored in the extension
|
||||
specified by ``soc_fw_hash``. This hash will be copied to the
|
||||
``soc_fw_hash_buf`` buffer.
|
||||
|
||||
The **BL31 image** is authenticated by calculating its hash and matching it
|
||||
with the hash obtained from the BL31 certificate. The image descriptor contains
|
||||
a single authentication method by hash. The parameters to the hash method are
|
||||
the reference hash, ``soc_fw_hash``, and the data to be hashed. In this case,
|
||||
it is the whole image, so we specify ``raw_data``.
|
||||
|
||||
The image parser library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The image parser module relies on libraries to check the image integrity and
|
||||
extract the authentication parameters. The number and type of parser libraries
|
||||
depend on the images used in the CoT. Raw images do not need a library, so
|
||||
only an x509v3 library is required for the TBBR CoT.
|
||||
|
||||
Arm platforms will use an x509v3 library based on mbed TLS. This library may be
|
||||
found in ``drivers/auth/mbedtls/mbedtls_x509_parser.c``. It exports three
|
||||
functions:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void init(void);
|
||||
int check_integrity(void *img, unsigned int img_len);
|
||||
int get_auth_param(const auth_param_type_desc_t *type_desc,
|
||||
void *img, unsigned int img_len,
|
||||
void **param, unsigned int *param_len);
|
||||
|
||||
The library is registered in the framework using the macro
|
||||
``REGISTER_IMG_PARSER_LIB()``. Each time the image parser module needs to access
|
||||
an image of type ``IMG_CERT``, it will call the corresponding function exported
|
||||
in this file.
|
||||
|
||||
The build system must be updated to include the corresponding library and
|
||||
mbed TLS sources. Arm platforms use the ``arm_common.mk`` file to pull the
|
||||
sources.
|
||||
|
||||
The cryptographic library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The cryptographic module relies on a library to perform the required operations,
|
||||
i.e. verify a hash or a digital signature. Arm platforms will use a library
|
||||
based on mbed TLS, which can be found in
|
||||
``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the
|
||||
authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports
|
||||
four functions:
|
||||
|
||||
.. code:: c
|
||||
|
||||
void init(void);
|
||||
int verify_signature(void *data_ptr, unsigned int data_len,
|
||||
void *sig_ptr, unsigned int sig_len,
|
||||
void *sig_alg, unsigned int sig_alg_len,
|
||||
void *pk_ptr, unsigned int pk_len);
|
||||
int verify_hash(void *data_ptr, unsigned int data_len,
|
||||
void *digest_info_ptr, unsigned int digest_info_len);
|
||||
int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
|
||||
size_t len, const void *key, unsigned int key_len,
|
||||
unsigned int key_flags, const void *iv,
|
||||
unsigned int iv_len, const void *tag,
|
||||
unsigned int tag_len)
|
||||
|
||||
The mbedTLS library algorithm support is configured by both the
|
||||
``TF_MBEDTLS_KEY_ALG`` and ``TF_MBEDTLS_KEY_SIZE`` variables.
|
||||
|
||||
- ``TF_MBEDTLS_KEY_ALG`` can take in 3 values: `rsa`, `ecdsa` or `rsa+ecdsa`.
|
||||
This variable allows the Makefile to include the corresponding sources in
|
||||
the build for the various algorithms. Setting the variable to `rsa+ecdsa`
|
||||
enables support for both rsa and ecdsa algorithms in the mbedTLS library.
|
||||
|
||||
- ``TF_MBEDTLS_KEY_SIZE`` sets the supported RSA key size for TFA. Valid values
|
||||
include 1024, 2048, 3072 and 4096.
|
||||
|
||||
- ``TF_MBEDTLS_USE_AES_GCM`` enables the authenticated decryption support based
|
||||
on AES-GCM algorithm. Valid values are 0 and 1.
|
||||
|
||||
.. note::
|
||||
If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can
|
||||
be defined in the platform Makefile. It will make mbed TLS use an
|
||||
implementation of SHA-256 with smaller memory footprint (~1.5 KB less) but
|
||||
slower (~30%).
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
|
||||
+859
@@ -0,0 +1,859 @@
|
||||
Arm CPU Specific Build Macros
|
||||
=============================
|
||||
|
||||
This document describes the various build options present in the CPU specific
|
||||
operations framework to enable errata workarounds and to enable optimizations
|
||||
for a specific CPU on a platform.
|
||||
|
||||
Security Vulnerability Workarounds
|
||||
----------------------------------
|
||||
|
||||
TF-A exports a series of build flags which control which security
|
||||
vulnerability workarounds should be applied at runtime.
|
||||
|
||||
- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for
|
||||
`CVE-2017-5715`_. This flag can be set to 0 by the platform if none
|
||||
of the PEs in the system need the workaround. Setting this flag to 0 provides
|
||||
no performance benefit for non-affected platforms, it just helps to comply
|
||||
with the recommendation in the spec regarding workaround discovery.
|
||||
Defaults to 1.
|
||||
|
||||
- ``WORKAROUND_CVE_2018_3639``: Enables the security workaround for
|
||||
`CVE-2018-3639`_. Defaults to 1. The TF-A project recommends to keep
|
||||
the default value of 1 even on platforms that are unaffected by
|
||||
CVE-2018-3639, in order to comply with the recommendation in the spec
|
||||
regarding workaround discovery.
|
||||
|
||||
- ``DYNAMIC_WORKAROUND_CVE_2018_3639``: Enables dynamic mitigation for
|
||||
`CVE-2018-3639`_. This build option should be set to 1 if the target
|
||||
platform contains at least 1 CPU that requires dynamic mitigation.
|
||||
Defaults to 0.
|
||||
|
||||
- ``WORKAROUND_CVE_2022_23960``: Enables mitigation for `CVE-2022-23960`_.
|
||||
This build option should be set to 1 if the target platform contains at
|
||||
least 1 CPU that requires this mitigation. Defaults to 1.
|
||||
|
||||
.. _arm_cpu_macros_errata_workarounds:
|
||||
|
||||
CPU Errata Workarounds
|
||||
----------------------
|
||||
|
||||
TF-A exports a series of build flags which control the errata workarounds that
|
||||
are applied to each CPU by the reset handler. The errata details can be found
|
||||
in the CPU specific errata documents published by Arm:
|
||||
|
||||
- `Cortex-A53 MPCore Software Developers Errata Notice`_
|
||||
- `Cortex-A57 MPCore Software Developers Errata Notice`_
|
||||
- `Cortex-A72 MPCore Software Developers Errata Notice`_
|
||||
|
||||
The errata workarounds are implemented for a particular revision or a set of
|
||||
processor revisions. This is checked by the reset handler at runtime. Each
|
||||
errata workaround is identified by its ``ID`` as specified in the processor's
|
||||
errata notice document. The format of the define used to enable/disable the
|
||||
errata workaround is ``ERRATA_<Processor name>_<ID>``, where the ``Processor name``
|
||||
is for example ``A57`` for the ``Cortex_A57`` CPU.
|
||||
|
||||
Refer to :ref:`firmware_design_cpu_errata_reporting` for information on how to
|
||||
write errata workaround functions.
|
||||
|
||||
All workarounds are disabled by default. The platform is responsible for
|
||||
enabling these workarounds according to its requirement by defining the
|
||||
errata workaround build flags in the platform specific makefile. In case
|
||||
these workarounds are enabled for the wrong CPU revision then the errata
|
||||
workaround is not applied. In the DEBUG build, this is indicated by
|
||||
printing a warning to the crash console.
|
||||
|
||||
In the current implementation, a platform which has more than 1 variant
|
||||
with different revisions of a processor has no runtime mechanism available
|
||||
for it to specify which errata workarounds should be enabled or not.
|
||||
|
||||
The value of the build flags is 0 by default, that is, disabled. A value of 1
|
||||
will enable it.
|
||||
|
||||
For Cortex-A9, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A9
|
||||
CPU. This needs to be enabled for all revisions of the CPU.
|
||||
|
||||
For Cortex-A15, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A15_816470``: This applies errata 816470 workaround to Cortex-A15
|
||||
CPU. This needs to be enabled only for revision >= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A15_827671``: This applies errata 827671 workaround to Cortex-A15
|
||||
CPU. This needs to be enabled only for revision >= r3p0 of the CPU.
|
||||
|
||||
For Cortex-A17, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A17_852421``: This applies errata 852421 workaround to Cortex-A17
|
||||
CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A17_852423``: This applies errata 852423 workaround to Cortex-A17
|
||||
CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
|
||||
|
||||
For Cortex-A35, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A35_855472``: This applies errata 855472 workaround to Cortex-A35
|
||||
CPUs. This needs to be enabled only for revision r0p0 of Cortex-A35.
|
||||
|
||||
For Cortex-A53, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A53_819472``: This applies errata 819472 workaround to all
|
||||
CPUs. This needs to be enabled only for revision <= r0p1 of Cortex-A53.
|
||||
|
||||
- ``ERRATA_A53_824069``: This applies errata 824069 workaround to all
|
||||
CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53.
|
||||
|
||||
- ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53
|
||||
CPU. This needs to be enabled only for revision <= r0p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A53_827319``: This applies errata 827319 workaround to all
|
||||
CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53.
|
||||
|
||||
- ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and
|
||||
link time to Cortex-A53 CPU. This needs to be enabled for some variants of
|
||||
revision <= r0p4. This workaround can lead the linker to create ``*.stub``
|
||||
sections.
|
||||
|
||||
- ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53
|
||||
CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From
|
||||
r0p4 and onwards, this errata is enabled by default in hardware.
|
||||
|
||||
- ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time
|
||||
to Cortex-A53 CPU. This needs to be enabled for some variants of revision
|
||||
<= r0p4. This workaround can lead the linker to emit ``*.stub`` sections
|
||||
which are 4kB aligned.
|
||||
|
||||
- ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53
|
||||
CPUs. Though the erratum is present in every revision of the CPU,
|
||||
this workaround is only applied to CPUs from r0p3 onwards, which feature
|
||||
a chicken bit in CPUACTLR_EL1 to enable a hardware workaround.
|
||||
Earlier revisions of the CPU have other errata which require the same
|
||||
workaround in software, so they should be covered anyway.
|
||||
|
||||
- ``ERRATA_A53_1530924``: This applies errata 1530924 workaround to all
|
||||
revisions of Cortex-A53 CPU.
|
||||
|
||||
For Cortex-A55, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A55_768277``: This applies errata 768277 workaround to Cortex-A55
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A55_778703``: This applies errata 778703 workaround to Cortex-A55
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A55_798797``: This applies errata 798797 workaround to Cortex-A55
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A55_846532``: This applies errata 846532 workaround to Cortex-A55
|
||||
CPU. This needs to be enabled only for revision <= r0p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A55_903758``: This applies errata 903758 workaround to Cortex-A55
|
||||
CPU. This needs to be enabled only for revision <= r0p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A55_1221012``: This applies errata 1221012 workaround to Cortex-A55
|
||||
CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A55_1530923``: This applies errata 1530923 workaround to all
|
||||
revisions of Cortex-A55 CPU.
|
||||
|
||||
For Cortex-A57, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A57_806969``: This applies errata 806969 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_813419``: This applies errata 813419 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_813420``: This applies errata 813420 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_814670``: This applies errata 814670 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_817169``: This applies errata 817169 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r0p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_826974``: This applies errata 826974 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_826977``: This applies errata 826977 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_828024``: This applies errata 828024 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_829520``: This applies errata 829520 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57
|
||||
CPU. This needs to be enabled only for revision <= r1p3 of the CPU.
|
||||
|
||||
- ``ERRATA_A57_1319537``: This applies errata 1319537 workaround to all
|
||||
revisions of Cortex-A57 CPU.
|
||||
|
||||
For Cortex-A72, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72
|
||||
CPU. This needs to be enabled only for revision <= r0p3 of the CPU.
|
||||
|
||||
- ``ERRATA_A72_1319367``: This applies errata 1319367 workaround to all
|
||||
revisions of Cortex-A72 CPU.
|
||||
|
||||
For Cortex-A73, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A73_852427``: This applies errata 852427 workaround to Cortex-A73
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A73_855423``: This applies errata 855423 workaround to Cortex-A73
|
||||
CPU. This needs to be enabled only for revision <= r0p1 of the CPU.
|
||||
|
||||
For Cortex-A75, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A75_764081``: This applies errata 764081 workaround to Cortex-A75
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A75_790748``: This applies errata 790748 workaround to Cortex-A75
|
||||
CPU. This needs to be enabled only for revision r0p0 of the CPU.
|
||||
|
||||
For Cortex-A76, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A76_1073348``: This applies errata 1073348 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1130799``: This applies errata 1130799 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1220197``: This applies errata 1220197 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1257314``: This applies errata 1257314 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1262606``: This applies errata 1262606 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1262888``: This applies errata 1262888 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1791580``: This applies errata 1791580 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1165522``: This applies errata 1165522 workaround to all
|
||||
revisions of Cortex-A76 CPU. This errata is fixed in r3p0 but due to
|
||||
limitation of errata framework this errata is applied to all revisions
|
||||
of Cortex-A76 CPU.
|
||||
|
||||
- ``ERRATA_A76_1868343``: This applies errata 1868343 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_1946160``: This applies errata 1946160 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled only for revisions r3p0 - r4p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A76_2743102``: This applies errata 2743102 workaround to Cortex-A76
|
||||
CPU. This needs to be enabled for all revisions <= r4p1 of the CPU and is
|
||||
still open.
|
||||
|
||||
For Cortex-A77, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A77_1925769``: This applies errata 1925769 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A77_1946167``: This applies errata 1946167 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A77_1791578``: This applies errata 1791578 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open.
|
||||
|
||||
- ``ERRATA_A77_2356587``: This applies errata 2356587 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open.
|
||||
|
||||
- ``ERRATA_A77_1800714``: This applies errata 1800714 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled for revisions <= r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A77_2743100``: This applies errata 2743100 workaround to Cortex-A77
|
||||
CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open.
|
||||
|
||||
For Cortex-A78, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A78_1688305``: This applies errata 1688305 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled only for revision r0p0 - r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_A78_1941498``: This applies errata 1941498 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_A78_1951500``: This applies errata 1951500 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r1p0 and r1p1, r0p0 has the same
|
||||
issue but there is no workaround for that revision.
|
||||
|
||||
- ``ERRATA_A78_1821534``: This applies errata 1821534 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0 and r1p0.
|
||||
|
||||
- ``ERRATA_A78_1952683``: This applies errata 1952683 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revision r0p0, it is fixed in r1p0.
|
||||
|
||||
- ``ERRATA_A78_2132060``: This applies errata 2132060 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2. It
|
||||
is still open.
|
||||
|
||||
- ``ERRATA_A78_2242635``: This applies errata 2242635 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r1p0, r1p1, and r1p2. The issue
|
||||
is present in r0p0 but there is no workaround. It is still open.
|
||||
|
||||
- ``ERRATA_A78_2376745``: This applies errata 2376745 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2, and
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_A78_2395406``: This applies errata 2395406 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2, and
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_A78_2712571``: This applies erratum 2712571 workaround to Cortex-A78
|
||||
CPU, this erratum affects system configurations that do not use an ARM
|
||||
interconnect IP. This needs to be enabled for revisions r0p0, r1p0, r1p1
|
||||
and r1p2 and it is still open.
|
||||
|
||||
- ``ERRATA_A78_2742426``: This applies erratum 2742426 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1 and r1p2 and
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_A78_2772019``: This applies errata 2772019 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2, and
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_A78_2779479``: This applies erratum 2779479 workaround to Cortex-A78
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1 and r1p2 and
|
||||
it is still open.
|
||||
|
||||
For Cortex-A78 AE, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A78_AE_1941500`` : This applies errata 1941500 workaround to
|
||||
Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1.
|
||||
This erratum is still open.
|
||||
|
||||
- ``ERRATA_A78_AE_1951502`` : This applies errata 1951502 workaround to
|
||||
Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This
|
||||
erratum is still open.
|
||||
|
||||
- ``ERRATA_A78_AE_2376748`` : This applies errata 2376748 workaround to
|
||||
Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This
|
||||
erratum is still open.
|
||||
|
||||
- ``ERRATA_A78_AE_2395408`` : This applies errata 2395408 workaround to
|
||||
Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This
|
||||
erratum is still open.
|
||||
|
||||
- ``ERRATA_A78_AE_2712574`` : This applies erratum 2712574 workaround to
|
||||
Cortex-A78 AE CPU. This erratum affects system configurations that do not use
|
||||
an ARM interconnect IP. This needs to be enabled for revisions r0p0, r0p1 and
|
||||
r0p2. This erratum is still open.
|
||||
|
||||
For Cortex-A78C, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A78C_1827430`` : This applies errata 1827430 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revision r0p0. The erratum is
|
||||
fixed in r0p1.
|
||||
|
||||
- ``ERRATA_A78C_1827440`` : This applies errata 1827440 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revision r0p0. The erratum is
|
||||
fixed in r0p1.
|
||||
|
||||
- ``ERRATA_A78C_2132064`` : This applies errata 2132064 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revisions r0p1, r0p2 and
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_A78C_2242638`` : This applies errata 2242638 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revisions r0p1, r0p2 and
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_A78C_2376749`` : This applies errata 2376749 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revisions r0p1 and r0p2. This
|
||||
erratum is still open.
|
||||
|
||||
- ``ERRATA_A78C_2395411`` : This applies errata 2395411 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revisions r0p1 and r0p2. This
|
||||
erratum is still open.
|
||||
|
||||
- ``ERRATA_A78C_2712575`` : This applies erratum 2712575 workaround to
|
||||
Cortex-A78C CPU, this erratum affects system configurations that do not use
|
||||
an ARM interconnect IP. This needs to be enabled for revisions r0p1 and r0p2
|
||||
and is still open.
|
||||
|
||||
- ``ERRATA_A78C_2772121`` : This applies errata 2772121 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revisions r0p0, r0p1 and r0p2.
|
||||
This erratum is still open.
|
||||
|
||||
- ``ERRATA_A78C_2779484`` : This applies errata 2779484 workaround to
|
||||
Cortex-A78C CPU. This needs to be enabled for revisions r0p1 and r0p2.
|
||||
This erratum is still open.
|
||||
|
||||
For Cortex-X1 CPU, the following errata build flags are defined:
|
||||
|
||||
- ``ERRATA_X1_1821534`` : This applies errata 1821534 workaround to Cortex-X1
|
||||
CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_X1_1688305`` : This applies errata 1688305 workaround to Cortex-X1
|
||||
CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_X1_1827429`` : This applies errata 1827429 workaround to Cortex-X1
|
||||
CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
|
||||
|
||||
For Neoverse N1, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision r0p0 and r1p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1130799``: This applies errata 1130799 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1165347``: This applies errata 1165347 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1207823``: This applies errata 1207823 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1220197``: This applies errata 1220197 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1257314``: This applies errata 1257314 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1262606``: This applies errata 1262606 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1262888``: This applies errata 1262888 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1275112``: This applies errata 1275112 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1315703``: This applies errata 1315703 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1542419``: This applies errata 1542419 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revisions r3p0 - r4p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1868343``: This applies errata 1868343 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
|
||||
|
||||
- ``ERRATA_N1_1946160``: This applies errata 1946160 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled for revisions r3p0, r3p1, r4p0, and r4p1, for
|
||||
revisions r0p0, r1p0, and r2p0 there is no workaround.
|
||||
|
||||
- ``ERRATA_N1_2743102``: This applies errata 2743102 workaround to Neoverse-N1
|
||||
CPU. This needs to be enabled for all revisions <= r4p1 of the CPU and is
|
||||
still open.
|
||||
|
||||
For Neoverse V1, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_V1_1618635``: This applies errata 1618635 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU, it is fixed in
|
||||
r1p0.
|
||||
|
||||
- ``ERRATA_V1_1774420``: This applies errata 1774420 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
|
||||
in r1p1.
|
||||
|
||||
- ``ERRATA_V1_1791573``: This applies errata 1791573 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
|
||||
in r1p1.
|
||||
|
||||
- ``ERRATA_V1_1852267``: This applies errata 1852267 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
|
||||
in r1p1.
|
||||
|
||||
- ``ERRATA_V1_1925756``: This applies errata 1925756 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open.
|
||||
|
||||
- ``ERRATA_V1_1940577``: This applies errata 1940577 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled only for revision r1p0 and r1p1 of the
|
||||
CPU.
|
||||
|
||||
- ``ERRATA_V1_1966096``: This applies errata 1966096 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the
|
||||
issue is present in r0p0 as well but there is no workaround for that
|
||||
revision. It is still open.
|
||||
|
||||
- ``ERRATA_V1_2139242``: This applies errata 2139242 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the
|
||||
CPU. It is still open.
|
||||
|
||||
- ``ERRATA_V1_2108267``: This applies errata 2108267 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU.
|
||||
It is still open.
|
||||
|
||||
- ``ERRATA_V1_2216392``: This applies errata 2216392 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the
|
||||
issue is present in r0p0 as well but there is no workaround for that
|
||||
revision. It is still open.
|
||||
|
||||
- ``ERRATA_V1_2294912``: This applies errata 2294912 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU.
|
||||
|
||||
- ``ERRATA_V1_2372203``: This applies errata 2372203 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0 and r1p1 of the CPU.
|
||||
It is still open.
|
||||
|
||||
- ``ERRATA_V1_2701953``: This applies erratum 2701953 workaround to Neoverse-V1
|
||||
CPU, this erratum affects system configurations that do not use an ARM
|
||||
interconnect IP. This needs to be enabled for revisions r0p0, r1p0 and r1p1.
|
||||
It has been fixed in r1p2.
|
||||
|
||||
- ``ERRATA_V1_2743093``: This applies errata 2743093 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1 and r1p2 of the
|
||||
CPU. It is still open.
|
||||
|
||||
- ``ERRATA_V1_2743233``: This applies erratum 2743233 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2 of the
|
||||
CPU. It is still open.
|
||||
|
||||
- ``ERRATA_V1_2779461``: This applies erratum 2779461 workaround to Neoverse-V1
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, r1p2 of the
|
||||
CPU. It is still open.
|
||||
|
||||
For Neoverse V2, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_V2_2719103``: This applies errata 2719103 workaround to Neoverse-V2
|
||||
CPU, this affects system configurations that do not use and ARM interconnect
|
||||
IP. This needs to be enabled for revisions r0p0 and r0p1. It has been fixed
|
||||
in r0p2.
|
||||
|
||||
- ``ERRATA_V2_2801372``: This applies errata 2801372 workaround to Neoverse-V2
|
||||
CPU, this affects all configurations. This needs to be enabled for revisions
|
||||
r0p0 and r0p1. It has been fixed in r0p2.
|
||||
|
||||
For Cortex-A710, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A710_1987031``: This applies errata 1987031 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
|
||||
r2p0 of the CPU. It is still open.
|
||||
|
||||
- ``ERRATA_A710_2081180``: This applies errata 2081180 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
|
||||
r2p0 of the CPU. It is still open.
|
||||
|
||||
- ``ERRATA_A710_2055002``: This applies errata 2055002 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r1p0, r2p0 of the CPU
|
||||
and is still open.
|
||||
|
||||
- ``ERRATA_A710_2017096``: This applies errata 2017096 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_A710_2083908``: This applies errata 2083908 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revision r2p0 of the CPU and
|
||||
is still open.
|
||||
|
||||
- ``ERRATA_A710_2058056``: This applies errata 2058056 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_A710_2267065``: This applies errata 2267065 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2136059``: This applies errata 2136059 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2147715``: This applies errata 2147715 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revision r2p0 of the CPU
|
||||
and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2216384``: This applies errata 2216384 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2282622``: This applies errata 2282622 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0, r2p0 and
|
||||
r2p1 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_A710_2291219``: This applies errata 2291219 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2008768``: This applies errata 2008768 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2371105``: This applies errata 2371105 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
|
||||
of the CPU and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_A710_2701952``: This applies erratum 2701952 workaround to Cortex-A710
|
||||
CPU, and applies to system configurations that do not use and ARM
|
||||
interconnect IP. This needs to be enabled for r0p0, r1p0, r2p0 and r2p1 and
|
||||
is still open.
|
||||
|
||||
- ``ERRATA_A710_2768515``: This applies errata 2768515 workaround to
|
||||
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0, r2p0 and
|
||||
r2p1 of the CPU and is still open.
|
||||
|
||||
For Neoverse N2, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU, it is still open.
|
||||
|
||||
- ``ERRATA_N2_2067956``: This applies errata 2067956 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2025414``: This applies errata 2025414 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2189731``: This applies errata 2189731 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2138956``: This applies errata 2138956 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2138953``: This applies errata 2138953 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2242415``: This applies errata 2242415 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2138958``: This applies errata 2138958 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2242400``: This applies errata 2242400 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2280757``: This applies errata 2280757 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
|
||||
|
||||
- ``ERRATA_N2_2326639``: This applies errata 2326639 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU, it is fixed in
|
||||
r0p1.
|
||||
|
||||
- ``ERRATA_N2_2376738``: This applies errata 2376738 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU, it is fixed in
|
||||
r0p1.
|
||||
|
||||
- ``ERRATA_N2_2388450``: This applies errata 2388450 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revision r0p0 of the CPU, it is fixed in
|
||||
r0p1.
|
||||
|
||||
- ``ERRATA_N2_2743089``: This applies errata 2743089 workaround to Neoverse-N2
|
||||
CPU. This needs to be enabled for revisions r0p0, r0p1 and r0p2. It is fixed
|
||||
in r0p3.
|
||||
|
||||
- ``ERRATA_N2_2728475``: This applies erratum 2728475 workaround to Neoverse-N2
|
||||
CPU, this erratum affects system configurations that do not use and ARM
|
||||
interconnect IP. This needs to be enabled for revisions r0p0, r0p1 and r0p2.
|
||||
It is fixed in r0p3.
|
||||
|
||||
For Cortex-X2, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_X2_2002765``: This applies errata 2002765 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU,
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_X2_2058056``: This applies errata 2058056 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU,
|
||||
it is still open.
|
||||
|
||||
- ``ERRATA_X2_2083908``: This applies errata 2083908 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled for revision r2p0 of the CPU, it is still open.
|
||||
|
||||
- ``ERRATA_X2_2017096``: This applies errata 2017096 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled only for revisions r0p0, r1p0 and r2p0 of the
|
||||
CPU, it is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_X2_2081180``: This applies errata 2081180 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled only for revisions r0p0, r1p0 and r2p0 of the
|
||||
CPU, it is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_X2_2216384``: This applies errata 2216384 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled only for revisions r0p0, r1p0 and r2p0 of the
|
||||
CPU, it is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_X2_2147715``: This applies errata 2147715 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled only for revision r2p0 of the CPU, it is fixed
|
||||
in r2p1.
|
||||
|
||||
- ``ERRATA_X2_2282622``: This applies errata 2282622 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r2p0 and r2p1 of the
|
||||
CPU and is still open.
|
||||
|
||||
- ``ERRATA_X2_2371105``: This applies errata 2371105 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 of the CPU
|
||||
and is fixed in r2p1.
|
||||
|
||||
- ``ERRATA_X2_2701952``: This applies erratum 2701952 workaround to Cortex-X2
|
||||
CPU and affects system configurations that do not use an ARM interconnect IP.
|
||||
This needs to be enabled for revisions r0p0, r1p0, r2p0 and r2p1 and is
|
||||
still open.
|
||||
|
||||
- ``ERRATA_X2_2768515``: This applies errata 2768515 workaround to Cortex-X2
|
||||
CPU. This needs to be enabled for revisions r0p0, r1p0, r2p0 and r2p1 of the
|
||||
CPU and is still open.
|
||||
|
||||
For Cortex-X3, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_X3_2313909``: This applies errata 2313909 workaround to
|
||||
Cortex-X3 CPU. This needs to be enabled only for revisions r0p0 and r1p0
|
||||
of the CPU, it is fixed in r1p1.
|
||||
|
||||
- ``ERRATA_X3_2615812``: This applies errata 2615812 workaround to Cortex-X3
|
||||
CPU. This needs to be enabled only for revisions r0p0, r1p0 and r1p1 of the
|
||||
CPU, it is still open.
|
||||
|
||||
For Cortex-A510, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled only for revision r0p0, it is
|
||||
fixed in r0p1.
|
||||
|
||||
- ``ERRATA_A510_2288014``: This applies errata 2288014 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1,
|
||||
r0p2, r0p3 and r1p0, it is fixed in r1p1.
|
||||
|
||||
- ``ERRATA_A510_2042739``: This applies errata 2042739 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1 and
|
||||
r0p2, it is fixed in r0p3.
|
||||
|
||||
- ``ERRATA_A510_2041909``: This applies errata 2041909 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled only for revision r0p2 and is fixed
|
||||
in r0p3. The issue is also present in r0p0 and r0p1 but there is no
|
||||
workaround for those revisions.
|
||||
|
||||
- ``ERRATA_A510_2250311``: This applies errata 2250311 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
|
||||
r0p3 and r1p0, it is fixed in r1p1. This workaround disables MPMM even if
|
||||
ENABLE_MPMM=1.
|
||||
|
||||
- ``ERRATA_A510_2218950``: This applies errata 2218950 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
|
||||
r0p3 and r1p0, it is fixed in r1p1.
|
||||
|
||||
- ``ERRATA_A510_2172148``: This applies errata 2172148 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
|
||||
r0p3 and r1p0, it is fixed in r1p1.
|
||||
|
||||
- ``ERRATA_A510_2347730``: This applies errata 2347730 workaround to
|
||||
Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
|
||||
r0p3, r1p0 and r1p1. It is fixed in r1p2.
|
||||
|
||||
- ``ERRATA_A510_2371937``: This applies errata 2371937 workaround to
|
||||
Cortex-A510 CPU. This needs to applied for revisions r0p0, r0p1, r0p2,
|
||||
r0p3, r1p0, r1p1, and is fixed in r1p2.
|
||||
|
||||
- ``ERRATA_A510_2666669``: This applies errata 2666669 workaround to
|
||||
Cortex-A510 CPU. This needs to applied for revisions r0p0, r0p1, r0p2,
|
||||
r0p3, r1p0, r1p1. It is fixed in r1p2.
|
||||
|
||||
- ``ERRATA_A510_2684597``: This applies erratum 2684597 workaround to
|
||||
Cortex-A510 CPU. This needs to be applied to revision r0p0, r0p1, r0p2,
|
||||
r0p3, r1p0, r1p1 and r1p2. It is fixed in r1p3.
|
||||
|
||||
For Cortex-A715, the following errata build flags are defined :
|
||||
|
||||
- ``ERRATA_A715_2701951``: This applies erratum 2701951 workaround to Cortex-A715
|
||||
CPU and affects system configurations that do not use an ARM interconnect
|
||||
IP. This needs to be applied to revisions r0p0, r1p0 and r1p1. It is fixed
|
||||
in r1p2.
|
||||
|
||||
DSU Errata Workarounds
|
||||
----------------------
|
||||
|
||||
Similar to CPU errata, TF-A also implements workarounds for DSU (DynamIQ
|
||||
Shared Unit) errata. The DSU errata details can be found in the respective Arm
|
||||
documentation:
|
||||
|
||||
- `Arm DSU Software Developers Errata Notice`_.
|
||||
|
||||
Each erratum is identified by an ``ID``, as defined in the DSU errata notice
|
||||
document. Thus, the build flags which enable/disable the errata workarounds
|
||||
have the format ``ERRATA_DSU_<ID>``. The implementation and application logic
|
||||
of DSU errata workarounds are similar to `CPU errata workarounds`_.
|
||||
|
||||
For DSU errata, the following build flags are defined:
|
||||
|
||||
- ``ERRATA_DSU_798953``: This applies errata 798953 workaround for the
|
||||
affected DSU configurations. This errata applies only for those DSUs that
|
||||
revision is r0p0 (on r0p1 it is fixed). However, please note that this
|
||||
workaround results in increased DSU power consumption on idle.
|
||||
|
||||
- ``ERRATA_DSU_936184``: This applies errata 936184 workaround for the
|
||||
affected DSU configurations. This errata applies only for those DSUs that
|
||||
contain the ACP interface **and** the DSU revision is older than r2p0 (on
|
||||
r2p0 it is fixed). However, please note that this workaround results in
|
||||
increased DSU power consumption on idle.
|
||||
|
||||
- ``ERRATA_DSU_2313941``: This applies errata 2313941 workaround for the
|
||||
affected DSU configurations. This errata applies for those DSUs with
|
||||
revisions r0p0, r1p0, r2p0, r2p1, r3p0, r3p1 and is still open. However,
|
||||
please note that this workaround results in increased DSU power consumption
|
||||
on idle.
|
||||
|
||||
CPU Specific optimizations
|
||||
--------------------------
|
||||
|
||||
This section describes some of the optimizations allowed by the CPU micro
|
||||
architecture that can be enabled by the platform as desired.
|
||||
|
||||
- ``SKIP_A57_L1_FLUSH_PWR_DWN``: This flag enables an optimization in the
|
||||
Cortex-A57 cluster power down sequence by not flushing the Level 1 data
|
||||
cache. The L1 data cache and the L2 unified cache are inclusive. A flush
|
||||
of the L2 by set/way flushes any dirty lines from the L1 as well. This
|
||||
is a known safe deviation from the Cortex-A57 TRM defined power down
|
||||
sequence. Each Cortex-A57 based platform must make its own decision on
|
||||
whether to use the optimization.
|
||||
|
||||
- ``A53_DISABLE_NON_TEMPORAL_HINT``: This flag disables the cache non-temporal
|
||||
hint. The LDNP/STNP instructions as implemented on Cortex-A53 do not behave
|
||||
in a way most programmers expect, and will most probably result in a
|
||||
significant speed degradation to any code that employs them. The Armv8-A
|
||||
architecture (see Arm DDI 0487A.h, section D3.4.3) allows cores to ignore
|
||||
the non-temporal hint and treat LDNP/STNP as LDP/STP instead. Enabling this
|
||||
flag enforces this behaviour. This needs to be enabled only for revisions
|
||||
<= r0p3 of the CPU and is enabled by default.
|
||||
|
||||
- ``A57_DISABLE_NON_TEMPORAL_HINT``: This flag has the same behaviour as
|
||||
``A53_DISABLE_NON_TEMPORAL_HINT`` but for Cortex-A57. This needs to be
|
||||
enabled only for revisions <= r1p2 of the CPU and is enabled by default,
|
||||
as recommended in section "4.7 Non-Temporal Loads/Stores" of the
|
||||
`Cortex-A57 Software Optimization Guide`_.
|
||||
|
||||
- ''A57_ENABLE_NON_CACHEABLE_LOAD_FWD'': This flag enables non-cacheable
|
||||
streaming enhancement feature for Cortex-A57 CPUs. Platforms can set
|
||||
this bit only if their memory system meets the requirement that cache
|
||||
line fill requests from the Cortex-A57 processor are atomic. Each
|
||||
Cortex-A57 based platform must make its own decision on whether to use
|
||||
the optimization. This flag is disabled by default.
|
||||
|
||||
- ``NEOVERSE_Nx_EXTERNAL_LLC``: This flag indicates that an external last
|
||||
level cache(LLC) is present in the system, and that the DataSource field
|
||||
on the master CHI interface indicates when data is returned from the LLC.
|
||||
This is used to control how the LL_CACHE* PMU events count.
|
||||
Default value is 0 (Disabled).
|
||||
|
||||
GIC Errata Workarounds
|
||||
----------------------
|
||||
- ``GIC600_ERRATA_WA_2384374``: This flag applies part 2 of errata 2384374
|
||||
workaround for the affected GIC600 and GIC600-AE implementations. It applies
|
||||
to implementations of GIC600 and GIC600-AE with revisions less than or equal
|
||||
to r1p6 and r0p2 respectively. If the platform sets GICV3_SUPPORT_GIC600,
|
||||
then this flag is enabled; otherwise, it is 0 (Disabled).
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
|
||||
.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639
|
||||
.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960
|
||||
.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html
|
||||
.. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/index.html
|
||||
.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html
|
||||
.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf
|
||||
.. _Arm DSU Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm138168/index.html
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
System Design
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Contents
|
||||
|
||||
alt-boot-flows
|
||||
auth-framework
|
||||
cpu-specific-build-macros
|
||||
firmware-design
|
||||
interrupt-framework-design
|
||||
psci-pd-tree
|
||||
reset-design
|
||||
trusted-board-boot
|
||||
trusted-board-boot-build
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2019, Arm Limited. All rights reserved.*
|
||||
+1021
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,304 @@
|
||||
PSCI Power Domain Tree Structure
|
||||
================================
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
#. A platform must export the ``plat_get_aff_count()`` and
|
||||
``plat_get_aff_state()`` APIs to enable the generic PSCI code to
|
||||
populate a tree that describes the hierarchy of power domains in the
|
||||
system. This approach is inflexible because a change to the topology
|
||||
requires a change in the code.
|
||||
|
||||
It would be much simpler for the platform to describe its power domain tree
|
||||
in a data structure.
|
||||
|
||||
#. The generic PSCI code generates MPIDRs in order to populate the power domain
|
||||
tree. It also uses an MPIDR to find a node in the tree. The assumption that
|
||||
a platform will use exactly the same MPIDRs as generated by the generic PSCI
|
||||
code is not scalable. The use of an MPIDR also restricts the number of
|
||||
levels in the power domain tree to four.
|
||||
|
||||
Therefore, there is a need to decouple allocation of MPIDRs from the
|
||||
mechanism used to populate the power domain topology tree.
|
||||
|
||||
#. The current arrangement of the power domain tree requires a binary search
|
||||
over the sibling nodes at a particular level to find a specified power
|
||||
domain node. During a power management operation, the tree is traversed from
|
||||
a 'start' to an 'end' power level. The binary search is required to find the
|
||||
node at each level. The natural way to perform this traversal is to
|
||||
start from a leaf node and follow the parent node pointer to reach the end
|
||||
level.
|
||||
|
||||
Therefore, there is a need to define data structures that implement the tree in
|
||||
a way which facilitates such a traversal.
|
||||
|
||||
#. The attributes of a core power domain differ from the attributes of power
|
||||
domains at higher levels. For example, only a core power domain can be identified
|
||||
using an MPIDR. There is no requirement to perform state coordination while
|
||||
performing a power management operation on the core power domain.
|
||||
|
||||
Therefore, there is a need to implement the tree in a way which facilitates this
|
||||
distinction between a leaf and non-leaf node and any associated
|
||||
optimizations.
|
||||
|
||||
--------------
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
Describing a power domain tree
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To fulfill requirement 1., the existing platform APIs
|
||||
``plat_get_aff_count()`` and ``plat_get_aff_state()`` have been
|
||||
removed. A platform must define an array of unsigned chars such that:
|
||||
|
||||
#. The first entry in the array specifies the number of power domains at the
|
||||
highest power level implemented in the platform. This caters for platforms
|
||||
where the power domain tree does not have a single root node, for example,
|
||||
the FVP has two cluster power domains at the highest level (1).
|
||||
|
||||
#. Each subsequent entry corresponds to a power domain and contains the number
|
||||
of power domains that are its direct children.
|
||||
|
||||
#. The size of the array minus the first entry will be equal to the number of
|
||||
non-leaf power domains.
|
||||
|
||||
#. The value in each entry in the array is used to find the number of entries
|
||||
to consider at the next level. The sum of the values (number of children) of
|
||||
all the entries at a level specifies the number of entries in the array for
|
||||
the next level.
|
||||
|
||||
The following example power domain topology tree will be used to describe the
|
||||
above text further. The leaf and non-leaf nodes in this tree have been numbered
|
||||
separately.
|
||||
|
||||
::
|
||||
|
||||
+-+
|
||||
|0|
|
||||
+-+
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
+-+ +-+
|
||||
|1| |2|
|
||||
+-+ +-+
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
+-+ +-+ +-+ +-+
|
||||
|3| |4| |5| |6|
|
||||
+-+ +-+ +-+ +-+
|
||||
+---+-----+ +----+----| +----+----+ +----+-----+-----+
|
||||
| | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | |
|
||||
v v v v v v v v v v v v v
|
||||
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+
|
||||
|0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |10| |11| |12|
|
||||
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+
|
||||
|
||||
This tree is defined by the platform as the array described above as follows:
|
||||
|
||||
.. code:: c
|
||||
|
||||
#define PLAT_NUM_POWER_DOMAINS 20
|
||||
#define PLATFORM_CORE_COUNT 13
|
||||
#define PSCI_NUM_NON_CPU_PWR_DOMAINS \
|
||||
(PLAT_NUM_POWER_DOMAINS - PLATFORM_CORE_COUNT)
|
||||
|
||||
unsigned char plat_power_domain_tree_desc[] = { 1, 2, 2, 2, 3, 3, 3, 4};
|
||||
|
||||
Removing assumptions about MPIDRs used in a platform
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To fulfill requirement 2., it is assumed that the platform assigns a
|
||||
unique number (core index) between ``0`` and ``PLAT_CORE_COUNT - 1`` to each core
|
||||
power domain. MPIDRs could be allocated in any manner and will not be used to
|
||||
populate the tree.
|
||||
|
||||
``plat_core_pos_by_mpidr(mpidr)`` will return the core index for the core
|
||||
corresponding to the MPIDR. It will return an error (-1) if an MPIDR is passed
|
||||
which is not allocated or corresponds to an absent core. The semantics of this
|
||||
platform API have changed since it is required to validate the passed MPIDR. It
|
||||
has been made a mandatory API as a result.
|
||||
|
||||
Another mandatory API, ``plat_my_core_pos()`` has been added to return the core
|
||||
index for the calling core. This API provides a more lightweight mechanism to get
|
||||
the index since there is no need to validate the MPIDR of the calling core.
|
||||
|
||||
The platform should assign the core indices (as illustrated in the diagram above)
|
||||
such that, if the core nodes are numbered from left to right, then the index
|
||||
for a core domain will be the same as the index returned by
|
||||
``plat_core_pos_by_mpidr()`` or ``plat_my_core_pos()`` for that core. This
|
||||
relationship allows the core nodes to be allocated in a separate array
|
||||
(requirement 4.) during ``psci_setup()`` in such an order that the index of the
|
||||
core in the array is the same as the return value from these APIs.
|
||||
|
||||
Dealing with holes in MPIDR allocation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For platforms where the number of allocated MPIDRs is equal to the number of
|
||||
core power domains, for example, Juno and FVPs, the logic to convert an MPIDR to
|
||||
a core index should remain unchanged. Both Juno and FVP use a simple collision
|
||||
proof hash function to do this.
|
||||
|
||||
It is possible that on some platforms, the allocation of MPIDRs is not
|
||||
contiguous or certain cores have been disabled. This essentially means that the
|
||||
MPIDRs have been sparsely allocated, that is, the size of the range of MPIDRs
|
||||
used by the platform is not equal to the number of core power domains.
|
||||
|
||||
The platform could adopt one of the following approaches to deal with this
|
||||
scenario:
|
||||
|
||||
#. Implement more complex logic to convert a valid MPIDR to a core index while
|
||||
maintaining the relationship described earlier. This means that the power
|
||||
domain tree descriptor will not describe any core power domains which are
|
||||
disabled or absent. Entries will not be allocated in the tree for these
|
||||
domains.
|
||||
|
||||
#. Treat unallocated MPIDRs and disabled cores as absent but still describe them
|
||||
in the power domain descriptor, that is, the number of core nodes described
|
||||
is equal to the size of the range of MPIDRs allocated. This approach will
|
||||
lead to memory wastage since entries will be allocated in the tree but will
|
||||
allow use of a simpler logic to convert an MPIDR to a core index.
|
||||
|
||||
Traversing through and distinguishing between core and non-core power domains
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To fulfill requirement 3 and 4, separate data structures have been defined
|
||||
to represent leaf and non-leaf power domain nodes in the tree.
|
||||
|
||||
.. code:: c
|
||||
|
||||
/*******************************************************************************
|
||||
* The following two data structures implement the power domain tree. The tree
|
||||
* is used to track the state of all the nodes i.e. power domain instances
|
||||
* described by the platform. The tree consists of nodes that describe CPU power
|
||||
* domains i.e. leaf nodes and all other power domains which are parents of a
|
||||
* CPU power domain i.e. non-leaf nodes.
|
||||
******************************************************************************/
|
||||
typedef struct non_cpu_pwr_domain_node {
|
||||
/*
|
||||
* Index of the first CPU power domain node level 0 which has this node
|
||||
* as its parent.
|
||||
*/
|
||||
unsigned int cpu_start_idx;
|
||||
|
||||
/*
|
||||
* Number of CPU power domains which are siblings of the domain indexed
|
||||
* by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx
|
||||
* -> cpu_start_idx + ncpus' have this node as their parent.
|
||||
*/
|
||||
unsigned int ncpus;
|
||||
|
||||
/* Index of the parent power domain node */
|
||||
unsigned int parent_node;
|
||||
|
||||
-----
|
||||
} non_cpu_pd_node_t;
|
||||
|
||||
typedef struct cpu_pwr_domain_node {
|
||||
u_register_t mpidr;
|
||||
|
||||
/* Index of the parent power domain node */
|
||||
unsigned int parent_node;
|
||||
|
||||
-----
|
||||
} cpu_pd_node_t;
|
||||
|
||||
The power domain tree is implemented as a combination of the following data
|
||||
structures.
|
||||
|
||||
.. code:: c
|
||||
|
||||
non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS];
|
||||
cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT];
|
||||
|
||||
Populating the power domain tree
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``populate_power_domain_tree()`` function in ``psci_setup.c`` implements the
|
||||
algorithm to parse the power domain descriptor exported by the platform to
|
||||
populate the two arrays. It is essentially a breadth-first-search. The nodes for
|
||||
each level starting from the root are laid out one after another in the
|
||||
``psci_non_cpu_pd_nodes`` and ``psci_cpu_pd_nodes`` arrays as follows:
|
||||
|
||||
::
|
||||
|
||||
psci_non_cpu_pd_nodes -> [[Level 3 nodes][Level 2 nodes][Level 1 nodes]]
|
||||
psci_cpu_pd_nodes -> [Level 0 nodes]
|
||||
|
||||
For the example power domain tree illustrated above, the ``psci_cpu_pd_nodes``
|
||||
will be populated as follows. The value in each entry is the index of the parent
|
||||
node. Other fields have been ignored for simplicity.
|
||||
|
||||
::
|
||||
|
||||
+-------------+ ^
|
||||
CPU0 | 3 | |
|
||||
+-------------+ |
|
||||
CPU1 | 3 | |
|
||||
+-------------+ |
|
||||
CPU2 | 3 | |
|
||||
+-------------+ |
|
||||
CPU3 | 4 | |
|
||||
+-------------+ |
|
||||
CPU4 | 4 | |
|
||||
+-------------+ |
|
||||
CPU5 | 4 | | PLATFORM_CORE_COUNT
|
||||
+-------------+ |
|
||||
CPU6 | 5 | |
|
||||
+-------------+ |
|
||||
CPU7 | 5 | |
|
||||
+-------------+ |
|
||||
CPU8 | 5 | |
|
||||
+-------------+ |
|
||||
CPU9 | 6 | |
|
||||
+-------------+ |
|
||||
CPU10 | 6 | |
|
||||
+-------------+ |
|
||||
CPU11 | 6 | |
|
||||
+-------------+ |
|
||||
CPU12 | 6 | v
|
||||
+-------------+
|
||||
|
||||
The ``psci_non_cpu_pd_nodes`` array will be populated as follows. The value in
|
||||
each entry is the index of the parent node.
|
||||
|
||||
::
|
||||
|
||||
+-------------+ ^
|
||||
PD0 | -1 | |
|
||||
+-------------+ |
|
||||
PD1 | 0 | |
|
||||
+-------------+ |
|
||||
PD2 | 0 | |
|
||||
+-------------+ |
|
||||
PD3 | 1 | | PLAT_NUM_POWER_DOMAINS -
|
||||
+-------------+ | PLATFORM_CORE_COUNT
|
||||
PD4 | 1 | |
|
||||
+-------------+ |
|
||||
PD5 | 2 | |
|
||||
+-------------+ |
|
||||
PD6 | 2 | |
|
||||
+-------------+ v
|
||||
|
||||
Each core can find its node in the ``psci_cpu_pd_nodes`` array using the
|
||||
``plat_my_core_pos()`` function. When a core is turned on, the normal world
|
||||
provides an MPIDR. The ``plat_core_pos_by_mpidr()`` function is used to validate
|
||||
the MPIDR before using it to find the corresponding core node. The non-core power
|
||||
domain nodes do not need to be identified.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.*
|
||||
@@ -0,0 +1,168 @@
|
||||
CPU Reset
|
||||
=========
|
||||
|
||||
This document describes the high-level design of the framework to handle CPU
|
||||
resets in Trusted Firmware-A (TF-A). It also describes how the platform
|
||||
integrator can tailor this code to the system configuration to some extent,
|
||||
resulting in a simplified and more optimised boot flow.
|
||||
|
||||
This document should be used in conjunction with the :ref:`Firmware Design`
|
||||
document which provides greater implementation details around the reset code,
|
||||
specifically for the cold boot path.
|
||||
|
||||
General reset code flow
|
||||
-----------------------
|
||||
|
||||
The TF-A reset code is implemented in BL1 by default. The following high-level
|
||||
diagram illustrates this:
|
||||
|
||||
|Default reset code flow|
|
||||
|
||||
This diagram shows the default, unoptimised reset flow. Depending on the system
|
||||
configuration, some of these steps might be unnecessary. The following sections
|
||||
guide the platform integrator by indicating which build options exclude which
|
||||
steps, depending on the capability of the platform.
|
||||
|
||||
.. note::
|
||||
If BL31 is used as the TF-A entry point instead of BL1, the diagram
|
||||
above is still relevant, as all these operations will occur in BL31 in
|
||||
this case. Please refer to section 6 "Using BL31 entrypoint as the reset
|
||||
address" for more information.
|
||||
|
||||
Programmable CPU reset address
|
||||
------------------------------
|
||||
|
||||
By default, TF-A assumes that the CPU reset address is not programmable.
|
||||
Therefore, all CPUs start at the same address (typically address 0) whenever
|
||||
they reset. Further logic is then required to identify whether it is a cold or
|
||||
warm boot to direct CPUs to the right execution path.
|
||||
|
||||
If the reset vector address (reflected in the reset vector base address register
|
||||
``RVBAR_EL3``) is programmable then it is possible to make each CPU start directly
|
||||
at the right address, both on a cold and warm reset. Therefore, the boot type
|
||||
detection can be skipped, resulting in the following boot flow:
|
||||
|
||||
|Reset code flow with programmable reset address|
|
||||
|
||||
To enable this boot flow, compile TF-A with ``PROGRAMMABLE_RESET_ADDRESS=1``.
|
||||
This option only affects the TF-A reset image, which is BL1 by default or BL31 if
|
||||
``RESET_TO_BL31=1``.
|
||||
|
||||
On both the FVP and Juno platforms, the reset vector address is not programmable
|
||||
so both ports use ``PROGRAMMABLE_RESET_ADDRESS=0``.
|
||||
|
||||
Cold boot on a single CPU
|
||||
-------------------------
|
||||
|
||||
By default, TF-A assumes that several CPUs may be released out of reset.
|
||||
Therefore, the cold boot code has to arbitrate access to hardware resources
|
||||
shared amongst CPUs. This is done by nominating one of the CPUs as the primary,
|
||||
which is responsible for initialising shared hardware and coordinating the boot
|
||||
flow with the other CPUs.
|
||||
|
||||
If the platform guarantees that only a single CPU will ever be brought up then
|
||||
no arbitration is required. The notion of primary/secondary CPU itself no longer
|
||||
applies. This results in the following boot flow:
|
||||
|
||||
|Reset code flow with single CPU released out of reset|
|
||||
|
||||
To enable this boot flow, compile TF-A with ``COLD_BOOT_SINGLE_CPU=1``. This
|
||||
option only affects the TF-A reset image, which is BL1 by default or BL31 if
|
||||
``RESET_TO_BL31=1``.
|
||||
|
||||
On both the FVP and Juno platforms, although only one core is powered up by
|
||||
default, there are platform-specific ways to release any number of cores out of
|
||||
reset. Therefore, both platform ports use ``COLD_BOOT_SINGLE_CPU=0``.
|
||||
|
||||
Programmable CPU reset address, Cold boot on a single CPU
|
||||
---------------------------------------------------------
|
||||
|
||||
It is obviously possible to combine both optimisations on platforms that have
|
||||
a programmable CPU reset address and which release a single CPU out of reset.
|
||||
This results in the following boot flow:
|
||||
|
||||
|
||||
|Reset code flow with programmable reset address and single CPU released out of reset|
|
||||
|
||||
To enable this boot flow, compile TF-A with both ``COLD_BOOT_SINGLE_CPU=1``
|
||||
and ``PROGRAMMABLE_RESET_ADDRESS=1``. These options only affect the TF-A reset
|
||||
image, which is BL1 by default or BL31 if ``RESET_TO_BL31=1``.
|
||||
|
||||
Using BL31 entrypoint as the reset address
|
||||
------------------------------------------
|
||||
|
||||
On some platforms the runtime firmware (BL3x images) for the application
|
||||
processors are loaded by some firmware running on a secure system processor
|
||||
on the SoC, rather than by BL1 and BL2 running on the primary application
|
||||
processor. For this type of SoC it is desirable for the application processor
|
||||
to always reset to BL31 which eliminates the need for BL1 and BL2.
|
||||
|
||||
TF-A provides a build-time option ``RESET_TO_BL31`` that includes some additional
|
||||
logic in the BL31 entry point to support this use case.
|
||||
|
||||
In this configuration, the platform's Trusted Boot Firmware must ensure that
|
||||
BL31 is loaded to its runtime address, which must match the CPU's ``RVBAR_EL3``
|
||||
reset vector base address, before the application processor is powered on.
|
||||
Additionally, platform software is responsible for loading the other BL3x images
|
||||
required and providing entry point information for them to BL31. Loading these
|
||||
images might be done by the Trusted Boot Firmware or by platform code in BL31.
|
||||
|
||||
Although the Arm FVP platform does not support programming the reset base
|
||||
address dynamically at run-time, it is possible to set the initial value of the
|
||||
``RVBAR_EL3`` register at start-up. This feature is provided on the Base FVP
|
||||
only.
|
||||
|
||||
It allows the Arm FVP port to support the ``RESET_TO_BL31`` configuration, in
|
||||
which case the ``bl31.bin`` image must be loaded to its run address in Trusted
|
||||
SRAM and all CPU reset vectors be changed from the default ``0x0`` to this run
|
||||
address. See the :ref:`Arm Fixed Virtual Platforms (FVP)` for details of running
|
||||
the FVP models in this way.
|
||||
|
||||
Although technically it would be possible to program the reset base address with
|
||||
the right support in the SCP firmware, this is currently not implemented so the
|
||||
Juno port doesn't support the ``RESET_TO_BL31`` configuration.
|
||||
|
||||
The ``RESET_TO_BL31`` configuration requires some additions and changes in the
|
||||
BL31 functionality:
|
||||
|
||||
Determination of boot path
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In this configuration, BL31 uses the same reset framework and code as the one
|
||||
described for BL1 above. Therefore, it is affected by the
|
||||
``PROGRAMMABLE_RESET_ADDRESS`` and ``COLD_BOOT_SINGLE_CPU`` build options in the
|
||||
same way.
|
||||
|
||||
In the default, unoptimised BL31 reset flow, on a warm boot a CPU is directed
|
||||
to the PSCI implementation via a platform defined mechanism. On a cold boot,
|
||||
the platform must place any secondary CPUs into a safe state while the primary
|
||||
CPU executes a modified BL31 initialization, as described below.
|
||||
|
||||
Platform initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In this configuration, when the CPU resets to BL31 there should be no parameters
|
||||
that can be passed in registers by previous boot stages. Instead, the platform
|
||||
code in BL31 needs to know, or be able to determine, the location of the BL32
|
||||
(if required) and BL33 images and provide this information in response to the
|
||||
``bl31_plat_get_next_image_ep_info()`` function.
|
||||
|
||||
.. note::
|
||||
Some platforms that configure ``RESET_TO_BL31`` might still be able to
|
||||
receive parameters in registers depending on their actual boot sequence. On
|
||||
those occasions, and in addition to ``RESET_TO_BL31``, these platforms should
|
||||
set ``RESET_TO_BL31_WITH_PARAMS`` to avoid the input registers from being
|
||||
zeroed before entering BL31.
|
||||
|
||||
Additionally, platform software is responsible for carrying out any security
|
||||
initialisation, for example programming a TrustZone address space controller.
|
||||
This might be done by the Trusted Boot Firmware or by platform code in BL31.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. |Default reset code flow| image:: ../resources/diagrams/default_reset_code.png
|
||||
.. |Reset code flow with programmable reset address| image:: ../resources/diagrams/reset_code_no_boot_type_check.png
|
||||
.. |Reset code flow with single CPU released out of reset| image:: ../resources/diagrams/reset_code_no_cpu_check.png
|
||||
.. |Reset code flow with programmable reset address and single CPU released out of reset| image:: ../resources/diagrams/reset_code_no_checks.png
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
Building FIP images with support for Trusted Board Boot
|
||||
=======================================================
|
||||
|
||||
Trusted Board Boot primarily consists of the following two features:
|
||||
|
||||
- Image Authentication, described in :ref:`Trusted Board Boot`, and
|
||||
- Firmware Update, described in :ref:`Firmware Update (FWU)`
|
||||
|
||||
The following steps should be followed to build FIP and (optionally) FWU_FIP
|
||||
images with support for these features:
|
||||
|
||||
#. Fulfill the dependencies of the ``mbedtls`` cryptographic and image parser
|
||||
modules by checking out a recent version of the `mbed TLS Repository`_. It
|
||||
is important to use a version that is compatible with TF-A and fixes any
|
||||
known security vulnerabilities. See `mbed TLS Security Center`_ for more
|
||||
information. See the :ref:`Prerequisites` document for the appropriate
|
||||
version of mbed TLS to use.
|
||||
|
||||
The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS
|
||||
source files the modules depend upon.
|
||||
``include/drivers/auth/mbedtls/mbedtls_config.h`` contains the configuration
|
||||
options required to build the mbed TLS sources.
|
||||
|
||||
Note that the mbed TLS library is licensed under the Apache version 2.0
|
||||
license. Using mbed TLS source code will affect the licensing of TF-A
|
||||
binaries that are built using this library.
|
||||
|
||||
#. To build the FIP image, ensure the following command line variables are set
|
||||
while invoking ``make`` to build TF-A:
|
||||
|
||||
- ``MBEDTLS_DIR=<path of the directory containing mbed TLS sources>``
|
||||
- ``TRUSTED_BOARD_BOOT=1``
|
||||
- ``GENERATE_COT=1``
|
||||
|
||||
By default, this will use the Chain of Trust described in the TBBR-client
|
||||
document. To select a different one, use the ``COT`` build option.
|
||||
|
||||
If using a custom build of OpenSSL, set the ``OPENSSL_DIR`` variable
|
||||
accordingly so it points at the OpenSSL installation path, as explained in
|
||||
:ref:`Build Options`. In addition, set the ``LD_LIBRARY_PATH`` variable
|
||||
when running to point at the custom OpenSSL path, so the OpenSSL libraries
|
||||
are loaded from that path instead of the default OS path. Export this
|
||||
variable if necessary.
|
||||
|
||||
In the case of Arm platforms, the location of the ROTPK hash must also be
|
||||
specified at build time. The following locations are currently supported (see
|
||||
``ARM_ROTPK_LOCATION`` build option):
|
||||
|
||||
- ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted
|
||||
root-key storage registers present in the platform. On Juno, these
|
||||
registers are read-only. On FVP Base and Cortex models, the registers
|
||||
are also read-only, but the value can be specified using the command line
|
||||
option ``bp.trusted_key_storage.public_key`` when launching the model.
|
||||
On Juno board, the default value corresponds to an ECDSA-SECP256R1 public
|
||||
key hash, whose private part is not currently available.
|
||||
|
||||
- ``ARM_ROTPK_LOCATION=devel_rsa``: use the default hash located in
|
||||
``plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin``. Enforce
|
||||
generation of the new hash if ``ROT_KEY`` is specified.
|
||||
|
||||
- ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the default hash located in
|
||||
``plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin``. Enforce
|
||||
generation of the new hash if ``ROT_KEY`` is specified.
|
||||
|
||||
Example of command line using RSA development keys:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
MBEDTLS_DIR=<path of the directory containing mbed TLS sources> \
|
||||
make PLAT=<platform> TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
|
||||
ARM_ROTPK_LOCATION=devel_rsa \
|
||||
ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
|
||||
BL33=<path-to>/<bl33_image> OPENSSL_DIR=<path-to>/<openssl> \
|
||||
all fip
|
||||
|
||||
The result of this build will be the bl1.bin and the fip.bin binaries. This
|
||||
FIP will include the certificates corresponding to the selected Chain of
|
||||
Trust. These certificates can also be found in the output build directory.
|
||||
|
||||
#. The optional FWU_FIP contains any additional images to be loaded from
|
||||
Non-Volatile storage during the :ref:`Firmware Update (FWU)` process. To build the
|
||||
FWU_FIP, any FWU images required by the platform must be specified on the
|
||||
command line. On Arm development platforms like Juno, these are:
|
||||
|
||||
- NS_BL2U. The AP non-secure Firmware Updater image.
|
||||
- SCP_BL2U. The SCP Firmware Update Configuration image.
|
||||
|
||||
Example of Juno command line for generating both ``fwu`` and ``fwu_fip``
|
||||
targets using RSA development:
|
||||
|
||||
::
|
||||
|
||||
MBEDTLS_DIR=<path of the directory containing mbed TLS sources> \
|
||||
make PLAT=juno TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
|
||||
ARM_ROTPK_LOCATION=devel_rsa \
|
||||
ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
|
||||
BL33=<path-to>/<bl33_image> OPENSSL_DIR=<path-to>/<openssl> \
|
||||
SCP_BL2=<path-to>/<scp_bl2_image> \
|
||||
SCP_BL2U=<path-to>/<scp_bl2u_image> \
|
||||
NS_BL2U=<path-to>/<ns_bl2u_image> \
|
||||
all fip fwu_fip
|
||||
|
||||
.. note::
|
||||
The BL2U image will be built by default and added to the FWU_FIP.
|
||||
The user may override this by adding ``BL2U=<path-to>/<bl2u_image>``
|
||||
to the command line above.
|
||||
|
||||
.. note::
|
||||
Building and installing the non-secure and SCP FWU images (NS_BL1U,
|
||||
NS_BL2U and SCP_BL2U) is outside the scope of this document.
|
||||
|
||||
The result of this build will be bl1.bin, fip.bin and fwu_fip.bin binaries.
|
||||
Both the FIP and FWU_FIP will include the certificates corresponding to the
|
||||
selected Chain of Trust. These certificates can also be found in the output
|
||||
build directory.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2019-2022, Arm Limited. All rights reserved.*
|
||||
|
||||
.. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git
|
||||
.. _mbed TLS Security Center: https://tls.mbed.org/security
|
||||
@@ -0,0 +1,263 @@
|
||||
Trusted Board Boot
|
||||
==================
|
||||
|
||||
The Trusted Board Boot (TBB) feature prevents malicious firmware from running on
|
||||
the platform by authenticating all firmware images up to and including the
|
||||
normal world bootloader. It does this by establishing a Chain of Trust using
|
||||
Public-Key-Cryptography Standards (PKCS).
|
||||
|
||||
This document describes the design of Trusted Firmware-A (TF-A) TBB, which is an
|
||||
implementation of the `Trusted Board Boot Requirements (TBBR)`_ specification,
|
||||
Arm DEN0006D. It should be used in conjunction with the
|
||||
:ref:`Firmware Update (FWU)` design document, which implements a specific aspect
|
||||
of the TBBR.
|
||||
|
||||
Chain of Trust
|
||||
--------------
|
||||
|
||||
A Chain of Trust (CoT) starts with a set of implicitly trusted components. On
|
||||
the Arm development platforms, these components are:
|
||||
|
||||
- A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the
|
||||
trusted root-key storage registers. Alternatively, a development ROTPK might
|
||||
be used and its hash embedded into the BL1 and BL2 images (only for
|
||||
development purposes).
|
||||
|
||||
- The BL1 image, on the assumption that it resides in ROM so cannot be
|
||||
tampered with.
|
||||
|
||||
The remaining components in the CoT are either certificates or boot loader
|
||||
images. The certificates follow the `X.509 v3`_ standard. This standard
|
||||
enables adding custom extensions to the certificates, which are used to store
|
||||
essential information to establish the CoT.
|
||||
|
||||
In the TBB CoT all certificates are self-signed. There is no need for a
|
||||
Certificate Authority (CA) because the CoT is not established by verifying the
|
||||
validity of a certificate's issuer but by the content of the certificate
|
||||
extensions. To sign the certificates, different signature schemes are available,
|
||||
please refer to the :ref:`Build Options` for more details.
|
||||
|
||||
The certificates are categorised as "Key" and "Content" certificates. Key
|
||||
certificates are used to verify public keys which have been used to sign content
|
||||
certificates. Content certificates are used to store the hash of a boot loader
|
||||
image. An image can be authenticated by calculating its hash and matching it
|
||||
with the hash extracted from the content certificate. Various hash algorithms
|
||||
are supported to calculate all hashes, please refer to the :ref:`Build Options`
|
||||
for more details.. The public keys and hashes are included as non-standard
|
||||
extension fields in the `X.509 v3`_ certificates.
|
||||
|
||||
The keys used to establish the CoT are:
|
||||
|
||||
- **Root of trust key**
|
||||
|
||||
The private part of this key is used to sign the BL2 content certificate and
|
||||
the trusted key certificate. The public part is the ROTPK.
|
||||
|
||||
- **Trusted world key**
|
||||
|
||||
The private part is used to sign the key certificates corresponding to the
|
||||
secure world images (SCP_BL2, BL31 and BL32). The public part is stored in
|
||||
one of the extension fields in the trusted world certificate.
|
||||
|
||||
- **Non-trusted world key**
|
||||
|
||||
The private part is used to sign the key certificate corresponding to the
|
||||
non secure world image (BL33). The public part is stored in one of the
|
||||
extension fields in the trusted world certificate.
|
||||
|
||||
- **BL3X keys**
|
||||
|
||||
For each of SCP_BL2, BL31, BL32 and BL33, the private part is used to
|
||||
sign the content certificate for the BL3X image. The public part is stored
|
||||
in one of the extension fields in the corresponding key certificate.
|
||||
|
||||
The following images are included in the CoT:
|
||||
|
||||
- BL1
|
||||
- BL2
|
||||
- SCP_BL2 (optional)
|
||||
- BL31
|
||||
- BL33
|
||||
- BL32 (optional)
|
||||
|
||||
The following certificates are used to authenticate the images.
|
||||
|
||||
- **BL2 content certificate**
|
||||
|
||||
It is self-signed with the private part of the ROT key. It contains a hash
|
||||
of the BL2 image.
|
||||
|
||||
- **Trusted key certificate**
|
||||
|
||||
It is self-signed with the private part of the ROT key. It contains the
|
||||
public part of the trusted world key and the public part of the non-trusted
|
||||
world key.
|
||||
|
||||
- **SCP_BL2 key certificate**
|
||||
|
||||
It is self-signed with the trusted world key. It contains the public part of
|
||||
the SCP_BL2 key.
|
||||
|
||||
- **SCP_BL2 content certificate**
|
||||
|
||||
It is self-signed with the SCP_BL2 key. It contains a hash of the SCP_BL2
|
||||
image.
|
||||
|
||||
- **BL31 key certificate**
|
||||
|
||||
It is self-signed with the trusted world key. It contains the public part of
|
||||
the BL31 key.
|
||||
|
||||
- **BL31 content certificate**
|
||||
|
||||
It is self-signed with the BL31 key. It contains a hash of the BL31 image.
|
||||
|
||||
- **BL32 key certificate**
|
||||
|
||||
It is self-signed with the trusted world key. It contains the public part of
|
||||
the BL32 key.
|
||||
|
||||
- **BL32 content certificate**
|
||||
|
||||
It is self-signed with the BL32 key. It contains a hash of the BL32 image.
|
||||
|
||||
- **BL33 key certificate**
|
||||
|
||||
It is self-signed with the non-trusted world key. It contains the public
|
||||
part of the BL33 key.
|
||||
|
||||
- **BL33 content certificate**
|
||||
|
||||
It is self-signed with the BL33 key. It contains a hash of the BL33 image.
|
||||
|
||||
The SCP_BL2 and BL32 certificates are optional, but they must be present if the
|
||||
corresponding SCP_BL2 or BL32 images are present.
|
||||
|
||||
Trusted Board Boot Sequence
|
||||
---------------------------
|
||||
|
||||
The CoT is verified through the following sequence of steps. The system panics
|
||||
if any of the steps fail.
|
||||
|
||||
- BL1 loads and verifies the BL2 content certificate. The issuer public key is
|
||||
read from the verified certificate. A hash of that key is calculated and
|
||||
compared with the hash of the ROTPK read from the trusted root-key storage
|
||||
registers. If they match, the BL2 hash is read from the certificate.
|
||||
|
||||
.. note::
|
||||
The matching operation is platform specific and is currently
|
||||
unimplemented on the Arm development platforms.
|
||||
|
||||
- BL1 loads the BL2 image. Its hash is calculated and compared with the hash
|
||||
read from the certificate. Control is transferred to the BL2 image if all
|
||||
the comparisons succeed.
|
||||
|
||||
- BL2 loads and verifies the trusted key certificate. The issuer public key is
|
||||
read from the verified certificate. A hash of that key is calculated and
|
||||
compared with the hash of the ROTPK read from the trusted root-key storage
|
||||
registers. If the comparison succeeds, BL2 reads and saves the trusted and
|
||||
non-trusted world public keys from the verified certificate.
|
||||
|
||||
The next two steps are executed for each of the SCP_BL2, BL31 & BL32 images.
|
||||
The steps for the optional SCP_BL2 and BL32 images are skipped if these images
|
||||
are not present.
|
||||
|
||||
- BL2 loads and verifies the BL3x key certificate. The certificate signature
|
||||
is verified using the trusted world public key. If the signature
|
||||
verification succeeds, BL2 reads and saves the BL3x public key from the
|
||||
certificate.
|
||||
|
||||
- BL2 loads and verifies the BL3x content certificate. The signature is
|
||||
verified using the BL3x public key. If the signature verification succeeds,
|
||||
BL2 reads and saves the BL3x image hash from the certificate.
|
||||
|
||||
The next two steps are executed only for the BL33 image.
|
||||
|
||||
- BL2 loads and verifies the BL33 key certificate. If the signature
|
||||
verification succeeds, BL2 reads and saves the BL33 public key from the
|
||||
certificate.
|
||||
|
||||
- BL2 loads and verifies the BL33 content certificate. If the signature
|
||||
verification succeeds, BL2 reads and saves the BL33 image hash from the
|
||||
certificate.
|
||||
|
||||
The next step is executed for all the boot loader images.
|
||||
|
||||
- BL2 calculates the hash of each image. It compares it with the hash obtained
|
||||
from the corresponding content certificate. The image authentication succeeds
|
||||
if the hashes match.
|
||||
|
||||
The Trusted Board Boot implementation spans both generic and platform-specific
|
||||
BL1 and BL2 code, and in tool code on the host build machine. The feature is
|
||||
enabled through use of specific build flags as described in
|
||||
:ref:`Build Options`.
|
||||
|
||||
On the host machine, a tool generates the certificates, which are included in
|
||||
the FIP along with the boot loader images. These certificates are loaded in
|
||||
Trusted SRAM using the IO storage framework. They are then verified by an
|
||||
Authentication module included in TF-A.
|
||||
|
||||
The mechanism used for generating the FIP and the Authentication module are
|
||||
described in the following sections.
|
||||
|
||||
Authentication Framework
|
||||
------------------------
|
||||
|
||||
The authentication framework included in TF-A provides support to implement
|
||||
the desired trusted boot sequence. Arm platforms use this framework to
|
||||
implement the boot requirements specified in the
|
||||
`Trusted Board Boot Requirements (TBBR)`_ document.
|
||||
|
||||
More information about the authentication framework can be found in the
|
||||
:ref:`Authentication Framework & Chain of Trust` document.
|
||||
|
||||
Certificate Generation Tool
|
||||
---------------------------
|
||||
|
||||
The ``cert_create`` tool is built and runs on the host machine as part of the
|
||||
TF-A build process when ``GENERATE_COT=1``. It takes the boot loader images
|
||||
and keys as inputs (keys must be in PEM format) and generates the
|
||||
certificates (in DER format) required to establish the CoT. New keys can be
|
||||
generated by the tool in case they are not provided. The certificates are then
|
||||
passed as inputs to the ``fiptool`` utility for creating the FIP.
|
||||
|
||||
The certificates are also stored individually in the output build directory.
|
||||
|
||||
The tool resides in the ``tools/cert_create`` directory. It uses the OpenSSL SSL
|
||||
library version to generate the X.509 certificates. The specific version of the
|
||||
library that is required is given in the :ref:`Prerequisites` document.
|
||||
|
||||
Instructions for building and using the tool can be found at
|
||||
:ref:`tools_build_cert_create`.
|
||||
|
||||
Authenticated Encryption Framework
|
||||
----------------------------------
|
||||
|
||||
The authenticated encryption framework included in TF-A provides support to
|
||||
implement the optional firmware encryption feature. This feature can be
|
||||
optionally enabled on platforms to implement the optional requirement:
|
||||
R060_TBBR_FUNCTION as specified in the `Trusted Board Boot Requirements (TBBR)`_
|
||||
document.
|
||||
|
||||
Firmware Encryption Tool
|
||||
------------------------
|
||||
|
||||
The ``encrypt_fw`` tool is built and runs on the host machine as part of the
|
||||
TF-A build process when ``DECRYPTION_SUPPORT != none``. It takes the plain
|
||||
firmware image as input and generates the encrypted firmware image which can
|
||||
then be passed as input to the ``fiptool`` utility for creating the FIP.
|
||||
|
||||
The encrypted firmwares are also stored individually in the output build
|
||||
directory.
|
||||
|
||||
The tool resides in the ``tools/encrypt_fw`` directory. It uses OpenSSL SSL
|
||||
library version 1.0.1 or later to do authenticated encryption operation.
|
||||
Instructions for building and using the tool can be found in the
|
||||
:ref:`tools_build_enctool`.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt
|
||||
.. _Trusted Board Boot Requirements (TBBR): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
|
||||
Reference in New Issue
Block a user