diff --git a/acknowledgements.rst b/acknowledgements.rst new file mode 100644 index 0000000..59f569e --- /dev/null +++ b/acknowledgements.rst @@ -0,0 +1,16 @@ +Contributor Acknowledgements +============================ + +Companies +--------- + +Linaro Limited + +NVIDIA Corporation + +Socionext Inc. + +Xilinx, Inc. + +Individuals +----------- diff --git a/contributing.rst b/contributing.rst new file mode 100644 index 0000000..cdf0620 --- /dev/null +++ b/contributing.rst @@ -0,0 +1,129 @@ +Contributing to ARM Trusted Firmware +==================================== + +Getting Started +--------------- + +- Make sure you have a `GitHub account`_. +- Create an `issue`_ for your work if one does not already exist. This gives + everyone visibility of whether others are working on something similar. ARM + licensees may contact ARM directly via their partner managers instead if + they prefer. + + - Note that the `issue`_ tracker for this project is in a separate + `issue tracking repository`_. Please follow the guidelines in that + repository. + - If you intend to include Third Party IP in your contribution, please + raise a separate `issue`_ for this and ensure that the changes that + include Third Party IP are made on a separate topic branch. + +- `Fork`_ `arm-trusted-firmware`_ on GitHub. +- Clone the fork to your own machine. +- Create a local topic branch based on the `arm-trusted-firmware`_ ``master`` + branch. + +Making Changes +-------------- + +- Make commits of logical units. See these general `Git guidelines`_ for + contributing to a project. +- Follow the `Linux coding style`_; this style is enforced for the ARM Trusted + Firmware project (style errors only, not warnings). + + - Use the checkpatch.pl script provided with the Linux source tree. A + Makefile target is provided for convenience (see section 2 in the + `User Guide`_). + +- Keep the commits on topic. If you need to fix another bug or make another + enhancement, please create a separate `issue`_ and address it on a separate + topic branch. +- Avoid long commit series. If you do have a long series, consider whether + some commits should be squashed together or addressed in a separate topic. +- Make sure your commit messages are in the proper format. If a commit fixes + a GitHub `issue`_, include a reference (e.g. + "fixes arm-software/tf-issues#45"); this ensures the `issue`_ is + `automatically closed`_ when merged into the `arm-trusted-firmware`_ ``master`` + branch. +- Where appropriate, please update the documentation. + + - Consider whether the `User Guide`_, `Porting Guide`_, `Firmware Design`_ or + other in-source documentation needs updating. + - Ensure that each changed file has the correct copyright and license + information. Files that entirely consist of contributions to this + project should have the copyright notice and BSD-3-Clause SPDX license + identifier as shown in `license.rst`_. Files that contain + changes to imported Third Party IP should contain a notice as follows, + with the original copyright and license text retained: + + :: + + Portions copyright (c) [XXXX-]YYYY, ARM Limited and Contributors. All rights reserved. + + where XXXX is the year of first contribution (if different to YYYY) and + YYYY is the year of most recent contribution. + - If not done previously, you may add your name or your company name to + the `Acknowledgements`_ file. + - If you are submitting new files that you intend to be the technical + sub-maintainer for (for example, a new platform port), then also update + the `Maintainers`_ file. + - For topics with multiple commits, you should make all documentation + changes (and nothing else) in the last commit of the series. Otherwise, + include the documentation changes within the single commit. + +- Please test your changes. As a minimum, ensure UEFI boots to the shell on + the Foundation FVP. See `Running the software on FVP`_ for more information. + +Submitting Changes +------------------ + +- Ensure that each commit in the series has at least one ``Signed-off-by:`` + line, using your real name and email address. The names in the + ``Signed-off-by:`` and ``Author:`` lines must match. If anyone else contributes + to the commit, they must also add their own ``Signed-off-by:`` line. + By adding this line the contributor certifies the contribution is made under + the terms of the `Developer Certificate of Origin (DCO)`_. +- Push your local changes to your fork of the repository. +- Submit a `pull request`_ to the `arm-trusted-firmware`_ ``integration`` branch. + + - The changes in the `pull request`_ will then undergo further review and + testing by the `Maintainers`_. Any review comments will be made as + comments on the `pull request`_. This may require you to do some rework. + +- When the changes are accepted, the `Maintainers`_ will integrate them. + + - Typically, the `Maintainers`_ will merge the `pull request`_ into the + ``integration`` branch within the GitHub UI, creating a merge commit. + - Please avoid creating merge commits in the `pull request`_ itself. + - If the `pull request`_ is not based on a recent commit, the `Maintainers`_ + may rebase it onto the ``master`` branch first, or ask you to do this. + - If the `pull request`_ cannot be automatically merged, the `Maintainers`_ + will ask you to rebase it onto the ``master`` branch. + - After final integration testing, the `Maintainers`_ will push your merge + commit to the ``master`` branch. If a problem is found during integration, + the merge commit will be removed from the ``integration`` branch and the + `Maintainers`_ will ask you to create a new pull request to resolve the + problem. + - Please do not delete your topic branch until it is safely merged into + the ``master`` branch. + +-------------- + +*Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.* + +.. _GitHub account: https://github.com/signup/free +.. _issue: https://github.com/ARM-software/tf-issues/issues +.. _issue tracking repository: https://github.com/ARM-software/tf-issues +.. _Fork: https://help.github.com/articles/fork-a-repo +.. _arm-trusted-firmware: https://github.com/ARM-software/arm-trusted-firmware +.. _Git guidelines: http://git-scm.com/book/ch5-2.html +.. _Linux coding style: https://www.kernel.org/doc/Documentation/CodingStyle +.. _User Guide: ./docs/user-guide.rst +.. _automatically closed: https://help.github.com/articles/closing-issues-via-commit-messages +.. _Porting Guide: ./docs/porting-guide.rst +.. _Firmware Design: ./docs/firmware-design.rst +.. _license.rst: ./license.rst +.. _Acknowledgements: ./acknowledgements.rst +.. _Maintainers: ./maintainers.rst +.. _Running the software on FVP: ./docs/user-guide.rst#user-content-running-the-software-on-fvp +.. _Developer Certificate of Origin (DCO): ./dco.txt +.. _pull request: https://help.github.com/articles/using-pull-requests diff --git a/docs/arm-sip-service.rst b/docs/arm-sip-service.rst new file mode 100644 index 0000000..6d456c7 --- /dev/null +++ b/docs/arm-sip-service.rst @@ -0,0 +1,96 @@ +ARM SiP Service +=============== + +This document enumerates and describes the ARM SiP (Silicon Provider) services. + +SiP services are non-standard, platform-specific services offered by the silicon +implementer or platform provider. They are accessed via. ``SMC`` ("SMC calls") +instruction executed from Exception Levels below EL3. SMC calls for SiP +services: + +- Follow `SMC Calling Convention`_; +- Use SMC function IDs that fall in the SiP range, which are ``0xc2000000`` - + ``0xc200ffff`` for 64-bit calls, and ``0x82000000`` - ``0x8200ffff`` for 32-bit + calls. + +The ARM SiP implementation offers the following services: + +- Performance Measurement Framework (PMF) +- Execution State Switching service + +Source definitions for ARM SiP service are located in the ``arm_sip_svc.h`` header +file. + +Performance Measurement Framework (PMF) +--------------------------------------- + +The `Performance Measurement Framework`_ +allows callers to retrieve timestamps captured at various paths in ARM Trusted +Firmware execution. It's described in detail in `Firmware Design document`_. + +Execution State Switching service +--------------------------------- + +Execution State Switching service provides a mechanism for a non-secure lower +Exception Level (either EL2, or NS EL1 if EL2 isn't implemented) to request to +switch its execution state (a.k.a. Register Width), either from AArch64 to +AArch32, or from AArch32 to AArch64, for the calling CPU. This service is only +available when ARM Trusted Firmware is built for AArch64 (i.e. when build option +``ARCH`` is set to ``aarch64``). + +``ARM_SIP_SVC_EXE_STATE_SWITCH`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t Function ID + uint32_t PC hi + uint32_t PC lo + uint32_t Cookie hi + uint32_t Cookie lo + + Return: + uint32_t + +The function ID parameter must be ``0x82000020``. It uniquely identifies the +Execution State Switching service being requested. + +The parameters *PC hi* and *PC lo* defines upper and lower words, respectively, +of the entry point (physical address) at which execution should start, after +Execution State has been switched. When calling from AArch64, *PC hi* must be 0. + +When execution starts at the supplied entry point after Execution State has been +switched, the parameters *Cookie hi* and *Cookie lo* are passed in CPU registers +0 and 1, respectively. When calling from AArch64, *Cookie hi* must be 0. + +This call can only be made on the primary CPU, before any secondaries were +brought up with ``CPU_ON`` PSCI call. Otherwise, the call will always fail. + +The effect of switching execution state is as if the Exception Level were +entered for the first time, following power on. This means CPU registers that +have a defined reset value by the Architecture will assume that value. Other +registers should not be expected to hold their values before the call was made. +CPU endianness, however, is preserved from the previous execution state. Note +that this switches the execution state of the calling CPU only. This is not a +substitute for PSCI ``SYSTEM_RESET``. + +The service may return the following error codes: + +- ``STATE_SW_E_PARAM``: If any of the parameters were deemed invalid for + a specific request. +- ``STATE_SW_E_DENIED``: If the call is not successful, or when ARM Trusted + Firmware is built for AArch32. + +If the call is successful, the caller wouldn't observe the SMC returning. +Instead, execution starts at the supplied entry point, with the CPU registers 0 +and 1 populated with the supplied *Cookie hi* and *Cookie lo* values, +respectively. + +-------------- + +*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.* + +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html +.. _Performance Measurement Framework: ./firmware-design.rst#user-content-performance-measurement-framework +.. _Firmware Design document: ./firmware-design.rst diff --git a/docs/auth-framework.rst b/docs/auth-framework.rst new file mode 100644 index 0000000..765d9f8 --- /dev/null +++ b/docs/auth-framework.rst @@ -0,0 +1,937 @@ +Abstracting a Chain of Trust +============================ + + +.. section-numbering:: + :suffix: . + +.. contents:: + +The aim of this document is to describe the authentication framework implemented +in the Trusted Firmware. 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 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 framewotk to load the image and calls the +Authentication module to authenticate it, following the CoT from ROT to Image. + +TF 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 ARM + TF. 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: + +:: + + 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 funcion 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; + auth_method_desc_t img_auth_methods[AUTH_METHOD_NUM]; + auth_param_desc_t authenticated_data[COT_MAX_VERIFIED_PARAMS]; + } auth_img_desc_t; + +A CoT is defined as an array of ``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 +~~~~~~~~~~~~ + +The CoT can be found in ``drivers/auth/tbbr/tbbr_cot.c``. This CoT consists of an +array of 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 the Trusted Firmware +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 +`Trusted Board Boot`_ document. + +Following the `Platform 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 array 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. + 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 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. + +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-2048 public key requires 294 +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:: asm + + [TRUSTED_KEY_CERT_ID] = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [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 + } + } + } + }, + [SOC_FW_KEY_CERT_ID] = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[TRUSTED_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }, + [SOC_FW_CONTENT_CERT_ID] = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &cot_desc[SOC_FW_KEY_CERT_ID], + .img_auth_methods = { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data, + } + } + }, + .authenticated_data = { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }, + [BL31_IMAGE_ID] = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &cot_desc[SOC_FW_CONTENT_CERT_ID], + .img_auth_methods = { + [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 ``tz_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 +``plat_tz_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 ``tz_world_pk``. Once this certificate has +been authenticated, we have to extract the BL31 public key, stored in the +extension specified by ``bl31_content_pk``. This key will be copied to the +``plat_content_pk`` 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 ``bl31_content_pk`` as public key. +After authentication, we need to extract the BL31 hash, stored in the extension +specified by ``bl31_hash``. This hash will be copied to the ``plat_bl31_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, ``bl31_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 +three 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); + +The key algorithm (rsa, ecdsa) must be specified in the build system using the +``TF_MBEDTLS_KEY_ALG`` variable, so the Makefile can include the corresponding +sources in the build. + +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) 2015, ARM Limited and Contributors. All rights reserved.* + +.. _Trusted Board Boot: ./trusted-board-boot.rst +.. _Platform Porting Guide: ./porting-guide.rst diff --git a/docs/change-log.rst b/docs/change-log.rst new file mode 100644 index 0000000..e075160 --- /dev/null +++ b/docs/change-log.rst @@ -0,0 +1,1083 @@ +ARM Trusted Firmware - version 1.3 +================================== + +New features +------------ + +- Added support for running Trusted Firmware in AArch32 execution state. + + The PSCI library has been refactored to allow integration with **EL3 Runtime + Software**. This is software that is executing at the highest secure + privilege which is EL3 in AArch64 or Secure SVC/Monitor mode in AArch32. See + `PSCI Integration Guide`_. + + Included is a minimal AArch32 Secure Payload, **SP-MIN**, that illustrates + the usage and integration of the PSCI library with EL3 Runtime Software + running in AArch32 state. + + Booting to the BL1/BL2 images as well as booting straight to the Secure + Payload is supported. + +- Improvements to the initialization framework for the PSCI service and ARM + Standard Services in general. + + The PSCI service is now initialized as part of ARM Standard Service + initialization. This consolidates the initializations of any ARM Standard + Service that may be added in the future. + + A new function ``get_arm_std_svc_args()`` is introduced to get arguments + corresponding to each standard service and must be implemented by the EL3 + Runtime Software. + + For PSCI, a new versioned structure ``psci_lib_args_t`` is introduced to + initialize the PSCI Library. **Note** this is a compatibility break due to + the change in the prototype of ``psci_setup()``. + +- To support AArch32 builds of BL1 and BL2, implemented a new, alternative + firmware image loading mechanism that adds flexibility. + + The current mechanism has a hard-coded set of images and execution order + (BL31, BL32, etc). The new mechanism is data-driven by a list of image + descriptors provided by the platform code. + + ARM platforms have been updated to support the new loading mechanism. + + The new mechanism is enabled by a build flag (``LOAD_IMAGE_V2``) which is + currently off by default for the AArch64 build. + + **Note** ``TRUSTED_BOARD_BOOT`` is currently not supported when + ``LOAD_IMAGE_V2`` is enabled. + +- Updated requirements for making contributions to ARM TF. + + Commits now must have a 'Signed-off-by:' field to certify that the + contribution has been made under the terms of the + `Developer Certificate of Origin`_. + + A signed CLA is no longer required. + + The `Contribution Guide`_ has been updated to reflect this change. + +- Introduced Performance Measurement Framework (PMF) which provides support + for capturing, storing, dumping and retrieving time-stamps to measure the + execution time of critical paths in the firmware. This relies on defining + fixed sample points at key places in the code. + +- To support the QEMU platform port, imported libfdt v1.4.1 from + https://git.kernel.org/cgit/utils/dtc/dtc.git + +- Updated PSCI support: + + - Added support for PSCI NODE\_HW\_STATE API for ARM platforms. + + - New optional platform hook, ``pwr_domain_pwr_down_wfi()``, in + ``plat_psci_ops`` to enable platforms to perform platform-specific actions + needed to enter powerdown, including the 'wfi' invocation. + + - PSCI STAT residency and count functions have been added on ARM platforms + by using PMF. + +- Enhancements to the translation table library: + + - Limited memory mapping support for region overlaps to only allow regions + to overlap that are identity mapped or have the same virtual to physical + address offset, and overlap completely but must not cover the same area. + + This limitation will enable future enhancements without having to + support complex edge cases that may not be necessary. + + - The initial translation lookup level is now inferred from the virtual + address space size. Previously, it was hard-coded. + + - Added support for mapping Normal, Inner Non-cacheable, Outer + Non-cacheable memory in the translation table library. + + This can be useful to map a non-cacheable memory region, such as a DMA + buffer. + + - Introduced the MT\_EXECUTE/MT\_EXECUTE\_NEVER memory mapping attributes to + specify the access permissions for instruction execution of a memory + region. + +- Enabled support to isolate code and read-only data on separate memory pages, + allowing independent access control to be applied to each. + +- Enabled SCR\_EL3.SIF (Secure Instruction Fetch) bit in BL1 and BL31 common + architectural setup code, preventing fetching instructions from non-secure + memory when in secure state. + +- Enhancements to FIP support: + + - Replaced ``fip_create`` with ``fiptool`` which provides a more consistent + and intuitive interface as well as additional support to remove an image + from a FIP file. + + - Enabled printing the SHA256 digest with info command, allowing quick + verification of an image within a FIP without having to extract the + image and running sha256sum on it. + + - Added support for unpacking the contents of an existing FIP file into + the working directory. + + - Aligned command line options for specifying images to use same naming + convention as specified by TBBR and already used in cert\_create tool. + +- Refactored the TZC-400 driver to also support memory controllers that + integrate TZC functionality, for example ARM CoreLink DMC-500. Also added + DMC-500 specific support. + +- Implemented generic delay timer based on the system generic counter and + migrated all platforms to use it. + +- Enhanced support for ARM platforms: + + - Updated image loading support to make SCP images (SCP\_BL2 and SCP\_BL2U) + optional. + + - Enhanced topology description support to allow multi-cluster topology + definitions. + + - Added interconnect abstraction layer to help platform ports select the + right interconnect driver, CCI or CCN, for the platform. + + - Added support to allow loading BL31 in the TZC-secured DRAM instead of + the default secure SRAM. + + - Added support to use a System Security Control (SSC) Registers Unit + enabling ARM TF to be compiled to support multiple ARM platforms and + then select one at runtime. + + - Restricted mapping of Trusted ROM in BL1 to what is actually needed by + BL1 rather than entire Trusted ROM region. + + - Flash is now mapped as execute-never by default. This increases security + by restricting the executable region to what is strictly needed. + +- Applied following erratum workarounds for Cortex-A57: 833471, 826977, + 829520, 828024 and 826974. + +- Added support for Mediatek MT6795 platform. + +- Added support for QEMU virtualization ARMv8-A target. + +- Added support for Rockchip RK3368 and RK3399 platforms. + +- Added support for Xilinx Zynq UltraScale+ MPSoC platform. + +- Added support for ARM Cortex-A73 MPCore Processor. + +- Added support for ARM Cortex-A72 processor. + +- Added support for ARM Cortex-A35 processor. + +- Added support for ARM Cortex-A32 MPCore Processor. + +- Enabled preloaded BL33 alternative boot flow, in which BL2 does not load + BL33 from non-volatile storage and BL31 hands execution over to a preloaded + BL33. The User Guide has been updated with an example of how to use this + option with a bootwrapped kernel. + +- Added support to build ARM TF on a Windows-based host machine. + +- Updated Trusted Board Boot prototype implementation: + + - Enabled the ability for a production ROM with TBBR enabled to boot test + software before a real ROTPK is deployed (e.g. manufacturing mode). + Added support to use ROTPK in certificate without verifying against the + platform value when ``ROTPK_NOT_DEPLOYED`` bit is set. + + - Added support for non-volatile counter authentication to the + Authentication Module to protect against roll-back. + +- Updated GICv3 support: + + - Enabled processor power-down and automatic power-on using GICv3. + + - Enabled G1S or G0 interrupts to be configured independently. + + - Changed FVP default interrupt driver to be the GICv3-only driver. + **Note** the default build of Trusted Firmware will not be able to boot + Linux kernel with GICv2 FDT blob. + + - Enabled wake-up from CPU\_SUSPEND to stand-by by temporarily re-routing + interrupts and then restoring after resume. + +Issues resolved since last release +---------------------------------- + +Known issues +------------ + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI ``SYSTEM_OFF`` API. This issue will be fixed in a future version of + the model. + +- Building TF with compiler optimisations disabled (``-O0``) fails. + +- ARM TF cannot be built with mbed TLS version v2.3.0 due to build warnings + that the ARM TF build system interprets as errors. + +- TBBR is not currently supported when running Trusted Firmware in AArch32 + state. + +ARM Trusted Firmware - version 1.2 +================================== + +New features +------------ + +- The Trusted Board Boot implementation on ARM platforms now conforms to the + mandatory requirements of the TBBR specification. + + In particular, the boot process is now guarded by a Trusted Watchdog, which + will reset the system in case of an authentication or loading error. On ARM + platforms, a secure instance of ARM SP805 is used as the Trusted Watchdog. + + Also, a firmware update process has been implemented. It enables + authenticated firmware to update firmware images from external interfaces to + SoC Non-Volatile memories. This feature functions even when the current + firmware in the system is corrupt or missing; it therefore may be used as + a recovery mode. + +- Improvements have been made to the Certificate Generation Tool + (``cert_create``) as follows. + + - Added support for the Firmware Update process by extending the Chain + of Trust definition in the tool to include the Firmware Update + certificate and the required extensions. + + - Introduced a new API that allows one to specify command line options in + the Chain of Trust description. This makes the declaration of the tool's + arguments more flexible and easier to extend. + + - The tool has been reworked to follow a data driven approach, which + makes it easier to maintain and extend. + +- Extended the FIP tool (``fip_create``) to support the new set of images + involved in the Firmware Update process. + +- Various memory footprint improvements. In particular: + + - The bakery lock structure for coherent memory has been optimised. + + - The mbed TLS SHA1 functions are not needed, as SHA256 is used to + generate the certificate signature. Therefore, they have been compiled + out, reducing the memory footprint of BL1 and BL2 by approximately + 6 KB. + + - On ARM development platforms, each BL stage now individually defines + the number of regions that it needs to map in the MMU. + +- Added the following new design documents: + + - `Authentication framework`_ + - `Firmware Update`_ + - `TF Reset Design`_ + - `Power Domain Topology Design`_ + +- Applied the new image terminology to the code base and documentation, as + described on the `TF wiki on GitHub`_. + +- The build system has been reworked to improve readability and facilitate + adding future extensions. + +- On ARM standard platforms, BL31 uses the boot console during cold boot + but switches to the runtime console for any later logs at runtime. The TSP + uses the runtime console for all output. + +- Implemented a basic NOR flash driver for ARM platforms. It programs the + device using CFI (Common Flash Interface) standard commands. + +- Implemented support for booting EL3 payloads on ARM platforms, which + reduces the complexity of developing EL3 baremetal code by doing essential + baremetal initialization. + +- Provided separate drivers for GICv3 and GICv2. These expect the entire + software stack to use either GICv2 or GICv3; hybrid GIC software systems + are no longer supported and the legacy ARM GIC driver has been deprecated. + +- Added support for Juno r1 and r2. A single set of Juno TF binaries can run + on Juno r0, r1 and r2 boards. Note that this TF version depends on a Linaro + release that does *not* contain Juno r2 support. + +- Added support for MediaTek mt8173 platform. + +- Implemented a generic driver for ARM CCN IP. + +- Major rework of the PSCI implementation. + + - Added framework to handle composite power states. + + - Decoupled the notions of affinity instances (which describes the + hierarchical arrangement of cores) and of power domain topology, instead + of assuming a one-to-one mapping. + + - Better alignment with version 1.0 of the PSCI specification. + +- Added support for the SYSTEM\_SUSPEND PSCI API on ARM platforms. When invoked + on the last running core on a supported platform, this puts the system + into a low power mode with memory retention. + +- Unified the reset handling code as much as possible across BL stages. + Also introduced some build options to enable optimization of the reset path + on platforms that support it. + +- Added a simple delay timer API, as well as an SP804 timer driver, which is + enabled on FVP. + +- Added support for NVidia Tegra T210 and T132 SoCs. + +- Reorganised ARM platforms ports to greatly improve code shareability and + facilitate the reuse of some of this code by other platforms. + +- Added support for ARM Cortex-A72 processor in the CPU specific framework. + +- Provided better error handling. Platform ports can now define their own + error handling, for example to perform platform specific bookkeeping or + post-error actions. + +- Implemented a unified driver for ARM Cache Coherent Interconnects used for + both CCI-400 & CCI-500 IPs. ARM platforms ports have been migrated to this + common driver. The standalone CCI-400 driver has been deprecated. + +Issues resolved since last release +---------------------------------- + +- The Trusted Board Boot implementation has been redesigned to provide greater + modularity and scalability. See the `Authentication Framework`_ document. + All missing mandatory features are now implemented. + +- The FVP and Juno ports may now use the hash of the ROTPK stored in the + Trusted Key Storage registers to verify the ROTPK. Alternatively, a + development public key hash embedded in the BL1 and BL2 binaries might be + used instead. The location of the ROTPK is chosen at build-time using the + ``ARM_ROTPK_LOCATION`` build option. + +- GICv3 is now fully supported and stable. + +Known issues +------------ + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI ``SYSTEM_OFF`` API. This issue will be fixed in a future version of + the model. + +- While this version has low on-chip RAM requirements, there are further + RAM usage enhancements that could be made. + +- The upstream documentation could be improved for structural consistency, + clarity and completeness. In particular, the design documentation is + incomplete for PSCI, the TSP(D) and the Juno platform. + +- Building TF with compiler optimisations disabled (``-O0``) fails. + +ARM Trusted Firmware - version 1.1 +================================== + +New features +------------ + +- A prototype implementation of Trusted Board Boot has been added. Boot + loader images are verified by BL1 and BL2 during the cold boot path. BL1 and + BL2 use the PolarSSL SSL library to verify certificates and images. The + OpenSSL library is used to create the X.509 certificates. Support has been + added to ``fip_create`` tool to package the certificates in a FIP. + +- Support for calling CPU and platform specific reset handlers upon entry into + BL3-1 during the cold and warm boot paths has been added. This happens after + another Boot ROM ``reset_handler()`` has already run. This enables a developer + to perform additional actions or undo actions already performed during the + first call of the reset handlers e.g. apply additional errata workarounds. + +- Support has been added to demonstrate routing of IRQs to EL3 instead of + S-EL1 when execution is in secure world. + +- The PSCI implementation now conforms to version 1.0 of the PSCI + specification. All the mandatory APIs and selected optional APIs are + supported. In particular, support for the ``PSCI_FEATURES`` API has been + added. A capability variable is constructed during initialization by + examining the ``plat_pm_ops`` and ``spd_pm_ops`` exported by the platform and + the Secure Payload Dispatcher. This is used by the PSCI FEATURES function + to determine which PSCI APIs are supported by the platform. + +- Improvements have been made to the PSCI code as follows. + + - The code has been refactored to remove redundant parameters from + internal functions. + + - Changes have been made to the code for PSCI ``CPU_SUSPEND``, ``CPU_ON`` and + ``CPU_OFF`` calls to facilitate an early return to the caller in case a + failure condition is detected. For example, a PSCI ``CPU_SUSPEND`` call + returns ``SUCCESS`` to the caller if a pending interrupt is detected early + in the code path. + + - Optional platform APIs have been added to validate the ``power_state`` and + ``entrypoint`` parameters early in PSCI ``CPU_ON`` and ``CPU_SUSPEND`` code + paths. + + - PSCI migrate APIs have been reworked to invoke the SPD hook to determine + the type of Trusted OS and the CPU it is resident on (if + applicable). Also, during a PSCI ``MIGRATE`` call, the SPD hook to migrate + the Trusted OS is invoked. + +- It is now possible to build Trusted Firmware without marking at least an + extra page of memory as coherent. The build flag ``USE_COHERENT_MEM`` can be + used to choose between the two implementations. This has been made possible + through these changes. + + - An implementation of Bakery locks, where the locks are not allocated in + coherent memory has been added. + + - Memory which was previously marked as coherent is now kept coherent + through the use of software cache maintenance operations. + + Approximately, 4K worth of memory is saved for each boot loader stage when + ``USE_COHERENT_MEM=0``. Enabling this option increases the latencies + associated with acquire and release of locks. It also requires changes to + the platform ports. + +- It is now possible to specify the name of the FIP at build time by defining + the ``FIP_NAME`` variable. + +- Issues with depedencies on the 'fiptool' makefile target have been + rectified. The ``fip_create`` tool is now rebuilt whenever its source files + change. + +- The BL3-1 runtime console is now also used as the crash console. The crash + console is changed to SoC UART0 (UART2) from the previous FPGA UART0 (UART0) + on Juno. In FVP, it is changed from UART0 to UART1. + +- CPU errata workarounds are applied only when the revision and part number + match. This behaviour has been made consistent across the debug and release + builds. The debug build additionally prints a warning if a mismatch is + detected. + +- It is now possible to issue cache maintenance operations by set/way for a + particular level of data cache. Levels 1-3 are currently supported. + +- The following improvements have been made to the FVP port. + + - The build option ``FVP_SHARED_DATA_LOCATION`` which allowed relocation of + shared data into the Trusted DRAM has been deprecated. Shared data is + now always located at the base of Trusted SRAM. + + - BL2 Translation tables have been updated to map only the region of + DRAM which is accessible to normal world. This is the region of the 2GB + DDR-DRAM memory at 0x80000000 excluding the top 16MB. The top 16MB is + accessible to only the secure world. + + - BL3-2 can now reside in the top 16MB of DRAM which is accessible only to + the secure world. This can be done by setting the build flag + ``FVP_TSP_RAM_LOCATION`` to the value ``dram``. + +- Separate transation tables are created for each boot loader image. The + ``IMAGE_BLx`` build options are used to do this. This allows each stage to + create mappings only for areas in the memory map that it needs. + +- A Secure Payload Dispatcher (OPTEED) for the OP-TEE Trusted OS has been + added. Details of using it with ARM Trusted Firmware can be found in + `OP-TEE Dispatcher`_ + +Issues resolved since last release +---------------------------------- + +- The Juno port has been aligned with the FVP port as follows. + + - Support for reclaiming all BL1 RW memory and BL2 memory by overlaying + the BL3-1/BL3-2 NOBITS sections on top of them has been added to the + Juno port. + + - The top 16MB of the 2GB DDR-DRAM memory at 0x80000000 is configured + using the TZC-400 controller to be accessible only to the secure world. + + - The ARM GIC driver is used to configure the GIC-400 instead of using a + GIC driver private to the Juno port. + + - PSCI ``CPU_SUSPEND`` calls that target a standby state are now supported. + + - The TZC-400 driver is used to configure the controller instead of direct + accesses to the registers. + +- The Linux kernel version referred to in the user guide has DVFS and HMP + support enabled. + +- DS-5 v5.19 did not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in + CADI server mode. This issue is not seen with DS-5 v5.20 and Version 6.2 of + the Cortex-A57-A53 Base FVPs. + +Known issues +------------ + +- The Trusted Board Boot implementation is a prototype. There are issues with + the modularity and scalability of the design. Support for a Trusted + Watchdog, firmware update mechanism, recovery images and Trusted debug is + absent. These issues will be addressed in future releases. + +- The FVP and Juno ports do not use the hash of the ROTPK stored in the + Trusted Key Storage registers to verify the ROTPK in the + ``plat_match_rotpk()`` function. This prevents the correct establishment of + the Chain of Trust at the first step in the Trusted Board Boot process. + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI ``SYSTEM_OFF`` API. This issue will be fixed in a future version of + the model. + +- GICv3 support is experimental. There are known issues with GICv3 + initialization in the ARM Trusted Firmware. + +- While this version greatly reduces the on-chip RAM requirements, there are + further RAM usage enhancements that could be made. + +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +- The Juno-specific firmware design documentation is incomplete. + +ARM Trusted Firmware - version 1.0 +================================== + +New features +------------ + +- It is now possible to map higher physical addresses using non-flat virtual + to physical address mappings in the MMU setup. + +- Wider use is now made of the per-CPU data cache in BL3-1 to store: + + - Pointers to the non-secure and secure security state contexts. + + - A pointer to the CPU-specific operations. + + - A pointer to PSCI specific information (for example the current power + state). + + - A crash reporting buffer. + +- The following RAM usage improvements result in a BL3-1 RAM usage reduction + from 96KB to 56KB (for FVP with TSPD), and a total RAM usage reduction + across all images from 208KB to 88KB, compared to the previous release. + + - Removed the separate ``early_exception`` vectors from BL3-1 (2KB code size + saving). + + - Removed NSRAM from the FVP memory map, allowing the removal of one + (4KB) translation table. + + - Eliminated the internal ``psci_suspend_context`` array, saving 2KB. + + - Correctly dimensioned the PSCI ``aff_map_node`` array, saving 1.5KB in the + FVP port. + + - Removed calling CPU mpidr from the bakery lock API, saving 160 bytes. + + - Removed current CPU mpidr from PSCI common code, saving 160 bytes. + + - Inlined the mmio accessor functions, saving 360 bytes. + + - Fully reclaimed all BL1 RW memory and BL2 memory on the FVP port by + overlaying the BL3-1/BL3-2 NOBITS sections on top of these at runtime. + + - Made storing the FP register context optional, saving 0.5KB per context + (8KB on the FVP port, with TSPD enabled and running on 8 CPUs). + + - Implemented a leaner ``tf_printf()`` function, allowing the stack to be + greatly reduced. + + - Removed coherent stacks from the codebase. Stacks allocated in normal + memory are now used before and after the MMU is enabled. This saves 768 + bytes per CPU in BL3-1. + + - Reworked the crash reporting in BL3-1 to use less stack. + + - Optimized the EL3 register state stored in the ``cpu_context`` structure + so that registers that do not change during normal execution are + re-initialized each time during cold/warm boot, rather than restored + from memory. This saves about 1.2KB. + + - As a result of some of the above, reduced the runtime stack size in all + BL images. For BL3-1, this saves 1KB per CPU. + +- PSCI SMC handler improvements to correctly handle calls from secure states + and from AArch32. + +- CPU contexts are now initialized from the ``entry_point_info``. BL3-1 fully + determines the exception level to use for the non-trusted firmware (BL3-3) + based on the SPSR value provided by the BL2 platform code (or otherwise + provided to BL3-1). This allows platform code to directly run non-trusted + firmware payloads at either EL2 or EL1 without requiring an EL2 stub or OS + loader. + +- Code refactoring improvements: + + - Refactored ``fvp_config`` into a common platform header. + + - Refactored the fvp gic code to be a generic driver that no longer has an + explicit dependency on platform code. + + - Refactored the CCI-400 driver to not have dependency on platform code. + + - Simplified the IO driver so it's no longer necessary to call ``io_init()`` + and moved all the IO storage framework code to one place. + + - Simplified the interface the the TZC-400 driver. + + - Clarified the platform porting interface to the TSP. + + - Reworked the TSPD setup code to support the alternate BL3-2 + intialization flow where BL3-1 generic code hands control to BL3-2, + rather than expecting the TSPD to hand control directly to BL3-2. + + - Considerable rework to PSCI generic code to support CPU specific + operations. + +- Improved console log output, by: + + - Adding the concept of debug log levels. + + - Rationalizing the existing debug messages and adding new ones. + + - Printing out the version of each BL stage at runtime. + + - Adding support for printing console output from assembler code, + including when a crash occurs before the C runtime is initialized. + +- Moved up to the latest versions of the FVPs, toolchain, EDK2, kernel, Linaro + file system and DS-5. + +- On the FVP port, made the use of the Trusted DRAM region optional at build + time (off by default). Normal platforms will not have such a "ready-to-use" + DRAM area so it is not a good example to use it. + +- Added support for PSCI ``SYSTEM_OFF`` and ``SYSTEM_RESET`` APIs. + +- Added support for CPU specific reset sequences, power down sequences and + register dumping during crash reporting. The CPU specific reset sequences + include support for errata workarounds. + +- Merged the Juno port into the master branch. Added support for CPU hotplug + and CPU idle. Updated the user guide to describe how to build and run on the + Juno platform. + +Issues resolved since last release +---------------------------------- + +- Removed the concept of top/bottom image loading. The image loader now + automatically detects the position of the image inside the current memory + layout and updates the layout to minimize fragementation. This resolves the + image loader limitations of previously releases. There are currently no + plans to support dynamic image loading. + +- CPU idle now works on the publicized version of the Foundation FVP. + +- All known issues relating to the compiler version used have now been + resolved. This TF version uses Linaro toolchain 14.07 (based on GCC 4.9). + +Known issues +------------ + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + the ARM Trusted Firmware. + +- While this version greatly reduces the on-chip RAM requirements, there are + further RAM usage enhancements that could be made. + +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +- The Juno-specific firmware design documentation is incomplete. + +- Some recent enhancements to the FVP port have not yet been translated into + the Juno port. These will be tracked via the tf-issues project. + +- The Linux kernel version referred to in the user guide has DVFS and HMP + support disabled due to some known instabilities at the time of this + release. A future kernel version will re-enable these features. + +- DS-5 v5.19 does not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in + CADI server mode. This is because the ```` reported by the FVP in + this version has changed. For example, for the Cortex-A57x4-A53x4 Base FVP, + the ```` reported by the FVP is ``FVP_Base_Cortex_A57x4_A53x4``, while + DS-5 expects it to be ``FVP_Base_A57x4_A53x4``. + + The temporary fix to this problem is to change the name of the FVP in + ``sw/debugger/configdb/Boards/ARM FVP/Base_A57x4_A53x4/cadi_config.xml``. + Change the following line: + + :: + + System Generator:FVP_Base_A57x4_A53x4 + + to + System Generator:FVP\_Base\_Cortex-A57x4\_A53x4 + + A similar change can be made to the other Cortex-A57-A53 Base FVP variants. + +ARM Trusted Firmware - version 0.4 +================================== + +New features +------------ + +- Makefile improvements: + + - Improved dependency checking when building. + + - Removed ``dump`` target (build now always produces dump files). + + - Enabled platform ports to optionally make use of parts of the Trusted + Firmware (e.g. BL3-1 only), rather than being forced to use all parts. + Also made the ``fip`` target optional. + + - Specified the full path to source files and removed use of the ``vpath`` + keyword. + +- Provided translation table library code for potential re-use by platforms + other than the FVPs. + +- Moved architectural timer setup to platform-specific code. + +- Added standby state support to PSCI cpu\_suspend implementation. + +- SRAM usage improvements: + + - Started using the ``-ffunction-sections``, ``-fdata-sections`` and + ``--gc-sections`` compiler/linker options to remove unused code and data + from the images. Previously, all common functions were being built into + all binary images, whether or not they were actually used. + + - Placed all assembler functions in their own section to allow more unused + functions to be removed from images. + + - Updated BL1 and BL2 to use a single coherent stack each, rather than one + per CPU. + + - Changed variables that were unnecessarily declared and initialized as + non-const (i.e. in the .data section) so they are either uninitialized + (zero init) or const. + +- Moved the Test Secure-EL1 Payload (BL3-2) to execute in Trusted SRAM by + default. The option for it to run in Trusted DRAM remains. + +- Implemented a TrustZone Address Space Controller (TZC-400) driver. A + default configuration is provided for the Base FVPs. This means the model + parameter ``-C bp.secure_memory=1`` is now supported. + +- Started saving the PSCI cpu\_suspend 'power\_state' parameter prior to + suspending a CPU. This allows platforms that implement multiple power-down + states at the same affinity level to identify a specific state. + +- Refactored the entire codebase to reduce the amount of nesting in header + files and to make the use of system/user includes more consistent. Also + split platform.h to separate out the platform porting declarations from the + required platform porting definitions and the definitions/declarations + specific to the platform port. + +- Optimized the data cache clean/invalidate operations. + +- Improved the BL3-1 unhandled exception handling and reporting. Unhandled + exceptions now result in a dump of registers to the console. + +- Major rework to the handover interface between BL stages, in particular the + interface to BL3-1. The interface now conforms to a specification and is + more future proof. + +- Added support for optionally making the BL3-1 entrypoint a reset handler + (instead of BL1). This allows platforms with an alternative image loading + architecture to re-use BL3-1 with fewer modifications to generic code. + +- Reserved some DDR DRAM for secure use on FVP platforms to avoid future + compatibility problems with non-secure software. + +- Added support for secure interrupts targeting the Secure-EL1 Payload (SP) + (using GICv2 routing only). Demonstrated this working by adding an interrupt + target and supporting test code to the TSP. Also demonstrated non-secure + interrupt handling during TSP processing. + +Issues resolved since last release +---------------------------------- + +- Now support use of the model parameter ``-C bp.secure_memory=1`` in the Base + FVPs (see **New features**). + +- Support for secure world interrupt handling now available (see **New + features**). + +- Made enough SRAM savings (see **New features**) to enable the Test Secure-EL1 + Payload (BL3-2) to execute in Trusted SRAM by default. + +- The tested filesystem used for this release (Linaro AArch64 OpenEmbedded + 14.04) now correctly reports progress in the console. + +- Improved the Makefile structure to make it easier to separate out parts of + the Trusted Firmware for re-use in platform ports. Also, improved target + dependency checking. + +Known issues +------------ + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + the ARM Trusted Firmware. + +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead + to loading errors, even if the images should theoretically fit in memory. + +- The ARM Trusted Firmware still uses too much on-chip Trusted SRAM. A number + of RAM usage enhancements have been identified to rectify this situation. + +- CPU idle does not work on the advertised version of the Foundation FVP. + Some FVP fixes are required that are not available externally at the time + of writing. This can be worked around by disabling CPU idle in the Linux + kernel. + +- Various bugs in ARM Trusted Firmware, UEFI and the Linux kernel have been + observed when using Linaro toolchain versions later than 13.11. Although + most of these have been fixed, some remain at the time of writing. These + mainly seem to relate to a subtle change in the way the compiler converts + between 64-bit and 32-bit values (e.g. during casting operations), which + reveals previously hidden bugs in client code. + +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +ARM Trusted Firmware - version 0.3 +================================== + +New features +------------ + +- Support for Foundation FVP Version 2.0 added. + The documented UEFI configuration disables some devices that are unavailable + in the Foundation FVP, including MMC and CLCD. The resultant UEFI binary can + be used on the AEMv8 and Cortex-A57-A53 Base FVPs, as well as the Foundation + FVP. + + NOTE: The software will not work on Version 1.0 of the Foundation FVP. + +- Enabled third party contributions. Added a new contributing.md containing + instructions for how to contribute and updated copyright text in all files + to acknowledge contributors. + +- The PSCI CPU\_SUSPEND API has been stabilised to the extent where it can be + used for entry into power down states with the following restrictions: + + - Entry into standby states is not supported. + - The API is only supported on the AEMv8 and Cortex-A57-A53 Base FVPs. + +- The PSCI AFFINITY\_INFO api has undergone limited testing on the Base FVPs to + allow experimental use. + +- Required C library and runtime header files are now included locally in ARM + Trusted Firmware instead of depending on the toolchain standard include + paths. The local implementation has been cleaned up and reduced in scope. + +- Added I/O abstraction framework, primarily to allow generic code to load + images in a platform-independent way. The existing image loading code has + been reworked to use the new framework. Semi-hosting and NOR flash I/O + drivers are provided. + +- Introduced Firmware Image Package (FIP) handling code and tools. A FIP + combines multiple firmware images with a Table of Contents (ToC) into a + single binary image. The new FIP driver is another type of I/O driver. The + Makefile builds a FIP by default and the FVP platform code expect to load a + FIP from NOR flash, although some support for image loading using semi- + hosting is retained. + + NOTE: Building a FIP by default is a non-backwards-compatible change. + + NOTE: Generic BL2 code now loads a BL3-3 (non-trusted firmware) image into + DRAM instead of expecting this to be pre-loaded at known location. This is + also a non-backwards-compatible change. + + NOTE: Some non-trusted firmware (e.g. UEFI) will need to be rebuilt so that + it knows the new location to execute from and no longer needs to copy + particular code modules to DRAM itself. + +- Reworked BL2 to BL3-1 handover interface. A new composite structure + (bl31\_args) holds the superset of information that needs to be passed from + BL2 to BL3-1, including information on how handover execution control to + BL3-2 (if present) and BL3-3 (non-trusted firmware). + +- Added library support for CPU context management, allowing the saving and + restoring of + + - Shared system registers between Secure-EL1 and EL1. + - VFP registers. + - Essential EL3 system registers. + +- Added a framework for implementing EL3 runtime services. Reworked the PSCI + implementation to be one such runtime service. + +- Reworked the exception handling logic, making use of both SP\_EL0 and SP\_EL3 + stack pointers for determining the type of exception, managing general + purpose and system register context on exception entry/exit, and handling + SMCs. SMCs are directed to the correct EL3 runtime service. + +- Added support for a Test Secure-EL1 Payload (TSP) and a corresponding + Dispatcher (TSPD), which is loaded as an EL3 runtime service. The TSPD + implements Secure Monitor functionality such as world switching and + EL1 context management, and is responsible for communication with the TSP. + NOTE: The TSPD does not yet contain support for secure world interrupts. + NOTE: The TSP/TSPD is not built by default. + +Issues resolved since last release +---------------------------------- + +- Support has been added for switching context between secure and normal + worlds in EL3. + +- PSCI API calls ``AFFINITY_INFO`` & ``PSCI_VERSION`` have now been tested (to + a limited extent). + +- The ARM Trusted Firmware build artifacts are now placed in the ``./build`` + directory and sub-directories instead of being placed in the root of the + project. + +- The ARM Trusted Firmware is now free from build warnings. Build warnings + are now treated as errors. + +- The ARM Trusted Firmware now provides C library support locally within the + project to maintain compatibility between toolchains/systems. + +- The PSCI locking code has been reworked so it no longer takes locks in an + incorrect sequence. + +- The RAM-disk method of loading a Linux file-system has been confirmed to + work with the ARM Trusted Firmware and Linux kernel version (based on + version 3.13) used in this release, for both Foundation and Base FVPs. + +Known issues +------------ + +The following is a list of issues which are expected to be fixed in the future +releases of the ARM Trusted Firmware. + +- The TrustZone Address Space Controller (TZC-400) is not being programmed + yet. Use of model parameter ``-C bp.secure_memory=1`` is not supported. + +- No support yet for secure world interrupt handling. + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + the ARM Trusted Firmware. + +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead + to loading errors, even if the images should theoretically fit in memory. + +- The ARM Trusted Firmware uses too much on-chip Trusted SRAM. Currently the + Test Secure-EL1 Payload (BL3-2) executes in Trusted DRAM since there is not + enough SRAM. A number of RAM usage enhancements have been identified to + rectify this situation. + +- CPU idle does not work on the advertised version of the Foundation FVP. + Some FVP fixes are required that are not available externally at the time + of writing. + +- Various bugs in ARM Trusted Firmware, UEFI and the Linux kernel have been + observed when using Linaro toolchain versions later than 13.11. Although + most of these have been fixed, some remain at the time of writing. These + mainly seem to relate to a subtle change in the way the compiler converts + between 64-bit and 32-bit values (e.g. during casting operations), which + reveals previously hidden bugs in client code. + +- The tested filesystem used for this release (Linaro AArch64 OpenEmbedded + 14.01) does not report progress correctly in the console. It only seems to + produce error output, not standard output. It otherwise appears to function + correctly. Other filesystem versions on the same software stack do not + exhibit the problem. + +- The Makefile structure doesn't make it easy to separate out parts of the + Trusted Firmware for re-use in platform ports, for example if only BL3-1 is + required in a platform port. Also, dependency checking in the Makefile is + flawed. + +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +ARM Trusted Firmware - version 0.2 +================================== + +New features +------------ + +- First source release. + +- Code for the PSCI suspend feature is supplied, although this is not enabled + by default since there are known issues (see below). + +Issues resolved since last release +---------------------------------- + +- The "psci" nodes in the FDTs provided in this release now fully comply + with the recommendations made in the PSCI specification. + +Known issues +------------ + +The following is a list of issues which are expected to be fixed in the future +releases of the ARM Trusted Firmware. + +- The TrustZone Address Space Controller (TZC-400) is not being programmed + yet. Use of model parameter ``-C bp.secure_memory=1`` is not supported. + +- No support yet for secure world interrupt handling or for switching context + between secure and normal worlds in EL3. + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + the ARM Trusted Firmware. + +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead + to loading errors, even if the images should theoretically fit in memory. + +- Although support for PSCI ``CPU_SUSPEND`` is present, it is not yet stable + and ready for use. + +- PSCI API calls ``AFFINITY_INFO`` & ``PSCI_VERSION`` are implemented but have not + been tested. + +- The ARM Trusted Firmware make files result in all build artifacts being + placed in the root of the project. These should be placed in appropriate + sub-directories. + +- The compilation of ARM Trusted Firmware is not free from compilation + warnings. Some of these warnings have not been investigated yet so they + could mask real bugs. + +- The ARM Trusted Firmware currently uses toolchain/system include files like + stdio.h. It should provide versions of these within the project to maintain + compatibility between toolchains/systems. + +- The PSCI code takes some locks in an incorrect sequence. This may cause + problems with suspend and hotplug in certain conditions. + +- The Linux kernel used in this release is based on version 3.12-rc4. Using + this kernel with the ARM Trusted Firmware fails to start the file-system as + a RAM-disk. It fails to execute user-space ``init`` from the RAM-disk. As an + alternative, the VirtioBlock mechanism can be used to provide a file-system + to the kernel. + +-------------- + +*Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.* + +.. _PSCI Integration Guide: psci-lib-integration-guide.rst +.. _Developer Certificate of Origin: ../dco.txt +.. _Contribution Guide: ../contributing.rst +.. _Authentication framework: auth-framework.rst +.. _Firmware Update: firmware-update.rst +.. _TF Reset Design: reset-design.rst +.. _Power Domain Topology Design: psci-pd-tree.rst +.. _TF wiki on GitHub: https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Image-Terminology +.. _Authentication Framework: auth-framework.rst +.. _OP-TEE Dispatcher: optee-dispatcher.rst diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst new file mode 100644 index 0000000..ce564a2 --- /dev/null +++ b/docs/cpu-specific-build-macros.rst @@ -0,0 +1,127 @@ +ARM CPU Specific Build Macros +============================= + + +.. section-numbering:: + :suffix: . + +.. contents:: + +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. + +CPU Errata Workarounds +---------------------- + +ARM Trusted Firmware 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`_ + +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__``, where the ``Processor name`` +is for example ``A57`` for the ``Cortex_A57`` CPU. + +Refer to the section *CPU errata status reporting* in +`Firmware Design guide`_ for information on 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 are 0 by default, that is, disabled. Any other +value will enable it. + +For Cortex-A53, following errata build flags are defined : + +- ``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_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_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. + +For Cortex-A57, 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_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. + +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`_. + +-------------- + +*Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.* + +.. _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/cortex_a57_mpcore_software_developers_errata_notice.pdf +.. _Firmware Design guide: firmware-design.rst +.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst new file mode 100644 index 0000000..cc2fe11 --- /dev/null +++ b/docs/firmware-design.rst @@ -0,0 +1,2443 @@ +ARM Trusted Firmware Design +=========================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +The ARM Trusted Firmware implements a subset of the Trusted Board Boot +Requirements (TBBR) Platform Design Document (PDD) [1] for ARM reference +platforms. The TBB sequence starts when the platform is powered on and runs up +to the stage where it hands-off control to firmware running in the normal +world in DRAM. This is the cold boot path. + +The ARM Trusted Firmware also implements the Power State Coordination Interface +PDD [2] as a runtime service. PSCI is the interface from normal world software +to firmware implementing power management use-cases (for example, secondary CPU +boot, hotplug and idle). Normal world software can access ARM Trusted Firmware +runtime services via the ARM SMC (Secure Monitor Call) instruction. The SMC +instruction must be used as mandated by the SMC Calling Convention [3]. + +The ARM Trusted Firmware implements a framework for configuring and managing +interrupts generated in either security state. The details of the interrupt +management framework and its design can be found in ARM Trusted Firmware +Interrupt Management Design guide [4]. + +The ARM Trusted Firmware can be built to support either AArch64 or AArch32 +execution state. + +Cold boot +--------- + +The cold boot path starts when the platform is physically turned on. If +``COLD_BOOT_SINGLE_CPU=0``, one of the CPUs released from reset is chosen as the +primary CPU, and the remaining CPUs are considered secondary CPUs. The primary +CPU is chosen through platform-specific means. The cold boot path is mainly +executed by the primary CPU, other than essential CPU initialization executed by +all CPUs. The secondary CPUs are kept in a safe platform-specific state until +the primary CPU has performed enough initialization to boot them. + +Refer to the `Reset Design`_ for more information on the effect of the +``COLD_BOOT_SINGLE_CPU`` platform build option. + +The cold boot path in this implementation of the ARM Trusted Firmware, +depends on the execution state. +For AArch64, it is divided into five steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-1 (BL31) *EL3 Runtime Software* +- Boot Loader stage 3-2 (BL32) *Secure-EL1 Payload* (optional) +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +For AArch32, it is divided into four steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-2 (BL32) *EL3 Runtime Software* +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +ARM development platforms (Fixed Virtual Platforms (FVPs) and Juno) implement a +combination of the following types of memory regions. Each bootloader stage uses +one or more of these memory regions. + +- Regions accessible from both non-secure and secure states. For example, + non-trusted SRAM, ROM and DRAM. +- Regions accessible from only the secure state. For example, trusted SRAM and + ROM. The FVPs also implement the trusted DRAM which is statically + configured. Additionally, the Base FVPs and Juno development platform + configure the TrustZone Controller (TZC) to create a region in the DRAM + which is accessible only from the secure state. + +The sections below provide the following details: + +- initialization and execution of the first three stages during cold boot +- specification of the EL3 Runtime Software (BL31 for AArch64 and BL32 for + AArch32) entrypoint requirements for use by alternative Trusted Boot + Firmware in place of the provided BL1 and BL2 + +BL1 +~~~ + +This stage begins execution from the platform's reset vector at EL3. The reset +address is platform dependent but it is usually located in a Trusted ROM area. +The BL1 data section is copied to trusted SRAM at runtime. + +On the ARM development platforms, BL1 code starts execution from the reset +vector defined by the constant ``BL1_RO_BASE``. The BL1 data section is copied +to the top of trusted SRAM as defined by the constant ``BL1_RW_BASE``. + +The functionality implemented by this stage is as follows. + +Determination of boot path +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Whenever a CPU is released from reset, BL1 needs to distinguish between a warm +boot and a cold boot. This is done using platform-specific mechanisms (see the +``plat_get_my_entrypoint()`` function in the `Porting Guide`_). In the case of a +warm boot, a CPU is expected to continue execution from a separate +entrypoint. In the case of a cold boot, the secondary CPUs are placed in a safe +platform-specific state (see the ``plat_secondary_cold_boot_setup()`` function in +the `Porting Guide`_) while the primary CPU executes the remaining cold boot path +as described in the following sections. + +This step only applies when ``PROGRAMMABLE_RESET_ADDRESS=0``. Refer to the +`Reset Design`_ for more information on the effect of the +``PROGRAMMABLE_RESET_ADDRESS`` platform build option. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL1 performs minimal architectural initialization as follows. + +- Exception vectors + + BL1 sets up simple exception vectors for both synchronous and asynchronous + exceptions. The default behavior upon receiving an exception is to populate + a status code in the general purpose register ``X0/R0`` and call the + ``plat_report_exception()`` function (see the `Porting Guide`_). The status + code is one of: + + For AArch64: + + :: + + 0x0 : Synchronous exception from Current EL with SP_EL0 + 0x1 : IRQ exception from Current EL with SP_EL0 + 0x2 : FIQ exception from Current EL with SP_EL0 + 0x3 : System Error exception from Current EL with SP_EL0 + 0x4 : Synchronous exception from Current EL with SP_ELx + 0x5 : IRQ exception from Current EL with SP_ELx + 0x6 : FIQ exception from Current EL with SP_ELx + 0x7 : System Error exception from Current EL with SP_ELx + 0x8 : Synchronous exception from Lower EL using aarch64 + 0x9 : IRQ exception from Lower EL using aarch64 + 0xa : FIQ exception from Lower EL using aarch64 + 0xb : System Error exception from Lower EL using aarch64 + 0xc : Synchronous exception from Lower EL using aarch32 + 0xd : IRQ exception from Lower EL using aarch32 + 0xe : FIQ exception from Lower EL using aarch32 + 0xf : System Error exception from Lower EL using aarch32 + + For AArch32: + + :: + + 0x10 : User mode + 0x11 : FIQ mode + 0x12 : IRQ mode + 0x13 : SVC mode + 0x16 : Monitor mode + 0x17 : Abort mode + 0x1a : Hypervisor mode + 0x1b : Undefined mode + 0x1f : System mode + + The ``plat_report_exception()`` implementation on the ARM FVP port programs + the Versatile Express System LED register in the following format to + indicate the occurence of an unexpected exception: + + :: + + SYS_LED[0] - Security state (Secure=0/Non-Secure=1) + SYS_LED[2:1] - Exception Level (EL3=0x3, EL2=0x2, EL1=0x1, EL0=0x0) + For AArch32 it is always 0x0 + SYS_LED[7:3] - Exception Class (Sync/Async & origin). This is the value + of the status code + + A write to the LED register reflects in the System LEDs (S6LED0..7) in the + CLCD window of the FVP. + + BL1 does not expect to receive any exceptions other than the SMC exception. + For the latter, BL1 installs a simple stub. The stub expects to receive a + limited set of SMC types (determined by their function IDs in the general + purpose register ``X0/R0``): + + - ``BL1_SMC_RUN_IMAGE``: This SMC is raised by BL2 to make BL1 pass control + to EL3 Runtime Software. + - All SMCs listed in section "BL1 SMC Interface" in the `Firmware Update`_ + Design Guide are supported for AArch64 only. These SMCs are currently + not supported when BL1 is built for AArch32. + + Any other SMC leads to an assertion failure. + +- CPU initialization + + BL1 calls the ``reset_handler()`` function which in turn calls the CPU + specific reset handler function (see the section: "CPU specific operations + framework"). + +- Control register setup (for AArch64) + + - ``SCTLR_EL3``. Instruction cache is enabled by setting the ``SCTLR_EL3.I`` + bit. Alignment and stack alignment checking is enabled by setting the + ``SCTLR_EL3.A`` and ``SCTLR_EL3.SA`` bits. Exception endianness is set to + little-endian by clearing the ``SCTLR_EL3.EE`` bit. + + - ``SCR_EL3``. The register width of the next lower exception level is set + to AArch64 by setting the ``SCR.RW`` bit. The ``SCR.EA`` bit is set to trap + both External Aborts and SError Interrupts in EL3. The ``SCR.SIF`` bit is + also set to disable instruction fetches from Non-secure memory when in + secure state. + + - ``CPTR_EL3``. Accesses to the ``CPACR_EL1`` register from EL1 or EL2, or the + ``CPTR_EL2`` register from EL2 are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TCPAC`` bit. Access to the trace functionality is + configured not to trap to EL3 by clearing the ``CPTR_EL3.TTA`` bit. + Instructions that access the registers associated with Floating Point + and Advanced SIMD execution are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TFP`` bit. + + - ``DAIF``. The SError interrupt is enabled by clearing the SError interrupt + mask bit. + + - ``MDCR_EL3``. The trap controls, ``MDCR_EL3.TDOSA``, ``MDCR_EL3.TDA`` and + ``MDCR_EL3.TPM``, are set so that accesses to the registers they control + do not trap to EL3. AArch64 Secure self-hosted debug is disabled by + setting the ``MDCR_EL3.SDD`` bit. Also ``MDCR_EL3.SPD32`` is set to + disable AArch32 Secure self-hosted privileged debug from S-EL1. + +- Control register setup (for AArch32) + + - ``SCTLR``. Instruction cache is enabled by setting the ``SCTLR.I`` bit. + Alignment checking is enabled by setting the ``SCTLR.A`` bit. + Exception endianness is set to little-endian by clearing the + ``SCTLR.EE`` bit. + + - ``SCR``. The ``SCR.SIF`` bit is set to disable instruction fetches from + Non-secure memory when in secure state. + + - ``CPACR``. Allow execution of Advanced SIMD instructions at PL0 and PL1, + by clearing the ``CPACR.ASEDIS`` bit. Access to the trace functionality + is configured not to trap to undefined mode by clearing the + ``CPACR.TRCDIS`` bit. + + - ``NSACR``. Enable non-secure access to Advanced SIMD functionality and + system register access to implemented trace registers. + + - ``FPEXC``. Enable access to the Advanced SIMD and floating-point + functionality from all Exception levels. + + - ``CPSR.A``. The Asynchronous data abort interrupt is enabled by clearing + the Asynchronous data abort interrupt mask bit. + + - ``SDCR``. The ``SDCR.SPD`` field is set to disable AArch32 Secure + self-hosted privileged debug. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On ARM platforms, BL1 performs the following platform initializations: + +- Enable the Trusted Watchdog. +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Configure any required platform storage to load the next bootloader image + (BL2). + +Firmware Update detection and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After performing platform setup, BL1 common code calls +``bl1_plat_get_next_image_id()`` to determine if `Firmware Update`_ is required or +to proceed with the normal boot process. If the platform code returns +``BL2_IMAGE_ID`` then the normal boot sequence is executed as described in the +next section, else BL1 assumes that `Firmware Update`_ is required and execution +passes to the first image in the `Firmware Update`_ process. In either case, BL1 +retrieves a descriptor of the next image by calling ``bl1_plat_get_image_desc()``. +The image descriptor contains an ``entry_point_info_t`` structure, which BL1 +uses to initialize the execution state of the next image. + +BL2 image load and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the normal boot flow, BL1 execution continues as follows: + +#. BL1 prints the following string from the primary CPU to indicate successful + execution of the BL1 stage: + + :: + + "Booting Trusted Firmware" + +#. BL1 determines the amount of free trusted SRAM memory available by + calculating the extent of its own data section, which also resides in + trusted SRAM. BL1 loads a BL2 raw binary image from platform storage, at a + platform-specific base address. If the BL2 image file is not present or if + there is not enough free trusted SRAM the following error message is + printed: + + :: + + "Failed to load BL2 firmware." + + BL1 calculates the amount of Trusted SRAM that can be used by the BL2 + image. The exact load location of the image is provided as a base address + in the platform header. Further description of the memory layout can be + found later in this document. + +#. BL1 passes control to the BL2 image at Secure EL1 (for AArch64) or at + Secure SVC mode (for AArch32), starting from its load address. + +#. BL1 also passes information about the amount of trusted SRAM used and + available for use. This information is populated at a platform-specific + memory address. + +BL2 +~~~ + +BL1 loads and passes control to BL2 at Secure-EL1 (for AArch64) or at Secure +SVC mode (for AArch32) . BL2 is linked against and loaded at a platform-specific +base address (more information can be found later in this document). +The functionality implemented by BL2 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For AArch64, BL2 performs the minimal architectural initialization required +for subsequent stages of the ARM Trusted Firmware and normal world software. +EL1 and EL0 are given access to Floating Point and Advanced SIMD registers +by clearing the ``CPACR.FPEN`` bits. + +For AArch32, the minimal architectural initialization required for subsequent +stages of the ARM Trusted Firmware and normal world software is taken care of +in BL1 as both BL1 and BL2 execute at PL1. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On ARM platforms, BL2 performs the following platform initializations: + +- Initialize the console. +- Configure any required platform storage to allow loading further bootloader + images. +- Enable the MMU and map the memory it needs to access. +- Perform platform security setup to allow access to controlled components. +- Reserve some memory for passing information to the next bootloader image + EL3 Runtime Software and populate it. +- Define the extents of memory available for loading each subsequent + bootloader image. + +Image loading in BL2 +^^^^^^^^^^^^^^^^^^^^ + +Image loading scheme in BL2 depends on ``LOAD_IMAGE_V2`` build option. If the +flag is disabled, the BLxx images are loaded, by calling the respective +load\_blxx() function from BL2 generic code. If the flag is enabled, the BL2 +generic code loads the images based on the list of loadable images provided +by the platform. BL2 passes the list of executable images provided by the +platform to the next handover BL image. By default, this flag is disabled for +AArch64 and the AArch32 build is supported only if this flag is enabled. + +SCP\_BL2 (System Control Processor Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some systems have a separate System Control Processor (SCP) for power, clock, +reset and system control. BL2 loads the optional SCP\_BL2 image from platform +storage into a platform-specific region of secure memory. The subsequent +handling of SCP\_BL2 is platform specific. For example, on the Juno ARM +development platform port the image is transferred into SCP's internal memory +using the Boot Over MHU (BOM) protocol after being loaded in the trusted SRAM +memory. The SCP executes SCP\_BL2 and signals to the Application Processor (AP) +for BL2 execution to continue. + +EL3 Runtime Software image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the EL3 Runtime Software image from platform storage into a platform- +specific address in trusted SRAM. If there is not enough memory to load the +image or image is missing it leads to an assertion failure. If ``LOAD_IMAGE_V2`` +is disabled and if image loads successfully, BL2 updates the amount of trusted +SRAM used and available for use by EL3 Runtime Software. This information is +populated at a platform-specific memory address. + +AArch64 BL32 (Secure-EL1 Payload) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the optional BL32 image from platform storage into a platform- +specific region of secure memory. The image executes in the secure world. BL2 +relies on BL31 to pass control to the BL32 image, if present. Hence, BL2 +populates a platform-specific area of memory with the entrypoint/load-address +of the BL32 image. The value of the Saved Processor Status Register (``SPSR``) +for entry into BL32 is not determined by BL2, it is initialized by the +Secure-EL1 Payload Dispatcher (see later) within BL31, which is responsible for +managing interaction with BL32. This information is passed to BL31. + +BL33 (Non-trusted Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the BL33 image (e.g. UEFI or other test or boot software) from +platform storage into non-secure memory as defined by the platform. + +BL2 relies on EL3 Runtime Software to pass control to BL33 once secure state +initialization is complete. Hence, BL2 populates a platform-specific area of +memory with the entrypoint and Saved Program Status Register (``SPSR``) of the +normal world software image. The entrypoint is the load address of the BL33 +image. The ``SPSR`` is determined as specified in Section 5.13 of the +`PSCI PDD`_. This information is passed to the EL3 Runtime Software. + +AArch64 BL31 (EL3 Runtime Software) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 execution continues as follows: + +#. BL2 passes control back to BL1 by raising an SMC, providing BL1 with the + BL31 entrypoint. The exception is handled by the SMC exception handler + installed by BL1. + +#. BL1 turns off the MMU and flushes the caches. It clears the + ``SCTLR_EL3.M/I/C`` bits, flushes the data cache to the point of coherency + and invalidates the TLBs. + +#. BL1 passes control to BL31 at the specified entrypoint at EL3. + +AArch64 BL31 +~~~~~~~~~~~~ + +The image for this stage is loaded by BL2 and BL1 passes control to BL31 at +EL3. BL31 executes solely in trusted SRAM. BL31 is linked against and +loaded at a platform-specific base address (more information can be found later +in this document). The functionality implemented by BL31 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Currently, BL31 performs a similar architectural initialization to BL1 as +far as system register settings are concerned. Since BL1 code resides in ROM, +architectural initialization in BL31 allows override of any previous +initialization done by BL1. + +BL31 initializes the per-CPU data framework, which provides a cache of +frequently accessed per-CPU data optimised for fast, concurrent manipulation +on different CPUs. This buffer includes pointers to per-CPU contexts, crash +buffer, CPU reset and power down operations, PSCI data, platform data and so on. + +It then replaces the exception vectors populated by BL1 with its own. BL31 +exception vectors implement more elaborate support for handling SMCs since this +is the only mechanism to access the runtime services implemented by BL31 (PSCI +for example). BL31 checks each SMC for validity as specified by the +`SMC calling convention PDD`_ before passing control to the required SMC +handler routine. + +BL31 programs the ``CNTFRQ_EL0`` register with the clock frequency of the system +counter, which is provided by the platform. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 performs detailed platform initialization, which enables normal world +software to function correctly. + +On ARM platforms, this consists of the following: + +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Initialize the generic interrupt controller. +- Initialize the power controller device. +- Detect the system topology. + +Runtime services initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 is responsible for initializing the runtime services. One of them is PSCI. + +As part of the PSCI initializations, BL31 detects the system topology. It also +initializes the data structures that implement the state machine used to track +the state of power domain nodes. The state can be one of ``OFF``, ``RUN`` or +``RETENTION``. All secondary CPUs are initially in the ``OFF`` state. The cluster +that the primary CPU belongs to is ``ON``; any other cluster is ``OFF``. It also +initializes the locks that protect them. BL31 accesses the state of a CPU or +cluster immediately after reset and before the data cache is enabled in the +warm boot path. It is not currently possible to use 'exclusive' based spinlocks, +therefore BL31 uses locks based on Lamport's Bakery algorithm instead. + +The runtime service framework and its initialization is described in more +detail in the "EL3 runtime services framework" section below. + +Details about the status of the PSCI implementation are provided in the +"Power State Coordination Interface" section below. + +AArch64 BL32 (Secure-EL1 Payload) image initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a BL32 image is present then there must be a matching Secure-EL1 Payload +Dispatcher (SPD) service (see later for details). During initialization +that service must register a function to carry out initialization of BL32 +once the runtime services are fully initialized. BL31 invokes such a +registered function to initialize BL32 before running BL33. This initialization +is not necessary for AArch32 SPs. + +Details on BL32 initialization and the SPD's role are described in the +"Secure-EL1 Payloads and Dispatchers" section below. + +BL33 (Non-trusted Firmware) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +EL3 Runtime Software initializes the EL2 or EL1 processor context for normal- +world cold boot, ensuring that no secure state information finds its way into +the non-secure execution state. EL3 Runtime Software uses the entrypoint +information provided by BL2 to jump to the Non-trusted firmware image (BL33) +at the highest available Exception Level (EL2 if available, otherwise EL1). + +Using alternative Trusted Boot Firmware in place of BL1 & BL2 (AArch64 only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have existing implementations of Trusted Boot Firmware that +would like to use ARM Trusted Firmware BL31 for the EL3 Runtime Software. To +enable this firmware architecture it is important to provide a fully documented +and stable interface between the Trusted Boot Firmware and BL31. + +Future changes to the BL31 interface will be done in a backwards compatible +way, and this enables these firmware components to be independently enhanced/ +updated to develop and exploit new functionality. + +Required CPU state when calling ``bl31_entrypoint()`` during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch64 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +X0 and X1 can be used to pass information from the Trusted Boot Firmware to the +platform code in BL31: + +:: + + X0 : Reserved for common Trusted Firmware information + X1 : Platform specific information + +BL31 zero-init sections (e.g. ``.bss``) should not contain valid data on entry, +these will be zero filled prior to invoking platform setup code. + +Use of the X0 and X1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and passed from ``bl31_entrypoint()`` to +``bl31_early_platform_setup()``. The value of these parameters is never directly +used by the common BL31 code. + +The convention is that ``X0`` conveys information regarding the BL31, BL32 and +BL33 images from the Trusted Boot firmware and ``X1`` can be used for other +platform specific purpose. This convention allows platforms which use ARM +Trusted Firmware's BL1 and BL2 images to transfer additional platform specific +information from Secure Boot without conflicting with future evolution of the +Trusted Firmware using ``X0`` to pass a ``bl31_params`` structure. + +BL31 common and SPD initialization code depends on image and entrypoint +information about BL33 and BL32, which is provided via BL31 platform APIs. +This information is required until the start of execution of BL33. This +information can be provided in a platform defined manner, e.g. compiled into +the platform code in BL31, or provided in a platform defined memory location +by the Trusted Boot firmware, or passed from the Trusted Boot Firmware via the +Cold boot Initialization parameters. This data may need to be cleaned out of +the CPU caches if it is provided by an earlier boot stage and then accessed by +BL31 platform code before the caches are enabled. + +ARM Trusted Firmware's BL2 implementation passes a ``bl31_params`` structure in +``X0`` and the ARM development platforms interpret this in the BL31 platform +code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +BL31 does not depend on the enabled state of the MMU, data caches or +interconnect coherency on entry to ``bl31_entrypoint()``. If these are disabled +on entry, these should be enabled during ``bl31_plat_arch_setup()``. + +Data structures used in the BL31 cold boot interface +'''''''''''''''''''''''''''''''''''''''''''''''''''' + +These structures are designed to support compatibility and independent +evolution of the structures and the firmware images. For example, a version of +BL31 that can interpret the BL3x image information from different versions of +BL2, a platform that uses an extended entry\_point\_info structure to convey +additional register information to BL31, or a ELF image loader that can convey +more details about the firmware images. + +To support these scenarios the structures are versioned and sized, which enables +BL31 to detect which information is present and respond appropriately. The +``param_header`` is defined to capture this information: + +.. code:: c + + typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ + } param_header_t; + +The structures using this format are ``entry_point_info``, ``image_info`` and +``bl31_params``. The code that allocates and populates these structures must set +the header fields appropriately, and the ``SET_PARAM_HEAD()`` a macro is defined +to simplify this action. + +Required CPU state for BL31 Warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, ARM Trusted +Firmware provides the platform power management code with a Warm boot +initialization entry-point, to be invoked by the CPU immediately after the +reset handler. On entry to the Warm boot initialization function the calling +CPU must be in AArch64 EL3, little-endian data access and all interrupt sources +masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +The PSCI implementation will initialize the processor state and ensure that the +platform power management code is then invoked as required to initialize all +necessary system, cluster and CPU resources. + +AArch32 EL3 Runtime Software entrypoint interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable this firmware architecture it is important to provide a fully +documented and stable interface between the Trusted Boot Firmware and the +AArch32 EL3 Runtime Software. + +Future changes to the entrypoint interface will be done in a backwards +compatible way, and this enables these firmware components to be independently +enhanced/updated to develop and exploit new functionality. + +Required CPU state when entering during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch32 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +R0 and R1 are used to pass information from the Trusted Boot Firmware to the +platform code in AArch32 EL3 Runtime Software: + +:: + + R0 : Reserved for common Trusted Firmware information + R1 : Platform specific information + +Use of the R0 and R1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and the convention is that ``R0`` conveys +information regarding the BL3x images from the Trusted Boot firmware and ``R1`` +can be used for other platform specific purpose. This convention allows +platforms which use ARM Trusted Firmware's BL1 and BL2 images to transfer +additional platform specific information from Secure Boot without conflicting +with future evolution of the Trusted Firmware using ``R0`` to pass a ``bl_params`` +structure. + +The AArch32 EL3 Runtime Software is responsible for entry into BL33. This +information can be obtained in a platform defined manner, e.g. compiled into +the AArch32 EL3 Runtime Software, or provided in a platform defined memory +location by the Trusted Boot firmware, or passed from the Trusted Boot Firmware +via the Cold boot Initialization parameters. This data may need to be cleaned +out of the CPU caches if it is provided by an earlier boot stage and then +accessed by AArch32 EL3 Runtime Software before the caches are enabled. + +When using AArch32 EL3 Runtime Software, the ARM development platforms pass a +``bl_params`` structure in ``R0`` from BL2 to be interpreted by AArch32 EL3 Runtime +Software platform code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +AArch32 EL3 Runtime Software must not depend on the enabled state of the MMU, +data caches or interconnect coherency in its entrypoint. They must be explicitly +enabled if required. + +Data structures used in cold boot interface +''''''''''''''''''''''''''''''''''''''''''' + +The AArch32 EL3 Runtime Software cold boot interface uses ``bl_params`` instead +of ``bl31_params``. The ``bl_params`` structure is based on the convention +described in AArch64 BL31 cold boot interface section. + +Required CPU state for warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, AArch32 EL3 +Runtime Software must ensure execution of a warm boot initialization entrypoint. +If ARM Trusted Firmware BL1 is used and the PROGRAMMABLE\_RESET\_ADDRESS build +flag is false, then AArch32 EL3 Runtime Software must ensure that BL1 branches +to the warm boot entrypoint by arranging for the BL1 platform function, +plat\_get\_my\_entrypoint(), to return a non-zero value. + +In this case, the warm boot entrypoint must be in AArch32 EL3, little-endian +data access and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +The warm boot entrypoint may be implemented by using the ARM Trusted Firmware +``psci_warmboot_entrypoint()`` function. In that case, the platform must fulfil +the pre-requisites mentioned in the `PSCI Library integration guide`_. + +EL3 runtime services framework +------------------------------ + +Software executing in the non-secure state and in the secure state at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +returned. + +The EL3 runtime services framework enables the development of services by +different providers that can be easily integrated into final product firmware. +The following sections describe the framework which facilitates the +registration, initialization and use of runtime services in EL3 Runtime +Software (BL31). + +The design of the runtime services depends heavily on the concepts and +definitions described in the `SMCCC`_, in particular SMC Function IDs, Owning +Entity Numbers (OEN), Fast and Yielding calls, and the SMC32 and SMC64 calling +conventions. Please refer to that document for more detailed explanation of +these terms. + +The following runtime services are expected to be implemented first. They have +not all been instantiated in the current implementation. + +#. Standard service calls + + This service is for management of the entire system. The Power State + Coordination Interface (`PSCI`_) is the first set of standard service calls + defined by ARM (see PSCI section later). + +#. Secure-EL1 Payload Dispatcher service + + If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then + it also requires a *Secure Monitor* at EL3 to switch the EL1 processor + context between the normal world (EL1/EL2) and trusted world (Secure-EL1). + The Secure Monitor will make these world switches in response to SMCs. The + `SMCCC`_ provides for such SMCs with the Trusted OS Call and Trusted + Application Call OEN ranges. + + The interface between the EL3 Runtime Software and the Secure-EL1 Payload is + not defined by the `SMCCC`_ or any other standard. As a result, each + Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime + service - within ARM Trusted Firmware this service is referred to as the + Secure-EL1 Payload Dispatcher (SPD). + + ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and its + associated Dispatcher (TSPD). Details of SPD design and TSP/TSPD operation + are described in the "Secure-EL1 Payloads and Dispatchers" section below. + +#. CPU implementation service + + This service will provide an interface to CPU implementation specific + services for a given platform e.g. access to processor errata workarounds. + This service is currently unimplemented. + +Additional services for ARM Architecture, SiP and OEM calls can be implemented. +Each implemented service handles a range of SMC function identifiers as +described in the `SMCCC`_. + +Registration +~~~~~~~~~~~~ + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. This macro instantiates a ``const struct rt_svc_desc`` for the service with these details (see ``runtime_svc.h``). +This structure is allocated in a special ELF section ``rt_svc_descs``, enabling +the framework to find all service descriptors included into BL31. + +The specific service for a SMC Function is selected based on the OEN and call +type of the Function ID, and the framework uses that information in the service +descriptor to identify the handler for the SMC Call. + +The service descriptors do not include information to identify the precise set +of SMC function identifiers supported by this service implementation, the +security state from which such calls are valid nor the capability to support +64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately +to these aspects of a SMC call is the responsibility of the service +implementation, the framework is focused on integration of services from +different providers and minimizing the time taken by the framework before the +service handler is invoked. + +Details of the parameters, requirements and behavior of the initialization and +call handling functions are provided in the following sections. + +Initialization +~~~~~~~~~~~~~~ + +``runtime_svc_init()`` in ``runtime_svc.c`` initializes the runtime services +framework running on the primary CPU during cold boot as part of the BL31 +initialization. This happens prior to initializing a Trusted OS and running +Normal world boot firmware that might in turn use these services. +Initialization involves validating each of the declared runtime service +descriptors, calling the service initialization function and populating the +index used for runtime lookup of the service. + +The BL31 linker script collects all of the declared service descriptors into a +single array and defines symbols that allow the framework to locate and traverse +the array, and determine its size. + +The framework does basic validation of each descriptor to halt firmware +initialization if service declaration errors are detected. The framework does +not check descriptors for the following error conditions, and may behave in an +unpredictable manner under such scenarios: + +#. Overlapping OEN ranges +#. Multiple descriptors for the same range of OENs and ``call_type`` +#. Incorrect range of owning entity numbers for a given ``call_type`` + +Once validated, the service ``init()`` callback is invoked. This function carries +out any essential EL3 initialization before servicing requests. The ``init()`` +function is only invoked on the primary CPU during cold boot. If the service +uses per-CPU data this must either be initialized for all CPUs during this call, +or be done lazily when a CPU first issues an SMC call to that service. If +``init()`` returns anything other than ``0``, this is treated as an initialization +error and the service is ignored: this does not cause the firmware to halt. + +The OEN and call type fields present in the SMC Function ID cover a total of +128 distinct services, but in practice a single descriptor can cover a range of +OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a +service handler, the framework uses an array of 128 indices that map every +distinct OEN/call-type combination either to one of the declared services or to +indicate the service is not handled. This ``rt_svc_descs_indices[]`` array is +populated for all of the OENs covered by a service after the service ``init()`` +function has reported success. So a service that fails to initialize will never +have it's ``handle()`` function invoked. + +The following figure shows how the ``rt_svc_descs_indices[]`` index maps the SMC +Function ID call type and OEN onto a specific service handler in the +``rt_svc_descs[]`` array. + +|Image 1| + +Handling an SMC +~~~~~~~~~~~~~~~ + +When the EL3 runtime services framework receives a Secure Monitor Call, the SMC +Function ID is passed in W0 from the lower exception level (as per the +`SMCCC`_). If the calling register width is AArch32, it is invalid to invoke an +SMC Function which indicates the SMC64 calling convention: such calls are +ignored and return the Unknown SMC Function Identifier result code ``0xFFFFFFFF`` +in R0/X0. + +Bit[31] (fast/yielding call) and bits[29:24] (owning entity number) of the SMC +Function ID are combined to index into the ``rt_svc_descs_indices[]`` array. The +resulting value might indicate a service that has no handler, in this case the +framework will also report an Unknown SMC Function ID. Otherwise, the value is +used as a further index into the ``rt_svc_descs[]`` array to locate the required +service and handler. + +The service's ``handle()`` callback is provided with five of the SMC parameters +directly, the others are saved into memory for retrieval (if needed) by the +handler. The handler is also provided with an opaque ``handle`` for use with the +supporting library for parameter retrieval, setting return values and context +manipulation; and with ``flags`` indicating the security state of the caller. The +framework finally sets up the execution stack for the handler, and invokes the +services ``handle()`` function. + +On return from the handler the result registers are populated in X0-X3 before +restoring the stack and CPU state and returning from the original SMC. + +Power State Coordination Interface +---------------------------------- + +TODO: Provide design walkthrough of PSCI implementation. + +The PSCI v1.0 specification categorizes APIs as optional and mandatory. All the +mandatory APIs in PSCI v1.0 and all the APIs in PSCI v0.2 draft specification +`Power State Coordination Interface PDD`_ are implemented. The table lists +the PSCI v1.0 APIs and their support in generic code. + +An API implementation might have a dependency on platform code e.g. CPU\_SUSPEND +requires the platform to export a part of the implementation. Hence the level +of support of the mandatory APIs depends upon the support exported by the +platform port as well. The Juno and FVP (all variants) platforms export all the +required support. + ++-----------------------------+-------------+-------------------------------+ +| PSCI v1.0 API | Supported | Comments | ++=============================+=============+===============================+ +| ``PSCI_VERSION`` | Yes | The version returned is 1.0 | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_ON`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``AFFINITY_INFO`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_TYPE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_CPU`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_FEATURES`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_FREEZE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_DEFAULT_SUSPEND`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``NODE_HW_STATE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_SET_SUSPEND_MODE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_RESIDENCY`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_COUNT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ + +\*Note : These PSCI APIs require platform power management hooks to be +registered with the generic PSCI code to be supported. + +\*\*Note : These PSCI APIs require appropriate Secure Payload Dispatcher +hooks to be registered with the generic PSCI code to be supported. + +The PSCI implementation in ARM Trusted Firmware is a library which can be +integrated with AArch64 or AArch32 EL3 Runtime Software for ARMv8-A systems. +A guide to integrating PSCI library with AArch32 EL3 Runtime Software +can be found `here`_. + +Secure-EL1 Payloads and Dispatchers +----------------------------------- + +On a production system that includes a Trusted OS running in Secure-EL1/EL0, +the Trusted OS is coupled with a companion runtime service in the BL31 +firmware. This service is responsible for the initialisation of the Trusted +OS and all communications with it. The Trusted OS is the BL32 stage of the +boot flow in ARM Trusted Firmware. The firmware will attempt to locate, load +and execute a BL32 image. + +ARM Trusted Firmware uses a more general term for the BL32 software that runs +at Secure-EL1 - the *Secure-EL1 Payload* - as it is not always a Trusted OS. + +The ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and a Test +Secure-EL1 Payload Dispatcher (TSPD) service as an example of how a Trusted OS +is supported on a production system using the Runtime Services Framework. On +such a system, the Test BL32 image and service are replaced by the Trusted OS +and its dispatcher service. The ARM Trusted Firmware build system expects that +the dispatcher will define the build flag ``NEED_BL32`` to enable it to include +the BL32 in the build either as a binary or to compile from source depending +on whether the ``BL32`` build option is specified or not. + +The TSP runs in Secure-EL1. It is designed to demonstrate synchronous +communication with the normal-world software running in EL1/EL2. Communication +is initiated by the normal-world software + +- either directly through a Fast SMC (as defined in the `SMCCC`_) + +- or indirectly through a `PSCI`_ SMC. The `PSCI`_ implementation in turn + informs the TSPD about the requested power management operation. This allows + the TSP to prepare for or respond to the power state change + +The TSPD service is responsible for. + +- Initializing the TSP + +- Routing requests and responses between the secure and the non-secure + states during the two types of communications just described + +Initializing a BL32 Image +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing +the BL32 image. It needs access to the information passed by BL2 to BL31 to do +so. This is provided by: + +.. code:: c + + entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t); + +which returns a reference to the ``entry_point_info`` structure corresponding to +the image which will be run in the specified security state. The SPD uses this +API to get entry point information for the SECURE image, BL32. + +In the absence of a BL32 image, BL31 passes control to the normal world +bootloader image (BL33). When the BL32 image is present, it is typical +that the SPD wants control to be passed to BL32 first and then later to BL33. + +To do this the SPD has to register a BL32 initialization function during +initialization of the SPD service. The BL32 initialization function has this +prototype: + +.. code:: c + + int32_t init(void); + +and is registered using the ``bl31_register_bl32_init()`` function. + +Trusted Firmware supports two approaches for the SPD to pass control to BL32 +before returning through EL3 and running the non-trusted firmware (BL33): + +#. In the BL32 setup function, use ``bl31_set_next_image_type()`` to + request that the exit from ``bl31_main()`` is to the BL32 entrypoint in + Secure-EL1. BL31 will exit to BL32 using the asynchronous method by + calling ``bl31_prepare_next_image_entry()`` and ``el3_exit()``. + + When the BL32 has completed initialization at Secure-EL1, it returns to + BL31 by issuing an SMC, using a Function ID allocated to the SPD. On + receipt of this SMC, the SPD service handler should switch the CPU context + from trusted to normal world and use the ``bl31_set_next_image_type()`` and + ``bl31_prepare_next_image_entry()`` functions to set up the initial return to + the normal world firmware BL33. On return from the handler the framework + will exit to EL2 and run BL33. + +#. The BL32 setup function registers an initialization function using + ``bl31_register_bl32_init()`` which provides a SPD-defined mechanism to + invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL32 + entrypoint. + NOTE: The Test SPD service included with the Trusted Firmware provides one + implementation of such a mechanism. + + On completion BL32 returns control to BL31 via a SMC, and on receipt the + SPD service handler invokes the synchronous call return mechanism to return + to the BL32 initialization function. On return from this function, + ``bl31_main()`` will set up the return to the normal world firmware BL33 and + continue the boot process in the normal world. + +#. .. rubric:: Crash Reporting in BL31 + :name: crash-reporting-in-bl31 + +BL31 implements a scheme for reporting the processor state when an unhandled +exception is encountered. The reporting mechanism attempts to preserve all the +register contents and report it via a dedicated UART (PL011 console). BL31 +reports the general purpose, EL3, Secure EL1 and some EL2 state registers. + +A dedicated per-CPU crash stack is maintained by BL31 and this is retrieved via +the per-CPU pointer cache. The implementation attempts to minimise the memory +required for this feature. The file ``crash_reporting.S`` contains the +implementation for crash reporting. + +The sample crash output is shown below. + +:: + + x0 :0x000000004F00007C + x1 :0x0000000007FFFFFF + x2 :0x0000000004014D50 + x3 :0x0000000000000000 + x4 :0x0000000088007998 + x5 :0x00000000001343AC + x6 :0x0000000000000016 + x7 :0x00000000000B8A38 + x8 :0x00000000001343AC + x9 :0x00000000000101A8 + x10 :0x0000000000000002 + x11 :0x000000000000011C + x12 :0x00000000FEFDC644 + x13 :0x00000000FED93FFC + x14 :0x0000000000247950 + x15 :0x00000000000007A2 + x16 :0x00000000000007A4 + x17 :0x0000000000247950 + x18 :0x0000000000000000 + x19 :0x00000000FFFFFFFF + x20 :0x0000000004014D50 + x21 :0x000000000400A38C + x22 :0x0000000000247950 + x23 :0x0000000000000010 + x24 :0x0000000000000024 + x25 :0x00000000FEFDC868 + x26 :0x00000000FEFDC86A + x27 :0x00000000019EDEDC + x28 :0x000000000A7CFDAA + x29 :0x0000000004010780 + x30 :0x000000000400F004 + scr_el3 :0x0000000000000D3D + sctlr_el3 :0x0000000000C8181F + cptr_el3 :0x0000000000000000 + tcr_el3 :0x0000000080803520 + daif :0x00000000000003C0 + mair_el3 :0x00000000000004FF + spsr_el3 :0x00000000800003CC + elr_el3 :0x000000000400C0CC + ttbr0_el3 :0x00000000040172A0 + esr_el3 :0x0000000096000210 + sp_el3 :0x0000000004014D50 + far_el3 :0x000000004F00007C + spsr_el1 :0x0000000000000000 + elr_el1 :0x0000000000000000 + spsr_abt :0x0000000000000000 + spsr_und :0x0000000000000000 + spsr_irq :0x0000000000000000 + spsr_fiq :0x0000000000000000 + sctlr_el1 :0x0000000030C81807 + actlr_el1 :0x0000000000000000 + cpacr_el1 :0x0000000000300000 + csselr_el1 :0x0000000000000002 + sp_el1 :0x0000000004028800 + esr_el1 :0x0000000000000000 + ttbr0_el1 :0x000000000402C200 + ttbr1_el1 :0x0000000000000000 + mair_el1 :0x00000000000004FF + amair_el1 :0x0000000000000000 + tcr_el1 :0x0000000000003520 + tpidr_el1 :0x0000000000000000 + tpidr_el0 :0x0000000000000000 + tpidrro_el0 :0x0000000000000000 + dacr32_el2 :0x0000000000000000 + ifsr32_el2 :0x0000000000000000 + par_el1 :0x0000000000000000 + far_el1 :0x0000000000000000 + afsr0_el1 :0x0000000000000000 + afsr1_el1 :0x0000000000000000 + contextidr_el1 :0x0000000000000000 + vbar_el1 :0x0000000004027000 + cntp_ctl_el0 :0x0000000000000000 + cntp_cval_el0 :0x0000000000000000 + cntv_ctl_el0 :0x0000000000000000 + cntv_cval_el0 :0x0000000000000000 + cntkctl_el1 :0x0000000000000000 + fpexc32_el2 :0x0000000004000700 + sp_el0 :0x0000000004010780 + +Guidelines for Reset Handlers +----------------------------- + +Trusted Firmware implements a framework that allows CPU and platform ports to +perform actions very early after a CPU is released from reset in both the cold +and warm boot paths. This is done by calling the ``reset_handler()`` function in +both the BL1 and BL31 images. It in turn calls the platform and CPU specific +reset handling functions. + +Details for implementing a CPU specific reset handler can be found in +Section 8. Details for implementing a platform specific reset handler can be +found in the `Porting Guide`_ (see the ``plat_reset_handler()`` function). + +When adding functionality to a reset handler, keep in mind that if a different +reset handling behavior is required between the first and the subsequent +invocations of the reset handling code, this should be detected at runtime. +In other words, the reset handler should be able to detect whether an action has +already been performed and act as appropriate. Possible courses of actions are, +e.g. skip the action the second time, or undo/redo it. + +CPU specific operations framework +--------------------------------- + +Certain aspects of the ARMv8 architecture are implementation defined, +that is, certain behaviours are not architecturally defined, but must be defined +and documented by individual processor implementations. The ARM Trusted +Firmware implements a framework which categorises the common implementation +defined behaviours and allows a processor to export its implementation of that +behaviour. The categories are: + +#. Processor specific reset sequence. + +#. Processor specific power down sequences. + +#. Processor specific register dumping as a part of crash reporting. + +#. Errata status reporting. + +Each of the above categories fulfils a different requirement. + +#. allows any processor specific initialization before the caches and MMU + are turned on, like implementation of errata workarounds, entry into + the intra-cluster coherency domain etc. + +#. allows each processor to implement the power down sequence mandated in + its Technical Reference Manual (TRM). + +#. allows a processor to provide additional information to the developer + in the event of a crash, for example Cortex-A53 has registers which + can expose the data cache contents. + +#. allows a processor to define a function that inspects and reports the status + of all errata workarounds on that processor. + +Please note that only 2. is mandated by the TRM. + +The CPU specific operations framework scales to accommodate a large number of +different CPUs during power down and reset handling. The platform can specify +any CPU optimization it wants to enable for each CPU. It can also specify +the CPU errata workarounds to be applied for each CPU type during reset +handling by defining CPU errata compile time macros. Details on these macros +can be found in the `cpu-specific-build-macros.rst`_ file. + +The CPU specific operations framework depends on the ``cpu_ops`` structure which +needs to be exported for each type of CPU in the platform. It is defined in +``include/lib/cpus/aarch64/cpu_macros.S`` and has the following fields : ``midr``, +``reset_func()``, ``cpu_pwr_down_ops`` (array of power down functions) and +``cpu_reg_dump()``. + +The CPU specific files in ``lib/cpus`` export a ``cpu_ops`` data structure with +suitable handlers for that CPU. For example, ``lib/cpus/aarch64/cortex_a53.S`` +exports the ``cpu_ops`` for Cortex-A53 CPU. According to the platform +configuration, these CPU specific files must be included in the build by +the platform makefile. The generic CPU specific operations framework code exists +in ``lib/cpus/aarch64/cpu_helpers.S``. + +CPU specific Reset Handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After a reset, the state of the CPU when it calls generic reset handler is: +MMU turned off, both instruction and data caches turned off and not part +of any coherency domain. + +The BL entrypoint code first invokes the ``plat_reset_handler()`` to allow +the platform to perform any system initialization required and any system +errata workarounds that needs to be applied. The ``get_cpu_ops_ptr()`` reads +the current CPU midr, finds the matching ``cpu_ops`` entry in the ``cpu_ops`` +array and returns it. Note that only the part number and implementer fields +in midr are used to find the matching ``cpu_ops`` entry. The ``reset_func()`` in +the returned ``cpu_ops`` is then invoked which executes the required reset +handling for that CPU and also any errata workarounds enabled by the platform. +This function must preserve the values of general purpose registers x20 to x29. + +Refer to Section "Guidelines for Reset Handlers" for general guidelines +regarding placement of code in a reset handler. + +CPU specific power down sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During the BL31 initialization sequence, the pointer to the matching ``cpu_ops`` +entry is stored in per-CPU data by ``init_cpu_ops()`` so that it can be quickly +retrieved during power down sequences. + +Various CPU drivers register handlers to perform power down at certain power +levels for that specific CPU. The PSCI service, upon receiving a power down +request, determines the highest power level at which to execute power down +sequence for a particular CPU. It uses the ``prepare_cpu_pwr_dwn()`` function to +pick the right power down handler for the requested level. The function +retrieves ``cpu_ops`` pointer member of per-CPU data, and from that, further +retrieves ``cpu_pwr_down_ops`` array, and indexes into the required level. If the +requested power level is higher than what a CPU driver supports, the handler +registered for highest level is invoked. + +At runtime the platform hooks for power down are invoked by the PSCI service to +perform platform specific operations during a power down sequence, for example +turning off CCI coherency during a cluster power down. + +CPU specific register reporting during crash +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the crash reporting is enabled in BL31, when a crash occurs, the crash +reporting framework calls ``do_cpu_reg_dump`` which retrieves the matching +``cpu_ops`` using ``get_cpu_ops_ptr()`` function. The ``cpu_reg_dump()`` in +``cpu_ops`` is invoked, which then returns the CPU specific register values to +be reported and a pointer to the ASCII list of register names in a format +expected by the crash reporting framework. + +CPU errata status reporting +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Errata workarounds for CPUs supported in ARM Trusted Firmware are applied during +both cold and warm boots, shortly after reset. Individual Errata workarounds are +enabled as build options. Some errata workarounds have potential run-time +implications; therefore some are enabled by default, others not. Platform ports +shall override build options to enable or disable errata as appropriate. The CPU +drivers take care of applying errata workarounds that are enabled and applicable +to a given CPU. Refer to the section titled *CPU Errata Workarounds* in `CPUBM`_ +for more information. + +Functions in CPU drivers that apply errata workaround must follow the +conventions listed below. + +The errata workaround must be authored as two separate functions: + +- One that checks for errata. This function must determine whether that errata + applies to the current CPU. Typically this involves matching the current + CPUs revision and variant against a value that's known to be affected by the + errata. If the function determines that the errata applies to this CPU, it + must return ``ERRATA_APPLIES``; otherwise, it must return + ``ERRATA_NOT_APPLIES``. The utility functions ``cpu_get_rev_var`` and + ``cpu_rev_var_ls`` functions may come in handy for this purpose. + +For an errata identified as ``E``, the check function must be named +``check_errata_E``. + +This function will be invoked at different times, both from assembly and from +C run time. Therefore it must follow AAPCS, and must not use stack. + +- Another one that applies the errata workaround. This function would call the + check function described above, and applies errata workaround if required. + +CPU drivers that apply errata workaround can optionally implement an assembly +function that report the status of errata workarounds pertaining to that CPU. +For a driver that registers the CPU, for example, ``cpux`` via. ``declare_cpu_ops`` +macro, the errata reporting function, if it exists, must be named +``cpux_errata_report``. This function will always be called with MMU enabled; it +must follow AAPCS and may use stack. + +In a debug build of ARM Trusted Firmware, on a CPU that comes out of reset, both +BL1 and the run time firmware (BL31 in AArch64, and BL32 in AArch32) will invoke +errata status reporting function, if one exists, for that type of CPU. + +To report the status of each errata workaround, the function shall use the +assembler macro ``report_errata``, passing it: + +- The build option that enables the errata; + +- The name of the CPU: this must be the same identifier that CPU driver + registered itself with, using ``declare_cpu_ops``; + +- And the errata identifier: the identifier must match what's used in the + errata's check function described above. + +The errata status reporting function will be called once per CPU type/errata +combination during the software's active life time. + +It's expected that whenever an errata workaround is submitted to ARM Trusted +Firmware, the errata reporting function is appropriately extended to report its +status as well. + +Reporting the status of errata workaround is for informational purpose only; it +has no functional significance. + +Memory layout of BL images +-------------------------- + +Each bootloader image can be divided in 2 parts: + +- the static contents of the image. These are data actually stored in the + binary on the disk. In the ELF terminology, they are called ``PROGBITS`` + sections; + +- the run-time contents of the image. These are data that don't occupy any + space in the binary on the disk. The ELF binary just contains some + metadata indicating where these data will be stored at run-time and the + corresponding sections need to be allocated and initialized at run-time. + In the ELF terminology, they are called ``NOBITS`` sections. + +All PROGBITS sections are grouped together at the beginning of the image, +followed by all NOBITS sections. This is true for all Trusted Firmware images +and it is governed by the linker scripts. This ensures that the raw binary +images are as small as possible. If a NOBITS section was inserted in between +PROGBITS sections then the resulting binary file would contain zero bytes in +place of this NOBITS section, making the image unnecessarily bigger. Smaller +images allow faster loading from the FIP to the main memory. + +Linker scripts and symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each bootloader stage image layout is described by its own linker script. The +linker scripts export some symbols into the program symbol table. Their values +correspond to particular addresses. The trusted firmware code can refer to these +symbols to figure out the image memory layout. + +Linker symbols follow the following naming convention in the trusted firmware. + +- ``__
_START__`` + + Start address of a given section named ``
``. + +- ``__
_END__`` + + End address of a given section named ``
``. If there is an alignment + constraint on the section's end address then ``__
_END__`` corresponds + to the end address of the section's actual contents, rounded up to the right + boundary. Refer to the value of ``__
_UNALIGNED_END__`` to know the + actual end address of the section's contents. + +- ``__
_UNALIGNED_END__`` + + End address of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. + +- ``__
_SIZE__`` + + Size (in bytes) of a given section named ``
``. If there is an + alignment constraint on the section's end address then ``__
_SIZE__`` + corresponds to the size of the section's actual contents, rounded up to the + right boundary. In other words, ``__
_SIZE__ = __
_END__ - _
_START__``. Refer to the value of ``__
_UNALIGNED_SIZE__`` + to know the actual size of the section's contents. + +- ``__
_UNALIGNED_SIZE__`` + + Size (in bytes) of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. In other words, + ``__
_UNALIGNED_SIZE__ = __
_UNALIGNED_END__ - __
_START__``. + +Some of the linker symbols are mandatory as the trusted firmware code relies on +them to be defined. They are listed in the following subsections. Some of them +must be provided for each bootloader stage and some are specific to a given +bootloader stage. + +The linker scripts define some extra, optional symbols. They are not actually +used by any code but they help in understanding the bootloader images' memory +layout as they are easy to spot in the link map files. + +Common linker symbols +^^^^^^^^^^^^^^^^^^^^^ + +All BL images share the following requirements: + +- The BSS section must be zero-initialised before executing any C code. +- The coherent memory section (if enabled) must be zero-initialised as well. +- The MMU setup code needs to know the extents of the coherent and read-only + memory regions to set the right memory attributes. When + ``SEPARATE_CODE_AND_RODATA=1``, it needs to know more specifically how the + read-only memory region is divided between code and data. + +The following linker symbols are defined for this purpose: + +- ``__BSS_START__`` +- ``__BSS_SIZE__`` +- ``__COHERENT_RAM_START__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_END__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_UNALIGNED_SIZE__`` +- ``__RO_START__`` +- ``__RO_END__`` +- ``__TEXT_START__`` +- ``__TEXT_END__`` +- ``__RODATA_START__`` +- ``__RODATA_END__`` + +BL1's linker symbols +^^^^^^^^^^^^^^^^^^^^ + +BL1 being the ROM image, it has additional requirements. BL1 resides in ROM and +it is entirely executed in place but it needs some read-write memory for its +mutable data. Its ``.data`` section (i.e. its allocated read-write data) must be +relocated from ROM to RAM before executing any C code. + +The following additional linker symbols are defined for BL1: + +- ``__BL1_ROM_END__`` End address of BL1's ROM contents, covering its code + and ``.data`` section in ROM. +- ``__DATA_ROM_START__`` Start address of the ``.data`` section in ROM. Must be + aligned on a 16-byte boundary. +- ``__DATA_RAM_START__`` Address in RAM where the ``.data`` section should be + copied over. Must be aligned on a 16-byte boundary. +- ``__DATA_SIZE__`` Size of the ``.data`` section (in ROM or RAM). +- ``__BL1_RAM_START__`` Start address of BL1 read-write data. +- ``__BL1_RAM_END__`` End address of BL1 read-write data. + +How to choose the right base addresses for each bootloader stage image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There is currently no support for dynamic image loading in the Trusted Firmware. +This means that all bootloader images need to be linked against their ultimate +runtime locations and the base addresses of each image must be chosen carefully +such that images don't overlap each other in an undesired way. As the code +grows, the base addresses might need adjustments to cope with the new memory +layout. + +The memory layout is completely specific to the platform and so there is no +general recipe for choosing the right base addresses for each bootloader image. +However, there are tools to aid in understanding the memory layout. These are +the link map files: ``build///bl/bl.map``, with ```` +being the stage bootloader. They provide a detailed view of the memory usage of +each image. Among other useful information, they provide the end address of +each image. + +- ``bl1.map`` link map file provides ``__BL1_RAM_END__`` address. +- ``bl2.map`` link map file provides ``__BL2_END__`` address. +- ``bl31.map`` link map file provides ``__BL31_END__`` address. +- ``bl32.map`` link map file provides ``__BL32_END__`` address. + +For each bootloader image, the platform code must provide its start address +as well as a limit address that it must not overstep. The latter is used in the +linker scripts to check that the image doesn't grow past that address. If that +happens, the linker will issue a message similar to the following: + +:: + + aarch64-none-elf-ld: BLx has exceeded its limit. + +Additionally, if the platform memory layout implies some image overlaying like +on FVP, BL31 and TSP need to know the limit address that their PROGBITS +sections must not overstep. The platform code must provide those. + +When LOAD\_IMAGE\_V2 is disabled, Trusted Firmware provides a mechanism to +verify at boot time that the memory to load a new image is free to prevent +overwriting a previously loaded image. For this mechanism to work, the platform +must specify the memory available in the system as regions, where each region +consists of base address, total size and the free area within it (as defined +in the ``meminfo_t`` structure). Trusted Firmware retrieves these memory regions +by calling the corresponding platform API: + +- ``meminfo_t *bl1_plat_sec_mem_layout(void)`` +- ``meminfo_t *bl2_plat_sec_mem_layout(void)`` +- ``void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)`` +- ``void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)`` +- ``void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)`` + +For example, in the case of BL1 loading BL2, ``bl1_plat_sec_mem_layout()`` will +return the region defined by the platform where BL1 intends to load BL2. The +``load_image()`` function will check that the memory where BL2 will be loaded is +within the specified region and marked as free. + +The actual number of regions and their base addresses and sizes is platform +specific. The platform may return the same region or define a different one for +each API. However, the overlap verification mechanism applies only to a single +region. Hence, it is the platform responsibility to guarantee that different +regions do not overlap, or that if they do, the overlapping images are not +accessed at the same time. This could be used, for example, to load temporary +images (e.g. certificates) or firmware images prior to being transfered to its +corresponding processor (e.g. the SCP BL2 image). + +To reduce fragmentation and simplify the tracking of free memory, all the free +memory within a region is always located in one single buffer defined by its +base address and size. Trusted Firmware implements a top/bottom load approach: +after a new image is loaded, it checks how much memory remains free above and +below the image. The smallest area is marked as unavailable, while the larger +area becomes the new free memory buffer. Platforms should take this behaviour +into account when defining the base address for each of the images. For example, +if an image is loaded near the middle of the region, small changes in image size +could cause a flip between a top load and a bottom load, which may result in an +unexpected memory layout. + +The following diagram is an example of an image loaded in the bottom part of +the memory region. The region is initially free (nothing has been loaded yet): + +:: + + Memory region + +----------+ + | | + | | <<<<<<<<<<<<< Free + | | + |----------| +------------+ + | image | <<<<<<<<<<<<< | image | + |----------| +------------+ + | xxxxxxxx | <<<<<<<<<<<<< Marked as unavailable + +----------+ + +And the following diagram is an example of an image loaded in the top part: + +:: + + Memory region + +----------+ + | xxxxxxxx | <<<<<<<<<<<<< Marked as unavailable + |----------| +------------+ + | image | <<<<<<<<<<<<< | image | + |----------| +------------+ + | | + | | <<<<<<<<<<<<< Free + | | + +----------+ + +When LOAD\_IMAGE\_V2 is enabled, Trusted Firmware does not provide any mechanism +to verify at boot time that the memory to load a new image is free to prevent +overwriting a previously loaded image. The platform must specify the memory +available in the system for all the relevant BL images to be loaded. + +For example, in the case of BL1 loading BL2, ``bl1_plat_sec_mem_layout()`` will +return the region defined by the platform where BL1 intends to load BL2. The +``load_image()`` function performs bounds check for the image size based on the +base and maximum image size provided by the platforms. Platforms must take +this behaviour into account when defining the base/size for each of the images. + +Memory layout on ARM development platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following list describes the memory layout on the ARM development platforms: + +- A 4KB page of shared memory is used for communication between Trusted + Firmware and the platform's power controller. This is located at the base of + Trusted SRAM. The amount of Trusted SRAM available to load the bootloader + images is reduced by the size of the shared memory. + + The shared memory is used to store the CPUs' entrypoint mailbox. On Juno, + this is also used for the MHU payload when passing messages to and from the + SCP. + +- On FVP, BL1 is originally sitting in the Trusted ROM at address ``0x0``. On + Juno, BL1 resides in flash memory at address ``0x0BEC0000``. BL1 read-write + data are relocated to the top of Trusted SRAM at runtime. + +- EL3 Runtime Software, BL31 for AArch64 and BL32 for AArch32 (e.g. SP\_MIN), + is loaded at the top of the Trusted SRAM, such that its NOBITS sections will + overwrite BL1 R/W data. This implies that BL1 global variables remain valid + only until execution reaches the EL3 Runtime Software entry point during a + cold boot. + +- BL2 is loaded below EL3 Runtime Software. + +- On Juno, SCP\_BL2 is loaded temporarily into the EL3 Runtime Software memory + region and transfered to the SCP before being overwritten by EL3 Runtime + Software. + +- BL32 (for AArch64) can be loaded in one of the following locations: + + - Trusted SRAM + - Trusted DRAM (FVP only) + - Secure region of DRAM (top 16MB of DRAM configured by the TrustZone + controller) + + When BL32 (for AArch64) is loaded into Trusted SRAM, its NOBITS sections + are allowed to overlay BL2. This memory layout is designed to give the + BL32 image as much memory as possible when it is loaded into Trusted SRAM. + +When LOAD\_IMAGE\_V2 is disabled the memory regions for the overlap detection +mechanism at boot time are defined as follows (shown per API): + +- ``meminfo_t *bl1_plat_sec_mem_layout(void)`` + + This region corresponds to the whole Trusted SRAM except for the shared + memory at the base. This region is initially free. At boot time, BL1 will + mark the BL1(rw) section within this region as occupied. The BL1(rw) section + is placed at the top of Trusted SRAM. + +- ``meminfo_t *bl2_plat_sec_mem_layout(void)`` + + This region corresponds to the whole Trusted SRAM as defined by + ``bl1_plat_sec_mem_layout()``, but with the BL1(rw) section marked as + occupied. This memory region is used to check that BL2 and BL31 do not + overlap with each other. BL2\_BASE and BL1\_RW\_BASE are carefully chosen so + that the memory for BL31 is top loaded above BL2. + +- ``void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)`` + + This region is an exact copy of the region defined by + ``bl2_plat_sec_mem_layout()``. Being a disconnected copy means that all the + changes made to this region by the Trusted Firmware will not be propagated. + This approach is valid because the SCP BL2 image is loaded temporarily + while it is being transferred to the SCP, so this memory is reused + afterwards. + +- ``void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)`` + + This region depends on the location of the BL32 image. Currently, ARM + platforms support three different locations (detailed below): Trusted SRAM, + Trusted DRAM and the TZC-Secured DRAM. + +- ``void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)`` + + This region corresponds to the Non-Secure DDR-DRAM, excluding the + TZC-Secured area. + +The location of the BL32 image will result in different memory maps. This is +illustrated for both FVP and Juno in the following diagrams, using the TSP as +an example. + +Note: Loading the BL32 image in TZC secured DRAM doesn't change the memory +layout of the other images in Trusted SRAM. + +**FVP with TSP in Trusted SRAM (default option):** +(These diagrams only cover the AArch64 case) + +:: + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 ------------------ + | BL1 (rw) | <<<<<<<<<<<<< | BL31 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| ------------------ + | BL2 | <<<<<<<<<<<<< | BL32 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 PROGBITS | + 0x04001000 +----------+ ------------------ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**FVP with TSP in Trusted DRAM:** + +:: + + Trusted DRAM + 0x08000000 +----------+ + | BL32 | + 0x06000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 ------------------ + | BL1 (rw) | <<<<<<<<<<<<< | BL31 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| ------------------ + | BL2 | + |----------| + | | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**FVP with TSP in TZC-Secured DRAM:** + +:: + + DRAM + 0xffffffff +----------+ + | BL32 | (secure) + 0xff000000 +----------+ + | | + : : (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 ------------------ + | BL1 (rw) | <<<<<<<<<<<<< | BL31 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| ------------------ + | BL2 | + |----------| + | | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**Juno with BL32 in Trusted SRAM (default option):** + +:: + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 ------------------ + | BL1 (rw) | <<<<<<<<<<<<< | BL31 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| ------------------ + | BL2 | <<<<<<<<<<<<< | BL32 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 PROGBITS | + 0x04001000 +----------+ ------------------ + | MHU | + 0x04000000 +----------+ + +**Juno with BL32 in TZC-secured DRAM:** + +:: + + DRAM + 0xFFE00000 +----------+ + | BL32 | (secure) + 0xFF000000 |----------| + | | + : : (non-secure) + | | + 0x80000000 +----------+ + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 ------------------ + | BL1 (rw) | <<<<<<<<<<<<< | BL31 NOBITS | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| ------------------ + | BL2 | + |----------| + | | + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +Firmware Image Package (FIP) +---------------------------- + +Using a Firmware Image Package (FIP) allows for packing bootloader images (and +potentially other payloads) into a single archive that can be loaded by the ARM +Trusted Firmware from non-volatile platform storage. A driver to load images +from a FIP has been added to the storage layer and allows a package to be read +from supported platform storage. A tool to create Firmware Image Packages is +also provided and described below. + +Firmware Image Package layout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP layout consists of a table of contents (ToC) followed by payload data. +The ToC itself has a header followed by one or more table entries. The ToC is +terminated by an end marker entry. All ToC entries describe some payload data +that has been appended to the end of the binary package. With the information +provided in the ToC entry the corresponding payload data can be retrieved. + +:: + + ------------------ + | ToC Header | + |----------------| + | ToC Entry 0 | + |----------------| + | ToC Entry 1 | + |----------------| + | ToC End Marker | + |----------------| + | | + | Data 0 | + | | + |----------------| + | | + | Data 1 | + | | + ------------------ + +The ToC header and entry formats are described in the header file +``include/tools_share/firmware_image_package.h``. This file is used by both the +tool and the ARM Trusted firmware. + +The ToC header has the following fields: + +:: + + `name`: The name of the ToC. This is currently used to validate the header. + `serial_number`: A non-zero number provided by the creation tool + `flags`: Flags associated with this data. + Bits 0-31: Reserved + Bits 32-47: Platform defined + Bits 48-63: Reserved + +A ToC entry has the following fields: + +:: + + `uuid`: All files are referred to by a pre-defined Universally Unique + IDentifier [UUID] . The UUIDs are defined in + `include/tools_share/firmware_image_package.h`. The platform translates + the requested image name into the corresponding UUID when accessing the + package. + `offset_address`: The offset address at which the corresponding payload data + can be found. The offset is calculated from the ToC base address. + `size`: The size of the corresponding payload data in bytes. + `flags`: Flags associated with this entry. Non are yet defined. + +Firmware Image Package creation tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP creation tool can be used to pack specified images into a binary package +that can be loaded by the ARM Trusted Firmware from platform storage. The tool +currently only supports packing bootloader images. Additional image definitions +can be added to the tool as required. + +The tool can be found in ``tools/fiptool``. + +Loading from a Firmware Image Package (FIP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Firmware Image Package (FIP) driver can load images from a binary package on +non-volatile platform storage. For the ARM development platforms, this is +currently NOR FLASH. + +Bootloader images are loaded according to the platform policy as specified by +the function ``plat_get_image_source()``. For the ARM development platforms, this +means the platform will attempt to load images from a Firmware Image Package +located at the start of NOR FLASH0. + +The ARM development platforms' policy is to only allow loading of a known set of +images. The platform policy can be modified to allow additional images. + +Use of coherent memory in Trusted Firmware +------------------------------------------ + +There might be loss of coherency when physical memory with mismatched +shareability, cacheability and memory attributes is accessed by multiple CPUs +(refer to section B2.9 of `ARM ARM`_ for more details). This possibility occurs +in Trusted Firmware during power up/down sequences when coherency, MMU and +caches are turned on/off incrementally. + +Trusted Firmware defines coherent memory as a region of memory with Device +nGnRE attributes in the translation tables. The translation granule size in +Trusted Firmware is 4KB. This is the smallest possible size of the coherent +memory region. + +By default, all data structures which are susceptible to accesses with +mismatched attributes from various CPUs are allocated in a coherent memory +region (refer to section 2.1 of `Porting Guide`_). The coherent memory region +accesses are Outer Shareable, non-cacheable and they can be accessed +with the Device nGnRE attributes when the MMU is turned on. Hence, at the +expense of at least an extra page of memory, Trusted Firmware is able to work +around coherency issues due to mismatched memory attributes. + +The alternative to the above approach is to allocate the susceptible data +structures in Normal WriteBack WriteAllocate Inner shareable memory. This +approach requires the data structures to be designed so that it is possible to +work around the issue of mismatched memory attributes by performing software +cache maintenance on them. + +Disabling the use of coherent memory in Trusted Firmware +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It might be desirable to avoid the cost of allocating coherent memory on +platforms which are memory constrained. Trusted Firmware enables inclusion of +coherent memory in firmware images through the build flag ``USE_COHERENT_MEM``. +This flag is enabled by default. It can be disabled to choose the second +approach described above. + +The below sections analyze the data structures allocated in the coherent memory +region and the changes required to allocate them in normal memory. + +Coherent memory usage in PSCI implementation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``psci_non_cpu_pd_nodes`` data structure stores the platform's power domain +tree information for state management of power domains. By default, this data +structure is allocated in the coherent memory region in the Trusted Firmware +because it can be accessed by multple CPUs, either with caches enabled or +disabled. + +.. code:: c + + 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. + * TODO: Figure out whether to whether using pointer is more efficient. + */ + unsigned int parent_node; + + plat_local_state_t local_state; + + unsigned char level; + + /* For indexing the psci_lock array*/ + unsigned char lock_index; + } non_cpu_pd_node_t; + +In order to move this data structure to normal memory, the use of each of its +fields must be analyzed. Fields like ``cpu_start_idx``, ``ncpus``, ``parent_node`` +``level`` and ``lock_index`` are only written once during cold boot. Hence removing +them from coherent memory involves only doing a clean and invalidate of the +cache lines after these fields are written. + +The field ``local_state`` can be concurrently accessed by multiple CPUs in +different cache states. A Lamport's Bakery lock ``psci_locks`` is used to ensure +mutual exlusion to this field and a clean and invalidate is needed after it +is written. + +Bakery lock data +~~~~~~~~~~~~~~~~ + +The bakery lock data structure ``bakery_lock_t`` is allocated in coherent memory +and is accessed by multiple CPUs with mismatched attributes. ``bakery_lock_t`` is +defined as follows: + +.. code:: c + + typedef struct bakery_lock { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS]; + } bakery_lock_t; + +It is a characteristic of Lamport's Bakery algorithm that the volatile per-CPU +fields can be read by all CPUs but only written to by the owning CPU. + +Depending upon the data cache line size, the per-CPU fields of the +``bakery_lock_t`` structure for multiple CPUs may exist on a single cache line. +These per-CPU fields can be read and written during lock contention by multiple +CPUs with mismatched memory attributes. Since these fields are a part of the +lock implementation, they do not have access to any other locking primitive to +safeguard against the resulting coherency issues. As a result, simple software +cache maintenance is not enough to allocate them in coherent memory. Consider +the following example. + +CPU0 updates its per-CPU field with data cache enabled. This write updates a +local cache line which contains a copy of the fields for other CPUs as well. Now +CPU1 updates its per-CPU field of the ``bakery_lock_t`` structure with data cache +disabled. CPU1 then issues a DCIVAC operation to invalidate any stale copies of +its field in any other cache line in the system. This operation will invalidate +the update made by CPU0 as well. + +To use bakery locks when ``USE_COHERENT_MEM`` is disabled, the lock data structure +has been redesigned. The changes utilise the characteristic of Lamport's Bakery +algorithm mentioned earlier. The bakery\_lock structure only allocates the memory +for a single CPU. The macro ``DEFINE_BAKERY_LOCK`` allocates all the bakery locks +needed for a CPU into a section ``bakery_lock``. The linker allocates the memory +for other cores by using the total size allocated for the bakery\_lock section +and multiplying it with (PLATFORM\_CORE\_COUNT - 1). This enables software to +perform software cache maintenance on the lock data structure without running +into coherency issues associated with mismatched attributes. + +The bakery lock data structure ``bakery_info_t`` is defined for use when +``USE_COHERENT_MEM`` is disabled as follows: + +.. code:: c + + typedef struct bakery_info { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data; + } bakery_info_t; + +The ``bakery_info_t`` represents a single per-CPU field of one lock and +the combination of corresponding ``bakery_info_t`` structures for all CPUs in the +system represents the complete bakery lock. The view in memory for a system +with n bakery locks are: + +:: + + bakery_lock section start + |----------------| + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU0 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU0 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU0 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | <--- Calculate PERCPU_BAKERY_LOCK_SIZE, allocate + | Granule | continuous memory for remaining CPUs. + ------------------ + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU1 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU1 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU1 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | + | Granule | + ------------------ + +Consider a system of 2 CPUs with 'N' bakery locks as shown above. For an +operation on Lock\_N, the corresponding ``bakery_info_t`` in both CPU0 and CPU1 +``bakery_lock`` section need to be fetched and appropriate cache operations need +to be performed for each access. + +On ARM Platforms, bakery locks are used in psci (``psci_locks``) and power controller +driver (``arm_lock``). + +Non Functional Impact of removing coherent memory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Removal of the coherent memory region leads to the additional software overhead +of performing cache maintenance for the affected data structures. However, since +the memory where the data structures are allocated is cacheable, the overhead is +mostly mitigated by an increase in performance. + +There is however a performance impact for bakery locks, due to: + +- Additional cache maintenance operations, and +- Multiple cache line reads for each lock operation, since the bakery locks + for each CPU are distributed across different cache lines. + +The implementation has been optimized to minimize this additional overhead. +Measurements indicate that when bakery locks are allocated in Normal memory, the +minimum latency of acquiring a lock is on an average 3-4 micro seconds whereas +in Device memory the same is 2 micro seconds. The measurements were done on the +Juno ARM development platform. + +As mentioned earlier, almost a page of memory can be saved by disabling +``USE_COHERENT_MEM``. Each platform needs to consider these trade-offs to decide +whether coherent memory should be used. If a platform disables +``USE_COHERENT_MEM`` and needs to use bakery locks in the porting layer, it can +optionally define macro ``PLAT_PERCPU_BAKERY_LOCK_SIZE`` (see the +`Porting Guide`_). Refer to the reference platform code for examples. + +Isolating code and read-only data on separate memory pages +---------------------------------------------------------- + +In the ARMv8 VMSA, translation table entries include fields that define the +properties of the target memory region, such as its access permissions. The +smallest unit of memory that can be addressed by a translation table entry is +a memory page. Therefore, if software needs to set different permissions on two +memory regions then it needs to map them using different memory pages. + +The default memory layout for each BL image is as follows: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +Note: The 2KB alignment for the exception vectors is an architectural +requirement. + +The read-write data start on a new memory page so that they can be mapped with +read-write permissions, whereas the code and read-only data below are configured +as read-only. + +However, the read-only data are not aligned on a page boundary. They are +contiguous to the code. Therefore, the end of the code section and the beginning +of the read-only data one might share a memory page. This forces both to be +mapped with the same memory attributes. As the code needs to be executable, this +means that the read-only data stored on the same memory page as the code are +executable as well. This could potentially be exploited as part of a security +attack. + +TF provides the build flag ``SEPARATE_CODE_AND_RODATA`` to isolate the code and +read-only data on separate memory pages. This in turn allows independent control +of the access permissions for the code and read-only data. In this case, +platform code gets a finer-grained view of the image layout and can +appropriately map the code region as executable and the read-only data as +execute-never. + +This has an impact on memory footprint, as padding bytes need to be introduced +between the code and read-only data to ensure the segragation of the two. To +limit the memory cost, this flag also changes the memory layout such that the +code and exception vectors are now contiguous, like so: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +With this more condensed memory layout, the separation of read-only data will +add zero or one page to the memory footprint of each BL image. Each platform +should consider the trade-off between memory footprint and security. + +This build flag is disabled by default, minimising memory footprint. On ARM +platforms, it is enabled. + +Performance Measurement Framework +--------------------------------- + +The Performance Measurement Framework (PMF) facilitates collection of +timestamps by registered services and provides interfaces to retrieve +them from within the ARM Trusted Firmware. A platform can choose to +expose appropriate SMCs to retrieve these collected timestamps. + +By default, the global physical counter is used for the timestamp +value and is read via ``CNTPCT_EL0``. The framework allows to retrieve +timestamps captured by other CPUs. + +Timestamp identifier format +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A PMF timestamp is uniquely identified across the system via the +timestamp ID or ``tid``. The ``tid`` is composed as follows: + +:: + + Bits 0-7: The local timestamp identifier. + Bits 8-9: Reserved. + Bits 10-15: The service identifier. + Bits 16-31: Reserved. + +#. The service identifier. Each PMF service is identified by a + service name and a service identifier. Both the service name and + identifier are unique within the system as a whole. + +#. The local timestamp identifier. This identifier is unique within a given + service. + +Registering a PMF service +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To register a PMF service, the ``PMF_REGISTER_SERVICE()`` macro from ``pmf.h`` +is used. The arguments required are the service name, the service ID, +the total number of local timestamps to be captured and a set of flags. + +The ``flags`` field can be specified as a bitwise-OR of the following values: + +:: + + PMF_STORE_ENABLE: The timestamp is stored in memory for later retrieval. + PMF_DUMP_ENABLE: The timestamp is dumped on the serial console. + +The ``PMF_REGISTER_SERVICE()`` reserves memory to store captured +timestamps in a PMF specific linker section at build time. +Additionally, it defines necessary functions to capture and +retrieve a particular timestamp for the given service at runtime. + +The macro ``PMF_REGISTER_SERVICE()`` only enables capturing PMF +timestamps from within ARM Trusted Firmware. In order to retrieve +timestamps from outside of ARM Trusted Firmware, the +``PMF_REGISTER_SERVICE_SMC()`` macro must be used instead. This macro +accepts the same set of arguments as the ``PMF_REGISTER_SERVICE()`` +macro but additionally supports retrieving timestamps using SMCs. + +Capturing a timestamp +~~~~~~~~~~~~~~~~~~~~~ + +PMF timestamps are stored in a per-service timestamp region. On a +system with multiple CPUs, each timestamp is captured and stored +in a per-CPU cache line aligned memory region. + +Having registered the service, the ``PMF_CAPTURE_TIMESTAMP()`` macro can be +used to capture a timestamp at the location where it is used. The macro +takes the service name, a local timestamp identifier and a flag as arguments. + +The ``flags`` field argument can be zero, or ``PMF_CACHE_MAINT`` which +instructs PMF to do cache maintenance following the capture. Cache +maintenance is required if any of the service's timestamps are captured +with data cache disabled. + +To capture a timestamp in assembly code, the caller should use +``pmf_calc_timestamp_addr`` macro (defined in ``pmf_asm_macros.S``) to +calculate the address of where the timestamp would be stored. The +caller should then read ``CNTPCT_EL0`` register to obtain the timestamp +and store it at the determined address for later retrieval. + +Retrieving a timestamp +~~~~~~~~~~~~~~~~~~~~~~ + +From within ARM Trusted Firmware, timestamps for individual CPUs can +be retrieved using either ``PMF_GET_TIMESTAMP_BY_MPIDR()`` or +``PMF_GET_TIMESTAMP_BY_INDEX()`` macros. These macros accept the CPU's MPIDR +value, or its ordinal position, respectively. + +From outside ARM Trusted Firmware, timestamps for individual CPUs can be +retrieved by calling into ``pmf_smc_handler()``. + +.. code:: c + + Interface : pmf_smc_handler() + Argument : unsigned int smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags + Return : uintptr_t + + smc_fid: Holds the SMC identifier which is either `PMF_SMC_GET_TIMESTAMP_32` + when the caller of the SMC is running in AArch32 mode + or `PMF_SMC_GET_TIMESTAMP_64` when the caller is running in AArch64 mode. + x1: Timestamp identifier. + x2: The `mpidr` of the CPU for which the timestamp has to be retrieved. + This can be the `mpidr` of a different core to the one initiating + the SMC. In that case, service specific cache maintenance may be + required to ensure the updated copy of the timestamp is returned. + x3: A flags value that is either 0 or `PMF_CACHE_MAINT`. If + `PMF_CACHE_MAINT` is passed, then the PMF code will perform a + cache invalidate before reading the timestamp. This ensures + an updated copy is returned. + +The remaining arguments, ``x4``, ``cookie``, ``handle`` and ``flags`` are unused +in this implementation. + +PMF code structure +~~~~~~~~~~~~~~~~~~ + +#. ``pmf_main.c`` consists of core functions that implement service registration, + initialization, storing, dumping and retrieving timestamps. + +#. ``pmf_smc.c`` contains the SMC handling for registered PMF services. + +#. ``pmf.h`` contains the public interface to Performance Measurement Framework. + +#. ``pmf_asm_macros.S`` consists of macros to facilitate capturing timestamps in + assembly code. + +#. ``pmf_helpers.h`` is an internal header used by ``pmf.h``. + +#. .. rubric:: ARMv8 Architecture Extensions + :name: armv8-architecture-extensions + +ARM Trusted Firmware makes use of ARMv8 Architecture Extensions where +applicable. This section lists the usage of Architecture Extensions, and build +flags controlling them. + +In general, and unless individually mentioned, the build options +``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` selects the Architecture Extension to +target when building ARM Trusted Firmware. Subsequent ARM Architecture +Extensions are backward compatible with previous versions. + +The build system only requires that ``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` have a +valid numeric value. These build options only control whether or not +Architecture Extension-specific code is included in the build. Otherwise, ARM +Trusted Firmware targets the base ARMv8.0 architecture; i.e. as if +``ARM_ARCH_MAJOR`` == 8 and ``ARM_ARCH_MINOR`` == 0, which are also their respective +default values. + +See also the *Summary of build options* in `User Guide`_. + +For details on the Architecture Extension and available features, please refer +to the respective Architecture Extension Supplement. + +ARMv8.1 +~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` >= 8, or when +``ARM_ARCH_MAJOR`` == 8 and ``ARM_ARCH_MINOR`` >= 1. + +- The Compare and Swap instruction is used to implement spinlocks. Otherwise, + the load-/store-exclusive instruction pair is used. + +Code Structure +-------------- + +Trusted Firmware code is logically divided between the three boot loader +stages mentioned in the previous sections. The code is also divided into the +following categories (present as directories in the source code): + +- **Platform specific.** Choice of architecture specific code depends upon + the platform. +- **Common code.** This is platform and architecture agnostic code. +- **Library code.** This code comprises of functionality commonly used by all + other code. The PSCI implementation and other EL3 runtime frameworks reside + as Library components. +- **Stage specific.** Code specific to a boot stage. +- **Drivers.** +- **Services.** EL3 runtime services (eg: SPD). Specific SPD services + reside in the ``services/spd`` directory (e.g. ``services/spd/tspd``). + +Each boot loader stage uses code from one or more of the above mentioned +categories. Based upon the above, the code layout looks like this: + +:: + + Directory Used by BL1? Used by BL2? Used by BL31? + bl1 Yes No No + bl2 No Yes No + bl31 No No Yes + plat Yes Yes Yes + drivers Yes No Yes + common Yes Yes Yes + lib Yes Yes Yes + services No No Yes + +The build system provides a non configurable build option IMAGE\_BLx for each +boot loader stage (where x = BL stage). e.g. for BL1 , IMAGE\_BL1 will be +defined by the build system. This enables the Trusted Firmware to compile +certain code only for specific boot loader stages + +All assembler files have the ``.S`` extension. The linker source files for each +boot stage have the extension ``.ld.S``. These are processed by GCC to create the +linker scripts which have the extension ``.ld``. + +FDTs provide a description of the hardware platform and are used by the Linux +kernel at boot time. These can be found in the ``fdts`` directory. + +References +---------- + +#. Trusted Board Boot Requirements CLIENT PDD (ARM DEN 0006B-5). Available + under NDA through your ARM account representative. + +#. `Power State Coordination Interface PDD`_ + +#. `SMC Calling Convention PDD`_ + +#. `ARM Trusted Firmware Interrupt Management Design guide`_. + +-------------- + +*Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.* + +.. _Reset Design: ./reset-design.rst +.. _Porting Guide: ./porting-guide.rst +.. _Firmware Update: ./firmware-update.rst +.. _PSCI PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _SMC calling convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _PSCI Library integration guide: ./psci-lib-integration-guide.rst +.. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _here: ./psci-lib-integration-guide.rst +.. _cpu-specific-build-macros.rst: ./cpu-specific-build-macros.rst +.. _CPUBM: ./cpu-specific-build-macros.rst +.. _ARM ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html +.. _User Guide: ./user-guide.rst +.. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _ARM Trusted Firmware Interrupt Management Design guide: ./interrupt-framework-design.rst + +.. |Image 1| image:: diagrams/rt-svc-descs-layout.png?raw=true diff --git a/docs/firmware-update.rst b/docs/firmware-update.rst new file mode 100644 index 0000000..829341d --- /dev/null +++ b/docs/firmware-update.rst @@ -0,0 +1,412 @@ +ARM Trusted Firmware - Firmware Update Design Guide +=================================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +-------------- + +Introduction +------------ + +This document describes the design of the Firmware Update (FWU) feature, which +enables authenticated firmware to update firmware images from external +interfaces such as USB, UART, SD-eMMC, NAND, NOR or Ethernet to SoC Non-Volatile +memories such as NAND Flash, LPPDR2-NVM or any memory determined by the +platform. This feature functions even when the current firmware in the system +is corrupt or missing; it therefore may be used as a recovery mode. It may also +be complemented by other, higher level firmware update software. + +FWU implements a specific part of the Trusted Board Boot Requirements (TBBR) +specification, ARM DEN0006C-1. It should be used in conjunction with the +`Trusted Board Boot`_ design document, which describes the image authentication +parts of the Trusted Firmware (TF) TBBR implementation. + +Scope +~~~~~ + +This document describes the secure world FWU design. It is beyond its scope to +describe how normal world FWU images should operate. To implement normal world +FWU images, please refer to the "Non-Trusted Firmware Updater" requirements in +the TBBR. + +FWU Overview +------------ + +The FWU boot flow is primarily mediated by BL1. Since BL1 executes in ROM, and +it is usually desirable to minimize the amount of ROM code, the design allows +some parts of FWU to be implemented in other secure and normal world images. +Platform code may choose which parts are implemented in which images but the +general expectation is: + +- BL1 handles: + + - Detection and initiation of the FWU boot flow. + - Copying images from non-secure to secure memory + - FWU image authentication + - Context switching between the normal and secure world during the FWU + process. + +- Other secure world FWU images handle platform initialization required by + the FWU process. +- Normal world FWU images handle loading of firmware images from external + interfaces to non-secure memory. + +The primary requirements of the FWU feature are: + +#. Export a BL1 SMC interface to interoperate with other FWU images executing + at other Exception Levels. +#. Export a platform interface to provide FWU common code with the information + it needs, and to enable platform specific FWU functionality. See the + `Porting Guide`_ for details of this interface. + +TF uses abbreviated image terminology for FWU images like for other TF images. +An overview of this terminology can be found `here`_. + +The following diagram shows the FWU boot flow for ARM development platforms. +ARM CSS platforms like Juno have a System Control Processor (SCP), and these +use all defined FWU images. Other platforms may use a subset of these. + +|Flow Diagram| + +Image Identification +-------------------- + +Each FWU image and certificate is identified by a unique ID, defined by the +platform, which BL1 uses to fetch an image descriptor (``image_desc_t``) via a +call to ``bl1_plat_get_image_desc()``. The same ID is also used to prepare the +Chain of Trust (Refer to the `Authentication Framework Design`_ +for more information). + +The image descriptor includes the following information: + +- Executable or non-executable image. This indicates whether the normal world + is permitted to request execution of a secure world FWU image (after + authentication). Secure world certificates and non-AP images are examples + of non-executable images. +- Secure or non-secure image. This indicates whether the image is + authenticated/executed in secure or non-secure memory. +- Image base address and size. +- Image entry point configuration (an ``entry_point_info_t``). +- FWU image state. + +BL1 uses the FWU image descriptors to: + +- Validate the arguments of FWU SMCs +- Manage the state of the FWU process +- Initialize the execution state of the next FWU image. + +FWU State Machine +----------------- + +BL1 maintains state for each FWU image during FWU execution. FWU images at lower +Exception Levels raise SMCs to invoke FWU functionality in BL1, which causes +BL1 to update its FWU image state. The BL1 image states and valid state +transitions are shown in the diagram below. Note that secure images have a more +complex state machine than non-secure images. + +|FWU state machine| + +The following is a brief description of the supported states: + +- RESET: This is the initial state of every image at the start of FWU. + Authentication failure also leads to this state. A secure + image may yield to this state if it has completed execution. + It can also be reached by using ``FWU_SMC_IMAGE_RESET``. + +- COPYING: This is the state of a secure image while BL1 is copying it + in blocks from non-secure to secure memory. + +- COPIED: This is the state of a secure image when BL1 has completed + copying it to secure memory. + +- AUTHENTICATED: This is the state of an image when BL1 has successfully + authenticated it. + +- EXECUTED: This is the state of a secure, executable image when BL1 has + passed execution control to it. + +- INTERRUPTED: This is the state of a secure, executable image after it has + requested BL1 to resume normal world execution. + +BL1 SMC Interface +----------------- + +BL1\_SMC\_CALL\_COUNT +~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x0 + + Return: + uint32_t + +This SMC returns the number of SMCs supported by BL1. + +BL1\_SMC\_UID +~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x1 + + Return: + UUID : 32 bits in each of w0-w3 (or r0-r3 for AArch32 callers) + +This SMC returns the 128-bit `Universally Unique Identifier`_ for the +BL1 SMC service. + +BL1\_SMC\_VERSION +~~~~~~~~~~~~~~~~~ + +:: + + Argument: + uint32_t function ID : 0x3 + + Return: + uint32_t : Bits [31:16] Major Version + Bits [15:0] Minor Version + +This SMC returns the current version of the BL1 SMC service. + +BL1\_SMC\_RUN\_IMAGE +~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x4 + entry_point_info_t *ep_info + + Return: + void + + Pre-conditions: + if (normal world caller) synchronous exception + if (ep_info not EL3) synchronous exception + +This SMC passes execution control to an EL3 image described by the provided +``entry_point_info_t`` structure. In the normal TF boot flow, BL2 invokes this SMC +for BL1 to pass execution control to BL31. + +FWU\_SMC\_IMAGE\_COPY +~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x10 + unsigned int image_id + uintptr_t image_addr + unsigned int block_size + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id state is not (RESET or COPYING)) return -EPERM + if (secure world caller) return -EPERM + if (image_addr + block_size overflows) return -ENOMEM + if (image destination address + image_size overflows) return -ENOMEM + if (source block is in secure memory) return -ENOMEM + if (source block is not mapped into BL1) return -ENOMEM + if (image_size > free secure memory) return -ENOMEM + if (image overlaps another image) return -EPERM + +This SMC copies the secure image indicated by ``image_id`` from non-secure memory +to secure memory for later authentication. The image may be copied in a single +block or multiple blocks. In either case, the total size of the image must be +provided in ``image_size`` when invoking this SMC for the first time for each +image; it is ignored in subsequent calls (if any) for the same image. + +The ``image_addr`` and ``block_size`` specify the source memory block to copy from. +The destination address is provided by the platform code. + +If ``block_size`` is greater than the amount of remaining bytes to copy for this +image then the former is truncated to the latter. The copy operation is then +considered as complete and the FWU state machine transitions to the "COPIED" +state. If there is still more to copy, the FWU state machine stays in or +transitions to the COPYING state (depending on the previous state). + +When using multiple blocks, the source blocks do not necessarily need to be in +contiguous memory. + +Once the SMC is handled, BL1 returns from exception to the normal world caller. + +FWU\_SMC\_IMAGE\_AUTH +~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x11 + unsigned int image_id + uintptr_t image_addr + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + : -EAUTH + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is not mappped into BL1) return -ENOMEM + else // normal world caller + if (image_id is secure image) + if (image_id state is not COPIED) return -EPERM + else // image_id is non-secure image + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is in secure memory) return -ENOMEM + if (image_addr/image_size not mappped into BL1) return -ENOMEM + +This SMC authenticates the image specified by ``image_id``. If the image is in the +RESET state, BL1 authenticates the image in place using the provided +``image_addr`` and ``image_size``. If the image is a secure image in the COPIED +state, BL1 authenticates the image from the secure memory that BL1 previously +copied the image into. + +BL1 returns from exception to the caller. If authentication succeeds then BL1 +sets the image state to AUTHENTICATED. If authentication fails then BL1 returns +the -EAUTH error and sets the image state back to RESET. + +FWU\_SMC\_IMAGE\_EXECUTE +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x12 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id is non-executable image) return -EPERM + if (image_id state is not AUTHENTICATED) return -EPERM + +This SMC initiates execution of a previously authenticated image specified by +``image_id``, in the other security world to the caller. The current +implementation only supports normal world callers initiating execution of a +secure world image. + +BL1 saves the normal world caller's context, sets the secure image state to +EXECUTED, and returns from exception to the secure image. + +FWU\_SMC\_IMAGE\_RESUME +~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x13 + register_t image_param + + Return: + register_t : image_param (Success) + : -EPERM + + Pre-conditions: + if (normal world caller and no INTERRUPTED secure image) return -EPERM + +This SMC resumes execution in the other security world while there is a secure +image in the EXECUTED/INTERRUPTED state. + +For normal world callers, BL1 sets the previously interrupted secure image state +to EXECUTED. For secure world callers, BL1 sets the previously executing secure +image state to INTERRUPTED. In either case, BL1 saves the calling world's +context, restores the resuming world's context and returns from exception into +the resuming world. If the call is successful then the caller provided +``image_param`` is returned to the resumed world, otherwise an error code is +returned to the caller. + +FWU\_SMC\_SEC\_IMAGE\_DONE +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x14 + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (normal world caller) return -EPERM + +This SMC indicates completion of a previously executing secure image. + +BL1 sets the previously executing secure image state to the RESET state, +restores the normal world context and returns from exception into the normal +world. + +FWU\_SMC\_UPDATE\_DONE +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x15 + register_t client_cookie + + Return: + N/A + +This SMC completes the firmware update process. BL1 calls the platform specific +function ``bl1_plat_fwu_done``, passing the optional argument ``client_cookie`` as +a ``void *``. The SMC does not return. + +FWU\_SMC\_IMAGE\_RESET +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x16 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (secure world caller) return -EPERM + if (image in EXECUTED) return -EPERM + +This SMC sets the state of an image to RESET and zeroes the memory used by it. + +This is only allowed if the image is not being executed. + +-------------- + +*Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.* + +.. _Trusted Board Boot: ./trusted-board-boot.rst +.. _Porting Guide: ./porting-guide.rst +.. _here: https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Image-Terminology +.. _Authentication Framework Design: ./auth-framework.rst +.. _Universally Unique Identifier: https://tools.ietf.org/rfc/rfc4122.txt + +.. |Flow Diagram| image:: diagrams/fwu_flow.png?raw=true +.. |FWU state machine| image:: diagrams/fwu_states.png?raw=true diff --git a/docs/interrupt-framework-design.rst b/docs/interrupt-framework-design.rst new file mode 100644 index 0000000..940bc24 --- /dev/null +++ b/docs/interrupt-framework-design.rst @@ -0,0 +1,1003 @@ +ARM Trusted Firmware Interrupt Management Design guide +====================================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +This framework is responsible for managing interrupts routed to EL3. It also +allows EL3 software to configure the interrupt routing behavior. Its main +objective is to implement the following two requirements. + +#. It should be possible to route interrupts meant to be handled by secure + software (Secure interrupts) to EL3, when execution is in non-secure state + (normal world). The framework should then take care of handing control of + the interrupt to either software in EL3 or Secure-EL1 depending upon the + software configuration and the GIC implementation. This requirement ensures + that secure interrupts are under the control of the secure software with + respect to their delivery and handling without the possibility of + intervention from non-secure software. + +#. It should be possible to route interrupts meant to be handled by + non-secure software (Non-secure interrupts) to the last executed exception + level in the normal world when the execution is in secure world at + exception levels lower than EL3. This could be done with or without the + knowledge of software executing in Secure-EL1/Secure-EL0. The choice of + approach should be governed by the secure software. This requirement + ensures that non-secure software is able to execute in tandem with the + secure software without overriding it. + +Concepts +-------- + +Interrupt types +~~~~~~~~~~~~~~~ + +The framework categorises an interrupt to be one of the following depending upon +the exception level(s) it is handled in. + +#. Secure EL1 interrupt. This type of interrupt can be routed to EL3 or + Secure-EL1 depending upon the security state of the current execution + context. It is always handled in Secure-EL1. + +#. Non-secure interrupt. This type of interrupt can be routed to EL3, + Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the + current execution context. It is always handled in either Non-secure EL1 + or EL2. + +#. EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1 + depending upon the security state of the current execution context. It is + always handled in EL3. + +The following constants define the various interrupt types in the framework +implementation. + +:: + + #define INTR_TYPE_S_EL1 0 + #define INTR_TYPE_EL3 1 + #define INTR_TYPE_NS 2 + +Routing model +~~~~~~~~~~~~~ + +A type of interrupt can be either generated as an FIQ or an IRQ. The target +exception level of an interrupt type is configured through the FIQ and IRQ bits +in the Secure Configuration Register at EL3 (``SCR_EL3.FIQ`` and ``SCR_EL3.IRQ`` +bits). When ``SCR_EL3.FIQ``\ =1, FIQs are routed to EL3. Otherwise they are routed +to the First Exception Level (FEL) capable of handling interrupts. When +``SCR_EL3.IRQ``\ =1, IRQs are routed to EL3. Otherwise they are routed to the +FEL. This register is configured independently by EL3 software for each security +state prior to entry into a lower exception level in that security state. + +A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as +its target exception level for each security state. It is represented by a +single bit for each security state. A value of ``0`` means that the interrupt +should be routed to the FEL. A value of ``1`` means that the interrupt should be +routed to EL3. A routing model is applicable only when execution is not in EL3. + +The default routing model for an interrupt type is to route it to the FEL in +either security state. + +Valid routing models +~~~~~~~~~~~~~~~~~~~~ + +The framework considers certain routing models for each type of interrupt to be +incorrect as they conflict with the requirements mentioned in Section 1. The +following sub-sections describe all the possible routing models and specify +which ones are valid or invalid. EL3 interrupts are currently supported only +for GIC version 3.0 (ARM GICv3) and only the Secure-EL1 and Non-secure interrupt +types are supported for GIC version 2.0 (ARM GICv2) (See 1.2). The terminology +used in the following sub-sections is explained below. + +#. **CSS**. Current Security State. ``0`` when secure and ``1`` when non-secure + +#. **TEL3**. Target Exception Level 3. ``0`` when targeted to the FEL. ``1`` when + targeted to EL3. + +Secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This is a valid routing model as secure software is in + control of handling secure interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can + handover the interrupt to Secure-EL1 for handling. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the ARM Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handover the interrupt to Secure-EL1 for handling. + +Non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This allows the secure software to trap non-secure + interrupts, perform its book-keeping and hand the interrupt to the + non-secure software through EL3. This is a valid routing model as secure + software is in control of how its execution is preempted by non-secure + interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can save + the state of software in Secure-EL1/Secure-EL0 before handing the + interrupt to non-secure software. This model requires additional + coordination between Secure-EL1 and EL3 software to ensure that the + former's state is correctly saved by the latter. + +#. **CSS=1, TEL3=0**. Interrupt is routed to FEL when execution is in + non-secure state. This is an valid routing model as a non-secure interrupt + is handled by non-secure software. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is an invalid routing model as there is no valid + reason to route the interrupt to EL3 software and then hand it back to + non-secure software for handling. + +EL3 interrupts +^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in Secure-EL1/Secure-EL0 is in control of how its execution is preempted + by EL3 interrupt and can handover the interrupt to EL3 for handling. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in EL3 can handle the interrupt. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the ARM Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handle the interrupt. + +Mapping of interrupt type to signal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The framework is meant to work with any interrupt controller implemented by a +platform. A interrupt controller could generate a type of interrupt as either an +FIQ or IRQ signal to the CPU depending upon the current security state. The +mapping between the type and signal is known only to the platform. The framework +uses this information to determine whether the IRQ or the FIQ bit should be +programmed in ``SCR_EL3`` while applying the routing model for a type of +interrupt. The platform provides this information through the +``plat_interrupt_type_to_line()`` API (described in the +`Porting Guide`_). For example, on the FVP port when the platform uses an ARM GICv2 +interrupt controller, Secure-EL1 interrupts are signaled through the FIQ signal +while Non-secure interrupts are signaled through the IRQ signal. This applies +when execution is in either security state. + +Effect of mapping of several interrupt types to one signal +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It should be noted that if more than one interrupt type maps to a single +interrupt signal, and if any one of the interrupt type sets **TEL3=1** for a +particular security state, then interrupt signal will be routed to EL3 when in +that security state. This means that all the other interrupt types using the +same interrupt signal will be forced to the same routing model. This should be +borne in mind when choosing the routing model for an interrupt type. + +For example, in ARM GICv3, when the execution context is Secure-EL1/ +Secure-EL0, both the EL3 and the non secure interrupt types map to the FIQ +signal. So if either one of the interrupt type sets the routing model so +that **TEL3=1** when **CSS=0**, the FIQ bit in ``SCR_EL3`` will be programmed to +route the FIQ signal to EL3 when executing in Secure-EL1/Secure-EL0, thereby +effectively routing the other interrupt type also to EL3. + +Assumptions in Interrupt Management Framework +--------------------------------------------- + +The framework makes the following assumptions to simplify its implementation. + +#. Although the framework has support for 2 types of secure interrupts (EL3 + and Secure-EL1 interrupt), only interrupt controller architectures + like ARM GICv3 has architectural support for EL3 interrupts in the form of + Group 0 interrupts. In ARM GICv2, all secure interrupts are assumed to be + handled in Secure-EL1. They can be delivered to Secure-EL1 via EL3 but they + cannot be handled in EL3. + +#. Interrupt exceptions (``PSTATE.I`` and ``F`` bits) are masked during execution + in EL3. + +#. .. rubric:: Interrupt management + :name: interrupt-management + + The following sections describe how interrupts are managed by the interrupt + handling framework. This entails: + +#. Providing an interface to allow registration of a handler and specification + of the routing model for a type of interrupt. + +#. Implementing support to hand control of an interrupt type to its registered + handler when the interrupt is generated. + +Both aspects of interrupt management involve various components in the secure +software stack spanning from EL3 to Secure-EL1. These components are described +in the section 2.1. The framework stores information associated with each type +of interrupt in the following data structure. + +.. code:: c + + typedef struct intr_type_desc { + interrupt_type_handler_t handler; + uint32_t flags; + uint32_t scr_el3[2]; + } intr_type_desc_t; + +The ``flags`` field stores the routing model for the interrupt type in +bits[1:0]. Bit[0] stores the routing model when execution is in the secure +state. Bit[1] stores the routing model when execution is in the non-secure +state. As mentioned in Section 1.2.2, a value of ``0`` implies that the interrupt +should be targeted to the FEL. A value of ``1`` implies that it should be targeted +to EL3. The remaining bits are reserved and SBZ. The helper macro +``set_interrupt_rm_flag()`` should be used to set the bits in the ``flags`` +parameter. + +The ``scr_el3[2]`` field also stores the routing model but as a mapping of the +model in the ``flags`` field to the corresponding bit in the ``SCR_EL3`` for each +security state. + +The framework also depends upon the platform port to configure the interrupt +controller to distinguish between secure and non-secure interrupts. The platform +is expected to be aware of the secure devices present in the system and their +associated interrupt numbers. It should configure the interrupt controller to +enable the secure interrupts, ensure that their priority is always higher than +the non-secure interrupts and target them to the primary CPU. It should also +export the interface described in the `Porting Guide`_ to enable +handling of interrupts. + +In the remainder of this document, for the sake of simplicity a ARM GICv2 system +is considered and it is assumed that the FIQ signal is used to generate Secure-EL1 +interrupts and the IRQ signal is used to generate non-secure interrupts in either +security state. EL3 interrupts are not considered. + +Software components +------------------- + +Roles and responsibilities for interrupt management are sub-divided between the +following components of software running in EL3 and Secure-EL1. Each component is +briefly described below. + +#. EL3 Runtime Firmware. This component is common to all ports of the ARM + Trusted Firmware. + +#. Secure Payload Dispatcher (SPD) service. This service interfaces with the + Secure Payload (SP) software which runs in Secure-EL1/Secure-EL0 and is + responsible for switching execution between secure and non-secure states. + A switch is triggered by a Secure Monitor Call and it uses the APIs + exported by the Context management library to implement this functionality. + Switching execution between the two security states is a requirement for + interrupt management as well. This results in a significant dependency on + the SPD service. ARM Trusted firmware implements an example Test Secure + Payload Dispatcher (TSPD) service. + + An SPD service plugs into the EL3 runtime firmware and could be common to + some ports of the ARM Trusted Firmware. + +#. Secure Payload (SP). On a production system, the Secure Payload corresponds + to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the + SPD service to manage communication with non-secure software. ARM Trusted + Firmware implements an example secure payload called Test Secure Payload + (TSP) which runs only in Secure-EL1. + + A Secure payload implementation could be common to some ports of the ARM + Trusted Firmware just like the SPD service. + +Interrupt registration +---------------------- + +This section describes in detail the role of each software component (see 2.1) +during the registration of a handler for an interrupt type. + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +This component declares the following prototype for a handler of an interrupt type. + +.. code:: c + + typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + +The ``id`` is parameter is reserved and could be used in the future for passing +the interrupt id of the highest pending interrupt only if there is a foolproof +way of determining the id. Currently it contains ``INTR_ID_UNAVAILABLE``. + +The ``flags`` parameter contains miscellaneous information as follows. + +#. Security state, bit[0]. This bit indicates the security state of the lower + exception level when the interrupt was generated. A value of ``1`` means + that it was in the non-secure state. A value of ``0`` indicates that it was + in the secure state. This bit can be used by the handler to ensure that + interrupt was generated and routed as per the routing model specified + during registration. + +#. Reserved, bits[31:1]. The remaining bits are reserved for future use. + +The ``handle`` parameter points to the ``cpu_context`` structure of the current CPU +for the security state specified in the ``flags`` parameter. + +Once the handler routine completes, execution will return to either the secure +or non-secure state. The handler routine must return a pointer to +``cpu_context`` structure of the current CPU for the target security state. On +AArch64, this return value is currently ignored by the caller as the +appropriate ``cpu_context`` to be used is expected to be set by the handler +via the context management library APIs. +A portable interrupt handler implementation must set the target context both in +the structure pointed to by the returned pointer and via the context management +library APIs. The handler should treat all error conditions as critical errors +and take appropriate action within its implementation e.g. use assertion +failures. + +The runtime firmware provides the following API for registering a handler for a +particular type of interrupt. A Secure Payload Dispatcher service should use +this API to register a handler for Secure-EL1 and optionally for non-secure +interrupts. This API also requires the caller to specify the routing model for +the type of interrupt. + +.. code:: c + + int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler handler, + uint64_t flags); + +The ``type`` parameter can be one of the three interrupt types listed above i.e. +``INTR_TYPE_S_EL1``, ``INTR_TYPE_NS`` & ``INTR_TYPE_EL3``. The ``flags`` parameter +is as described in Section 2. + +The function will return ``0`` upon a successful registration. It will return +``-EALREADY`` in case a handler for the interrupt type has already been +registered. If the ``type`` is unrecognised or the ``flags`` or the ``handler`` are +invalid it will return ``-EINVAL``. + +Interrupt routing is governed by the configuration of the ``SCR_EL3.FIQ/IRQ`` bits +prior to entry into a lower exception level in either security state. The +context management library maintains a copy of the ``SCR_EL3`` system register for +each security state in the ``cpu_context`` structure of each CPU. It exports the +following APIs to let EL3 Runtime Firmware program and retrieve the routing +model for each security state for the current CPU. The value of ``SCR_EL3`` stored +in the ``cpu_context`` is used by the ``el3_exit()`` function to program the +``SCR_EL3`` register prior to returning from the EL3 exception level. + +.. code:: c + + uint32_t cm_get_scr_el3(uint32_t security_state); + void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); + +``cm_get_scr_el3()`` returns the value of the ``SCR_EL3`` register for the specified +security state of the current CPU. ``cm_write_scr_el3()`` writes a ``0`` or ``1`` to +the bit specified by ``bit_pos``. ``register_interrupt_type_handler()`` invokes +``set_routing_model()`` API which programs the ``SCR_EL3`` according to the routing +model using the ``cm_get_scr_el3()`` and ``cm_write_scr_el3_bit()`` APIs. + +It is worth noting that in the current implementation of the framework, the EL3 +runtime firmware is responsible for programming the routing model. The SPD is +responsible for ensuring that the routing model has been adhered to upon +receiving an interrupt. + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A SPD service is responsible for determining and maintaining the interrupt +routing model supported by itself and the Secure Payload. It is also responsible +for ferrying interrupts between secure and non-secure software depending upon +the routing model. It could determine the routing model at build time or at +runtime. It must use this information to register a handler for each interrupt +type using the ``register_interrupt_type_handler()`` API in EL3 runtime firmware. + +If the routing model is not known to the SPD service at build time, then it must +be provided by the SP as the result of its initialisation. The SPD should +program the routing model only after SP initialisation has completed e.g. in the +SPD initialisation function pointed to by the ``bl32_init`` variable. + +The SPD should determine the mechanism to pass control to the Secure Payload +after receiving an interrupt from the EL3 runtime firmware. This information +could either be provided to the SPD service at build time or by the SP at +runtime. + +Test secure payload dispatcher behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The TSPD only handles Secure-EL1 interrupts and is provided with the following +routing model at build time. + +- Secure-EL1 interrupts are routed to EL3 when execution is in non-secure + state and are routed to the FEL when execution is in the secure state + i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=1** for Secure-EL1 interrupts + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is zero, the default routing + model is used for non-secure interrupts. They are routed to the FEL in + either security state i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=0** for + Non-secure interrupts. + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, then the + non secure interrupts are routed to EL3 when execution is in secure state + i.e **CSS=0, TEL3=1** for non-secure interrupts. This effectively preempts + Secure-EL1. The default routing model is used for non secure interrupts in + non-secure state. i.e **CSS=1, TEL3=0**. + +It performs the following actions in the ``tspd_init()`` function to fulfill the +requirements mentioned earlier. + +#. It passes control to the Test Secure Payload to perform its + initialisation. The TSP provides the address of the vector table + ``tsp_vectors`` in the SP which also includes the handler for Secure-EL1 + interrupts in the ``sel1_intr_entry`` field. The TSPD passes control to the TSP at + this address when it receives a Secure-EL1 interrupt. + + The handover agreement between the TSP and the TSPD requires that the TSPD + masks all interrupts (``PSTATE.DAIF`` bits) when it calls + ``tsp_sel1_intr_entry()``. The TSP has to preserve the callee saved general + purpose, SP\_EL1/Secure-EL0, LR, VFP and system registers. It can use + ``x0-x18`` to enable its C runtime. + +#. The TSPD implements a handler function for Secure-EL1 interrupts. This + function is registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_secure_el1_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tspd_secure_el1_interrupt_handler, + flags); + if (rc) + panic(); + +#. When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, the TSPD + implements a handler function for non-secure interrupts. This function is + registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_ns_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_NS, + tspd_ns_interrupt_handler, + flags); + if (rc) + panic(); + +Secure payload +~~~~~~~~~~~~~~ + +A Secure Payload must implement an interrupt handling framework at Secure-EL1 +(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload +execution will alternate between the below cases. + +#. In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt + type is targeted to the FEL, then it will be routed to the Secure-EL1 + exception vector table. This is defined as the **asynchronous mode** of + handling interrupts. This mode applies to both Secure-EL1 and non-secure + interrupts. + +#. In the code where both interrupts are disabled, if an interrupt type is + targeted to the FEL, then execution will eventually migrate to the + non-secure state. Any non-secure interrupts will be handled as described + in the routing model where **CSS=1 and TEL3=0**. Secure-EL1 interrupts + will be routed to EL3 (as per the routing model where **CSS=1 and + TEL3=1**) where the SPD service will hand them to the SP. This is defined + as the **synchronous mode** of handling interrupts. + +The interrupt handling framework implemented by the SP should support one or +both these interrupt handling models depending upon the chosen routing model. + +The following list briefly describes how the choice of a valid routing model +(See 1.2.3) effects the implementation of the Secure-EL1 IHF. If the choice of +the interrupt routing model is not known to the SPD service at compile time, +then the SP should pass this information to the SPD service at runtime during +its initialisation phase. + +As mentioned earlier, a ARM GICv2 system is considered and it is assumed that +the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal +is used to generate non-secure interrupts in either security state. + +Secure payload IHF design w.r.t secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.F=0``, Secure-EL1 interrupts will be + triggered at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1 + IHF should implement support for handling FIQ interrupts asynchronously. + + If ``PSTATE.F=1`` then Secure-EL1 interrupts will be handled as per the + synchronous interrupt handling model. The SP could implement this scenario + by exporting a separate entrypoint for Secure-EL1 interrupts to the SPD + service during the registration phase. The SPD service would also need to + know the state of the system, general purpose and the ``PSTATE`` registers + in which it should arrange to return execution to the SP. The SP should + provide this information in an implementation defined way during the + registration phase if it is not known to the SPD service at build time. + +#. **CSS=1, TEL3=1**. Interrupts are routed to EL3 when execution is in + non-secure state. They should be handled through the synchronous interrupt + handling model as described in 1. above. + +#. **CSS=0, TEL3=1**. Secure-EL1 interrupts are routed to EL3 when execution + is in secure state. They will not be visible to the SP. The ``PSTATE.F`` bit + in Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will + call the handler registered by the SPD service for Secure-EL1 interrupts. + Secure-EL1 IHF should then handle all Secure-EL1 interrupt through the + synchronous interrupt handling model described in 1. above. + +Secure payload IHF design w.r.t non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.I=0``, non-secure interrupts will be + triggered at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1 + IHF should co-ordinate with the SPD service to transfer execution to the + non-secure state where the interrupt should be handled e.g the SP could + allocate a function identifier to issue a SMC64 or SMC32 to the SPD + service which indicates that the SP execution has been preempted by a + non-secure interrupt. If this function identifier is not known to the SPD + service at compile time then the SP could provide it during the + registration phase. + + If ``PSTATE.I=1`` then the non-secure interrupt will pend until execution + resumes in the non-secure state. + +#. **CSS=0, TEL3=1**. Non-secure interrupts are routed to EL3. They will not + be visible to the SP. The ``PSTATE.I`` bit in Secure-EL1/Secure-EL0 will + have not effect. The SPD service should register a non-secure interrupt + handler which should save the SP state correctly and resume execution in + the non-secure state where the interrupt will be handled. The Secure-EL1 + IHF does not need to take any action. + +#. **CSS=1, TEL3=0**. Non-secure interrupts are handled in the FEL in + non-secure state (EL1/EL2) and are not visible to the SP. This routing + model does not affect the SP behavior. + +A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly +configured at the interrupt controller by the platform port of the EL3 runtime +firmware. It should configure any additional Secure-EL1 interrupts which the EL3 +runtime firmware is not aware of through its platform port. + +Test secure payload behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is +described in Section 2.2.2. It is known to the TSPD service at build time. + +The TSP implements an entrypoint (``tsp_sel1_intr_entry()``) for handling Secure-EL1 +interrupts taken in non-secure state and routed through the TSPD service +(synchronous handling model). It passes the reference to this entrypoint via +``tsp_vectors`` to the TSPD service. + +The TSP also replaces the default exception vector table referenced through the +``early_exceptions`` variable, with a vector table capable of handling FIQ and IRQ +exceptions taken at the same (Secure-EL1) exception level. This table is +referenced through the ``tsp_exceptions`` variable and programmed into the +VBAR\_EL1. It caters for the asynchronous handling model. + +The TSP also programs the Secure Physical Timer in the ARM Generic Timer block +to raise a periodic interrupt (every half a second) for the purpose of testing +interrupt management across all the software components listed in 2.1 + +Interrupt handling +------------------ + +This section describes in detail the role of each software component (see +Section 2.1) in handling an interrupt of a particular type. + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced +by the ``runtime_exceptions`` variable as follows. + +#. IRQ and FIQ exceptions taken from the current exception level with + ``SP_EL0`` or ``SP_EL3`` are reported as irrecoverable error conditions. As + mentioned earlier, EL3 runtime firmware always executes with the + ``PSTATE.I`` and ``PSTATE.F`` bits set. + +#. The following text describes how the IRQ and FIQ exceptions taken from a + lower exception level using AArch64 or AArch32 are handled. + +When an interrupt is generated, the vector for each interrupt type is +responsible for: + +#. Saving the entire general purpose register context (x0-x30) immediately + upon exception entry. The registers are saved in the per-cpu ``cpu_context`` + data structure referenced by the ``SP_EL3``\ register. + +#. Saving the ``ELR_EL3``, ``SP_EL0`` and ``SPSR_EL3`` system registers in the + per-cpu ``cpu_context`` data structure referenced by the ``SP_EL3`` register. + +#. Switching to the C runtime stack by restoring the ``CTX_RUNTIME_SP`` value + from the per-cpu ``cpu_context`` data structure in ``SP_EL0`` and + executing the ``msr spsel, #0`` instruction. + +#. Determining the type of interrupt. Secure-EL1 interrupts will be signaled + at the FIQ vector. Non-secure interrupts will be signaled at the IRQ + vector. The platform should implement the following API to determine the + type of the pending interrupt. + + .. code:: c + + uint32_t plat_ic_get_interrupt_type(void); + + It should return either ``INTR_TYPE_S_EL1`` or ``INTR_TYPE_NS``. + +#. Determining the handler for the type of interrupt that has been generated. + The following API has been added for this purpose. + + .. code:: c + + interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type); + + It returns the reference to the registered handler for this interrupt + type. The ``handler`` is retrieved from the ``intr_type_desc_t`` structure as + described in Section 2. ``NULL`` is returned if no handler has been + registered for this type of interrupt. This scenario is reported as an + irrecoverable error condition. + +#. Calling the registered handler function for the interrupt type generated. + The ``id`` parameter is set to ``INTR_ID_UNAVAILABLE`` currently. The id along + with the current security state and a reference to the ``cpu_context_t`` + structure for the current security state are passed to the handler function + as its arguments. + + The handler function returns a reference to the per-cpu ``cpu_context_t`` + structure for the target security state. + +#. Calling ``el3_exit()`` to return from EL3 into a lower exception level in + the security state determined by the handler routine. The ``el3_exit()`` + function is responsible for restoring the register context from the + ``cpu_context_t`` data structure for the target security state. + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupt entry +^^^^^^^^^^^^^^^ + +The SPD service begins handling an interrupt when the EL3 runtime firmware calls +the handler function for that type of interrupt. The SPD service is responsible +for the following: + +#. Validating the interrupt. This involves ensuring that the interrupt was + generating according to the interrupt routing model specified by the SPD + service during registration. It should use the security state of the + exception level (passed in the ``flags`` parameter of the handler) where + the interrupt was taken from to determine this. If the interrupt is not + recognised then the handler should treat it as an irrecoverable error + condition. + + A SPD service can register a handler for Secure-EL1 and/or Non-secure + interrupts. A non-secure interrupt should never be routed to EL3 from + from non-secure state. Also if a routing model is chosen where Secure-EL1 + interrupts are routed to S-EL1 when execution is in Secure state, then a + S-EL1 interrupt should never be routed to EL3 from secure state. The handler + could use the security state flag to check this. + +#. Determining whether a context switch is required. This depends upon the + routing model and interrupt type. For non secure and S-EL1 interrupt, + if the security state of the execution context where the interrupt was + generated is not the same as the security state required for handling + the interrupt, a context switch is required. The following 2 cases + require a context switch from secure to non-secure or vice-versa: + + #. A Secure-EL1 interrupt taken from the non-secure state should be + routed to the Secure Payload. + + #. A non-secure interrupt taken from the secure state should be routed + to the last known non-secure exception level. + + The SPD service must save the system register context of the current + security state. It must then restore the system register context of the + target security state. It should use the ``cm_set_next_eret_context()`` API + to ensure that the next ``cpu_context`` to be restored is of the target + security state. + + If the target state is secure then execution should be handed to the SP as + per the synchronous interrupt handling model it implements. A Secure-EL1 + interrupt can be routed to EL3 while execution is in the SP. This implies + that SP execution can be preempted while handling an interrupt by a + another higher priority Secure-EL1 interrupt or a EL3 interrupt. The SPD + service should be able to handle this preemption or manage secure interrupt + priorities before handing control to the SP. + +#. Setting the return value of the handler to the per-cpu ``cpu_context`` if + the interrupt has been successfully validated and ready to be handled at a + lower exception level. + +The routing model allows non-secure interrupts to interrupt Secure-EL1 when in +secure state if it has been configured to do so. The SPD service and the SP +should implement a mechanism for routing these interrupts to the last known +exception level in the non-secure state. The former should save the SP context, +restore the non-secure context and arrange for entry into the non-secure state +so that the interrupt can be handled. + +Interrupt exit +^^^^^^^^^^^^^^ + +When the Secure Payload has finished handling a Secure-EL1 interrupt, it could +return control back to the SPD service through a SMC32 or SMC64. The SPD service +should handle this secure monitor call so that execution resumes in the +exception level and the security state from where the Secure-EL1 interrupt was +originally taken. + +Test secure payload dispatcher Secure-EL1 interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The example TSPD service registers a handler for Secure-EL1 interrupts taken +from the non-secure state. During execution in S-EL1, the TSPD expects that the +Secure-EL1 interrupts are handled in S-EL1 by TSP. Its handler +``tspd_secure_el1_interrupt_handler()`` expects only to be invoked for Secure-EL1 +originating from the non-secure state. It takes the following actions upon being +invoked. + +#. It uses the security state provided in the ``flags`` parameter to ensure + that the secure interrupt originated from the non-secure state. It asserts + if this is not the case. + +#. It saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE);``. + +#. It sets the ``ELR_EL3`` system register to ``tsp_sel1_intr_entry`` and sets the + ``SPSR_EL3.DAIF`` bits in the secure CPU context. It sets ``x0`` to + ``TSP_HANDLE_SEL1_INTR_AND_RETURN``. If the TSP was preempted earlier by a non + secure interrupt during ``yielding`` SMC processing, save the registers that + will be trashed, which is the ``ELR_EL3`` and ``SPSR_EL3``, in order to be able + to re-enter TSP for Secure-EL1 interrupt processing. It does not need to + save any other secure context since the TSP is expected to preserve it + (see Section 2.2.2.1). + +#. It restores the system register context for the secure state by calling + ``cm_el1_sysregs_context_restore(SECURE);``. + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE);``. + +#. It returns the per-cpu ``cpu_context`` to indicate that the interrupt can + now be handled by the SP. ``x1`` is written with the value of ``elr_el3`` + register for the non-secure state. This information is used by the SP for + debugging purposes. + +The figure below describes how the interrupt handling is implemented by the TSPD +when a Secure-EL1 interrupt is generated when execution is in the non-secure +state. + +|Image 1| + +The TSP issues an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier to +signal completion of interrupt handling. + +The TSPD service takes the following actions in ``tspd_smc_handler()`` function +upon receiving an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier: + +#. It ensures that the call originated from the secure state otherwise + execution returns to the non-secure state with ``SMC_UNK`` in ``x0``. + +#. It restores the saved ``ELR_EL3`` and ``SPSR_EL3`` system registers back to + the secure CPU context (see step 3 above) in case the TSP had been preempted + by a non secure interrupt earlier. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the non-secure ``cpu_context`` + as the return value. + +Test secure payload dispatcher non-secure interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSP in Secure-EL1 can be preempted by a non-secure interrupt during +``yielding`` SMC processing or by a higher priority EL3 interrupt during +Secure-EL1 interrupt processing. Currently only non-secure interrupts can +cause preemption of TSP since there are no EL3 interrupts in the +system. + +It should be noted that while TSP is preempted, the TSPD only allows entry into +the TSP either for Secure-EL1 interrupt handling or for resuming the preempted +``yielding`` SMC in response to the ``TSP_FID_RESUME`` SMC from the normal world. +(See Section 3). + +The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC processing +can be routed to either EL3 or Secure-EL1 and is controlled by build option +``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section 2.2.2.1). If the build option is set, +the TSPD will set the routing model for the non-secure interrupt to be routed to +EL3 from secure state i.e. **TEL3=1, CSS=0** and registers +``tspd_ns_interrupt_handler()`` as the non-secure interrupt handler. The +``tspd_ns_interrupt_handler()`` on being invoked ensures that the interrupt +originated from the secure state and disables routing of non-secure interrupts +from secure state to EL3. This is to prevent further preemption (by a non-secure +interrupt) when TSP is reentered for handling Secure-EL1 interrupts that +triggered while execution was in the normal world. The +``tspd_ns_interrupt_handler()`` then invokes ``tspd_handle_sp_preemption()`` for +further handling. + +If the ``TSP_NS_INTR_ASYNC_PREEMPT`` build option is zero (default), the default +routing model for non-secure interrupt in secure state is in effect +i.e. **TEL3=0, CSS=0**. During ``yielding`` SMC processing, the IRQ +exceptions are unmasked i.e. ``PSTATE.I=0``, and a non-secure interrupt will +trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose +register context and issues an SMC with ``TSP_PREEMPTED`` as the function +identifier to signal preemption of TSP. The TSPD SMC handler, +``tspd_smc_handler()``, ensures that the SMC call originated from the +secure state otherwise execution returns to the non-secure state with +``SMC_UNK`` in ``x0``. It then invokes ``tspd_handle_sp_preemption()`` for +further handling. + +The ``tspd_handle_sp_preemption()`` takes the following actions upon being +invoked: + +#. It saves the system register context for the secure state by calling + ``cm_el1_sysregs_context_save(SECURE)``. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``SMC_PREEMPTED`` is set in x0 and return to non secure state after + restoring non secure context. + +The Normal World is expected to resume the TSP after the ``yielding`` SMC preemption +by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier (see section 3). +The TSPD service takes the following actions in ``tspd_smc_handler()`` function +upon receiving this SMC: + +#. It ensures that the call originated from the non secure state. An + assertion is raised otherwise. + +#. Checks whether the TSP needs a resume i.e check if it was preempted. It + then saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE)``. + +#. Restores the secure context by calling + ``cm_el1_sysregs_context_restore(SECURE)`` + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the secure ``cpu_context`` as the + return value. + +The figure below describes how the TSP/TSPD handle a non-secure interrupt when +it is generated during execution in the TSP with ``PSTATE.I`` = 0 when the +``TSP_NS_INTR_ASYNC_PREEMPT`` build flag is 0. + +|Image 2| + +Secure payload +~~~~~~~~~~~~~~ + +The SP should implement one or both of the synchronous and asynchronous +interrupt handling models depending upon the interrupt routing model it has +chosen (as described in 2.2.3). + +In the synchronous model, it should begin handling a Secure-EL1 interrupt after +receiving control from the SPD service at an entrypoint agreed upon during build +time or during the registration phase. Before handling the interrupt, the SP +should save any Secure-EL1 system register context which is needed for resuming +normal execution in the SP later e.g. ``SPSR_EL1,``\ ELR\_EL1\`. After handling the +interrupt, the SP could return control back to the exception level and security +state where the interrupt was originally taken from. The SP should use an SMC32 +or SMC64 to ask the SPD service to do this. + +In the asynchronous model, the Secure Payload is responsible for handling +non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception +vector table when ``PSTATE.I`` and ``PSTATE.F`` bits are 0. As described earlier, +when a non-secure interrupt is generated, the SP should coordinate with the SPD +service to pass control back to the non-secure state in the last known exception +level. This will allow the non-secure interrupt to be handled in the non-secure +state. + +Test secure payload behavior +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSPD hands control of a Secure-EL1 interrupt to the TSP at the +``tsp_sel1_intr_entry()``. The TSP handles the interrupt while ensuring that the +handover agreement described in Section 2.2.2.1 is maintained. It updates some +statistics by calling ``tsp_update_sync_sel1_intr_stats()``. It then calls +``tsp_common_int_handler()`` which. + +#. Checks whether the interrupt is the secure physical timer interrupt. It + uses the platform API ``plat_ic_get_pending_interrupt_id()`` to get the + interrupt number. If it is not the secure physical timer interrupt, then + that means that a higher priority interrupt has preempted it. Invoke + ``tsp_handle_preemption()`` to handover control back to EL3 by issuing + an SMC with ``TSP_PREEMPTED`` as the function identifier. + +#. Handles the secure timer interrupt interrupt by acknowledging it using the + ``plat_ic_acknowledge_interrupt()`` platform API, calling + ``tsp_generic_timer_handler()`` to reprogram the secure physical generic + timer and calling the ``plat_ic_end_of_interrupt()`` platform API to signal + end of interrupt processing. + +The TSP passes control back to the TSPD by issuing an SMC64 with +``TSP_HANDLED_S_EL1_INTR`` as the function identifier. + +The TSP handles interrupts under the asynchronous model as follows. + +#. Secure-EL1 interrupts are handled by calling the ``tsp_common_int_handler()`` + function. The function has been described above. + +#. Non-secure interrupts are handled by by calling the ``tsp_common_int_handler()`` + function which ends up invoking ``tsp_handle_preemption()`` and issuing an + SMC64 with ``TSP_PREEMPTED`` as the function identifier. Execution resumes at + the instruction that follows this SMC instruction when the TSPD hands + control to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the + function identifier from the non-secure state (see section 2.3.2.4). + +#. .. rubric:: Other considerations + :name: other-considerations + +Implication of preempted SMC on Non-Secure Software +--------------------------------------------------- + +A ``yielding`` SMC call to Secure payload can be preempted by a non-secure +interrupt and the execution can return to the non-secure world for handling +the interrupt (For details on ``yielding`` SMC refer `SMC calling convention`_). +In this case, the SMC call has not completed its execution and the execution +must return back to the secure payload to resume the preempted SMC call. +This can be achieved by issuing an SMC call which instructs to resume the +preempted SMC. + +A ``fast`` SMC cannot be preempted and hence this case will not happen for +a fast SMC call. + +In the Test Secure Payload implementation, ``TSP_FID_RESUME`` is designated +as the resume SMC FID. It is important to note that ``TSP_FID_RESUME`` is a +``yielding`` SMC which means it too can be be preempted. The typical non +secure software sequence for issuing a ``yielding`` SMC would look like this, +assuming ``P.STATE.I=0`` in the non secure state : + +.. code:: c + + int rc; + rc = smc(TSP_YIELD_SMC_FID, ...); /* Issue a Yielding SMC call */ + /* The pending non-secure interrupt is handled by the interrupt handler + and returns back here. */ + while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */ + rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */ + } + +The ``TSP_YIELD_SMC_FID`` is any ``yielding`` SMC function identifier and the smc() +function invokes a SMC call with the required arguments. The pending non-secure +interrupt causes an IRQ exception and the IRQ handler registered at the +exception vector handles the non-secure interrupt and returns. The return value +from the SMC call is tested for ``SMC_PREEMPTED`` to check whether it is +preempted. If it is, then the resume SMC call ``TSP_FID_RESUME`` is issued. The +return value of the SMC call is tested again to check if it is preempted. +This is done in a loop till the SMC call succeeds or fails. If a ``yielding`` +SMC is preempted, until it is resumed using ``TSP_FID_RESUME`` SMC and +completed, the current TSPD prevents any other SMC call from re-entering +TSP by returning ``SMC_UNK`` error. + +-------------- + +*Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.* + +.. _Porting Guide: ./porting-guide.rst +.. _SMC calling convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + +.. |Image 1| image:: diagrams/sec-int-handling.png?raw=true +.. |Image 2| image:: diagrams/non-sec-int-handling.png?raw=true diff --git a/docs/plat/hikey.rst b/docs/plat/hikey.rst new file mode 100644 index 0000000..027e14c --- /dev/null +++ b/docs/plat/hikey.rst @@ -0,0 +1,156 @@ +Description +=========== + +HiKey is one of 96boards. Hisilicon Kirin6220 processor is installed on HiKey. + +More information are listed in `link`_. + +How to build +============ + +Code Locations +-------------- + +- ARM Trusted Firmware: + `link `__ + +- edk2: + `link `__ + +- OpenPlatformPkg: + `link `__ + +- l-loader: + `link `__ + +- uefi-tools: + `link `__ + +- atf-fastboot: + `link `__ + +Build Procedure +--------------- + +- Fetch all the above repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Create the symbol link to OpenPlatformPkg in edk2. + + .. code:: shell + + $cd ${BUILD_PATH}/edk2 + $ln -sf ../OpenPlatformPkg + +- Prepare AARCH64 && AARCH32 toolchain. Prepare python. + +- If your hikey hardware is built by CircuitCo, update *uefi-tools/platform.config* first. *(optional)* + **Uncomment the below sentence. Otherwise, UEFI can't output messages on serial + console on hikey.** + + .. code:: shell + + BUILDFLAGS=-DSERIAL_BASE=0xF8015000 + + If your hikey hardware is built by LeMarker, nothing to do. + +- Build it as debug mode. Create your own build script file or you could refer to **build\_uefi.sh** in l-loader git repository. + + .. code:: shell + + BUILD_OPTION=DEBUG + export AARCH64_TOOLCHAIN=GCC5 + export UEFI_TOOLS_DIR=${BUILD_PATH}/uefi-tools + export EDK2_DIR=${BUILD_PATH}/edk2 + EDK2_OUTPUT_DIR=${EDK2_DIR}/Build/HiKey/${BUILD_OPTION}_${AARCH64_TOOLCHAIN} + # Build fastboot for ARM Trust Firmware. It's used for recovery mode. + cd ${BUILD_PATH}/atf-fastboot + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=hikey DEBUG=1 + # Convert DEBUG/RELEASE to debug/release + FASTBOOT_BUILD_OPTION=$(echo ${BUILD_OPTION} | tr '[A-Z]' '[a-z]') + cd ${EDK2_DIR} + # Build UEFI & ARM Trust Firmware + ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware hikey + # Generate l-loader.bin + cd ${BUILD_PATH}/l-loader + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin + ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin + python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd + arm-linux-gnueabihf-gcc -c -o start.o start.S + arm-linux-gnueabihf-ld -Bstatic -Tl-loader.lds -Ttext 0xf9800800 start.o -o loader + arm-linux-gnueabihf-objcopy -O binary loader temp + python gen_loader_hikey.py -o l-loader.bin --img_loader=temp --img_bl1=bl1.bin --img_ns_bl1u=fastboot.bin + +- Generate partition table for aosp. The eMMC capacity is either 4GB or 8GB. Just change "aosp-4g" to "linux-4g" for debian. + + .. code:: shell + + $PTABLE=aosp-4g SECTOR_SIZE=512 bash -x generate_ptable.sh + +Setup Console +------------- + +- Install ser2net. Use telnet as the console since UEFI fails to display Boot Manager GUI in minicom. **If you don't need Boot Manager GUI, just ignore this section.** + + .. code:: shell + + $sudo apt-get install ser2net + +- Configure ser2net. + + .. code:: shell + + $sudo vi /etc/ser2net.conf + + Append one line for serial-over-USB in below. + *#ser2net.conf* + + .. code:: shell + + 2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner + +- Open the console. + + .. code:: shell + + $telnet localhost 2004 + + And you could open the console remotely, too. + +Flush images in recovery mode +----------------------------- + +- Make sure Pin3-Pin4 on J15 are connected for recovery mode. Then power on HiKey. + +- Remove the modemmanager package. This package may cause the idt tool failure. + + .. code:: shell + + $sudo apt-get purge modemmanager + +- Run the command to download l-loader.bin into HiKey. + + .. code:: shell + + $sudo python hisi-idt.py -d /dev/ttyUSB1 --img1 l-loader.bin + +- Update images. All aosp or debian images could be fetched from `link `__. + + .. code:: shell + + $sudo fastboot flash ptable prm_ptable.img + $sudo fastboot flash fastboot fip.bin + $sudo fastboot flash boot boot.img + $sudo fastboot flash cache cache.img + $sudo fastboot flash system system.img + $sudo fastboot flash userdata userdata.img + +Boot UEFI in normal mode +------------------------ + +- Make sure Pin3-Pin4 on J15 are open for normal boot mode. Then power on HiKey. + +- Reference `link `__ + +.. _link: https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey/Quickstart/README.md diff --git a/docs/plat/hikey960.rst b/docs/plat/hikey960.rst new file mode 100644 index 0000000..c28ef3a --- /dev/null +++ b/docs/plat/hikey960.rst @@ -0,0 +1,172 @@ +Description +=========== + +HiKey960 is one of 96boards. Hisilicon Hi3660 processor is installed on HiKey960. + +More information are listed in `link`_. + +How to build +============ + +Code Locations +-------------- + +- ARM Trusted Firmware: + `link `__ + +- edk2: + `link `__ + +- OpenPlatformPkg: + `link `__ + +- l-loader: + `link `__ + +- uefi-tools: + `link `__ + +Build Procedure +--------------- + +- Fetch all the above 5 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Create the symbol link to OpenPlatformPkg in edk2. + + .. code:: shell + + $cd ${BUILD_PATH}/edk2 + $ln -sf ../OpenPlatformPkg + +- Prepare AARCH64 toolchain. + +- If your hikey960 hardware is v1, update *uefi-tools/platform.config* first. *(optional)* + **Uncomment the below sentence. Otherwise, UEFI can't output messages on serial + console on hikey960 v1.** + + .. code:: shell + + BUILDFLAGS=-DSERIAL_BASE=0xFDF05000 + + If your hikey960 hardware is v2 or newer, nothing to do. + +- Build it as debug mode. Create script file for build. + + .. code:: shell + + BUILD_OPTION=DEBUG + export AARCH64_TOOLCHAIN=GCC48 + export UEFI_TOOLS_DIR=${BUILD_PATH}/uefi-tools + export EDK2_DIR=${BUILD_PATH}/edk2 + EDK2_OUTPUT_DIR=${EDK2_DIR}/Build/HiKey960/${BUILD_OPTION}_${AARCH64_TOOLCHAIN} + cd ${EDK2_DIR} + # Build UEFI & ARM Trust Firmware + ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware hikey960 + # Generate l-loader.bin + cd ${BUILD_PATH}/l-loader + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd + python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd + +- Generate partition table. + *Make sure that you're using the sgdisk in the l-loader directory.* + + .. code:: shell + + $PTABLE=aosp-32g SECTOR_SIZE=4096 SGDISK=./sgdisk bash -x generate_ptable.sh + +Setup Console +------------- + +- Install ser2net. Use telnet as the console since UEFI will output window + that fails to display in minicom. + + .. code:: shell + + $sudo apt-get install ser2net + +- Configure ser2net. + + .. code:: shell + + $sudo vi /etc/ser2net.conf + + Append one line for serial-over-USB in *#ser2net.conf* + + :: + + 2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner + +- Open the console. + + .. code:: shell + + $telnet localhost 2004 + + And you could open the console remotely, too. + +Boot UEFI in recovery mode +-------------------------- + +- Fetch that are used in recovery mode. The code location is in below. + `link `__ + +- Generate l-loader.bin. + + .. code:: shell + + $cd tools-images-hikey960 + $ln -sf ${BUILD_PATH}/l-loader/l-loader.bin + +- Prepare config file. + + .. code:: shell + + $vi config + # The content of config file + ./sec_user_xloader.img 0x00020000 + ./sec_uce_boot.img 0x6A908000 + ./l-loader.bin 0x1AC00000 + +- Remove the modemmanager package. This package may causes hikey\_idt tool failure. + + .. code:: shell + + $sudo apt-get purge modemmanager + +- Run the command to download l-loader.bin into HiKey960. + + .. code:: shell + + $sudo ./hikey_idt -c config -p /dev/ttyUSB1 + +- UEFI running in recovery mode. + When prompt '.' is displayed on console, press hotkey 'f' in keyboard. Then Android fastboot app is running. + The timeout of prompt '.' is 10 seconds. + +- Update images. + + .. code:: shell + + $sudo fastboot flash ptable prm_ptable.img + $sudo fastboot flash xloader sec_xloader.img + $sudo fastboot flash fastboot l-loader.bin + $sudo fastboot flash fip fip.bin + $sudo fastboot flash boot boot.img + $sudo fastboot flash cache cache.img + $sudo fastboot flash system system.img + $sudo fastboot flash userdata userdata.img + +- Notice: UEFI could also boot kernel in recovery mode, but BL31 isn't loaded in + recovery mode. + +Boot UEFI in normal mode +------------------------ + +- Make sure "Boot Mode" switch is OFF for normal boot mode. Then power on HiKey960. + +- Reference `link `__ + +.. _link: http://www.96boards.org/documentation/ConsumerEdition/HiKey960/README.md diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst new file mode 100644 index 0000000..7aac7e5 --- /dev/null +++ b/docs/plat/nvidia-tegra.rst @@ -0,0 +1,98 @@ +Tegra SoCs - Overview +===================== + +- .. rubric:: T210 + :name: t210 + +T210 has Quad ARM® Cortex®-A57 cores in a switched configuration with a +companion set of quad ARM Cortex-A53 cores. The Cortex-A57 and A53 cores +support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code +including legacy ARMv7 applications. The Cortex-A57 processors each have +48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared +Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction +and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache. + +- .. rubric:: T132 + :name: t132 + +Denver is NVIDIA's own custom-designed, 64-bit, dual-core CPU which is +fully ARMv8 architecture compatible. Each of the two Denver cores +implements a 7-way superscalar microarchitecture (up to 7 concurrent +micro-ops can be executed per clock), and includes a 128KB 4-way L1 +instruction cache, a 64KB 4-way L1 data cache, and a 2MB 16-way L2 +cache, which services both cores. + +Denver implements an innovative process called Dynamic Code Optimization, +which optimizes frequently used software routines at runtime into dense, +highly tuned microcode-equivalent routines. These are stored in a +dedicated, 128MB main-memory-based optimization cache. After being read +into the instruction cache, the optimized micro-ops are executed, +re-fetched and executed from the instruction cache as long as needed and +capacity allows. + +Effectively, this reduces the need to re-optimize the software routines. +Instead of using hardware to extract the instruction-level parallelism +(ILP) inherent in the code, Denver extracts the ILP once via software +techniques, and then executes those routines repeatedly, thus amortizing +the cost of ILP extraction over the many execution instances. + +Denver also features new low latency power-state transitions, in addition +to extensive power-gating and dynamic voltage and clock scaling based on +workloads. + +Directory structure +=================== + +- plat/nvidia/tegra/common - Common code for all Tegra SoCs +- plat/nvidia/tegra/soc/txxx - Chip specific code + +Trusted OS dispatcher +===================== + +Tegra supports multiple Trusted OS', Trusted Little Kernel (TLK) being one of +them. In order to include the 'tlkd' dispatcher in the image, pass 'SPD=tlkd' +on the command line while preparing a bl31 image. This allows other Trusted OS +vendors to use the upstream code and include their dispatchers in the image +without changing any makefiles. + +Preparing the BL31 image to run on Tegra SoCs +============================================= + +.. code:: shell + + CROSS_COMPILE=/bin/aarch64-none-elf- make PLAT=tegra \ + TARGET_SOC= SPD= bl31 + +Platforms wanting to use different TZDRAM\_BASE, can add ``TZDRAM_BASE=`` +to the build command line. + +The Tegra platform code expects a pointer to the following platform specific +structure via 'x1' register from the BL2 layer which is used by the +bl31\_early\_platform\_setup() handler to extract the TZDRAM carveout base and +size for loading the Trusted OS and the UART port ID to be used. The Tegra +memory controller driver programs this base/size in order to restrict NS +accesses. + +typedef struct plat\_params\_from\_bl2 { +/\* TZ memory size */ +uint64\_t tzdram\_size; +/* TZ memory base */ +uint64\_t tzdram\_base; +/* UART port ID \*/ +int uart\_id; +} plat\_params\_from\_bl2\_t; + +Power Management +================ + +The PSCI implementation expects each platform to expose the 'power state' +parameter to be used during the 'SYSTEM SUSPEND' call. The state-id field +is implementation defined on Tegra SoCs and is preferably defined by +tegra\_def.h. + +Tegra configs +============= + +- 'tegra\_enable\_l2\_ecc\_parity\_prot': This flag enables the L2 ECC and Parity + Protection bit, for ARM Cortex-A57 CPUs, during CPU boot. This flag will + be enabled by Tegrs SoCs during 'Cluster power up' or 'System Suspend' exit. diff --git a/docs/plat/qemu.rst b/docs/plat/qemu.rst new file mode 100644 index 0000000..4e2cd7c --- /dev/null +++ b/docs/plat/qemu.rst @@ -0,0 +1,48 @@ +ARM Trusted Firmware for QEMU virt ARMv8-A +========================================== + +ARM Trusted Firmware implements the EL3 firmware layer for QEMU virt +ARMv8-A. BL1 is used as the BootROM, supplied with the -bios argument. +When QEMU starts all CPUs are released simultaneously, BL1 selects a +primary CPU to handle the boot and the secondaries are placed in a polling +loop to be released by normal world via PSCI. + +BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to +add a node describing PSCI and also enable methods for the CPUs. + +An ARM64 defonfig v4.5 Linux kernel is known to boot, FTD doesn't need to be +provided as it's generated by QEMU. + +Current limitations: + +- Only cold boot is supported +- No build instructions for QEMU\_EFI.fd and rootfs-arm64.cpio.gz +- No instructions for how to load a BL32 (Secure Payload) + +``QEMU_EFI.fd`` can be dowloaded from +http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC49/QEMU_EFI.fd + +Boot binaries, except BL1, are primarily loaded via semi-hosting so all +binaries has to reside in the same directory as QEMU is started from. This +is conveniently achieved with symlinks the local names as: + +- ``bl2.bin`` -> BL2 +- ``bl31.bin`` -> BL31 +- ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``) +- ``Image`` -> linux/Image + +To build: + +:: + + make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu + +To start (QEMU v2.6.0): + +:: + + qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \ + -kernel Image \ + -append console=ttyAMA0,38400 keep_bootcon root=/dev/vda2 \ + -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin \ + -d unimp -semihosting-config enable,target=native diff --git a/docs/plat/socionext-uniphier.rst b/docs/plat/socionext-uniphier.rst new file mode 100644 index 0000000..fb6ebe5 --- /dev/null +++ b/docs/plat/socionext-uniphier.rst @@ -0,0 +1,124 @@ +ARM Trusted Firmware for Socionext UniPhier SoCs +================================================ + +Socionext UniPhier ARMv8-A SoCs use ARM Trusted Firmware as the secure world +firmware, supporting BL1, BL2, and BL31. + +UniPhier SoC family implements its internal boot ROM, so BL1 is used as pseudo +ROM (i.e. runs in RAM). The internal boot ROM loads 64KB `1`_ image from a +non-volatile storage to the on-chip SRAM. Unfortunately, BL1 does not fit in +the 64KB limit if `Trusted Board Boot`_ (TBB) is enabled. To solve this problem, +Socionext provides a first stage loader called `UniPhier BL`_. This loader runs +in the on-chip SRAM, initializes the DRAM, expands BL1 there, and hands the +control over to it. Therefore, all images of ARM Trusted Firmware run in DRAM. + +The UniPhier platform works with/without TBB. See below for the build process +of each case. The image authentication for the UniPhier platform fully +complies with the Trusted Board Boot Requirements (TBBR) specification. + +The UniPhier BL does not implement the authentication functionality, that is, +it can not verify the BL1 image by itself. Instead, the UniPhier BL assures +the BL1 validity in a different way; BL1 is GZIP-compressed and appended to +the UniPhier BL. The concatenation of the UniPhier BL and the compressed BL1 +fits in the 64KB limit. The concatenated image is loaded by the boot ROM +(and verified if the chip fuses are blown). + +:: + + to the lowest common denominator. + +Boot Flow +--------- + +#. The Boot ROM + +This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with +compressed-BL1 appended) into the on-chip SRAM. If the SoC fuses are blown, +the image is verified by the SoC's own method. + +#. UniPhier BL + +This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM +setup, it decompresses the appended BL1 image into the DRAM, then jumps to +the BL1 entry. + +#. BL1 + +This runs in the DRAM. It extracts BL2 from FIP (Firmware Image Package). +If TBB is enabled, the BL2 is authenticated by the standard mechanism of ARM +Trusted Firmware. + +#. BL2, BL31, and more + +They all run in the DRAM, and are authenticated by the standard mechanism if +TBB is enabled. See `Firmware Design`_ for details. + +Basic Build +----------- + +BL1 must be compressed for the reason above. The UniPhier's platform makefile +provides a build target ``bl1_gzip`` for this. + +For a non-secure boot loader (aka BL33), U-Boot is well supported for UniPhier +SoCs. The U-Boot image (``u-boot.bin``) must be built in advance. For the build +procedure of U-Boot, refer to the document in the `U-Boot`_ project. + +To build minimum functionality for UniPhier (without TBB): + +:: + + make CROSS_COMPILE= PLAT=uniphier BL33= bl1_gzip fip + +Output images: + +- ``bl1.bin.gzip`` +- ``fip.bin`` + +Optional features +----------------- + +- Trusted Board Boot + +`mbed TLS`_ is needed as the cryptographic and image parser modules. +Refer to the `User Guide`_ for the appropriate version of mbed TLS. + +To enable TBB, add the following options to the build command: + +:: + + TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR= + +- System Control Processor (SCP) + +If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image +in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards +still work without SCP, but SCP provides better power management support. + +To include SCP\_BL2, add the following option to the build command: + +:: + + SCP_BL2= + +- BL32 (Secure Payload) + +To enable BL32, add the following option to the build command: + +:: + + SPD= BL32= + +If you use TSP for BL32, ``BL32=`` is not required. Just add the +following: + +:: + + SPD=tspd + +.. _1: Some%20SoCs%20can%20load%2080KB,%20but%20the%20software%20implementation%20must%20be%20aligned +.. _Trusted Board Boot: ../trusted-board-boot.rst +.. _UniPhier BL: https://github.com/uniphier/uniphier-bl +.. _Firmware Design: ../firmware-design.rst +.. _U-Boot: https://www.denx.de/wiki/U-Boot +.. _mbed TLS: https://tls.mbed.org/ +.. _User Guide: ../user-guide.rst diff --git a/docs/plat/xilinx-zynqmp.rst b/docs/plat/xilinx-zynqmp.rst new file mode 100644 index 0000000..b9c7825 --- /dev/null +++ b/docs/plat/xilinx-zynqmp.rst @@ -0,0 +1,67 @@ +ARM Trusted Firmware for Xilinx Zynq UltraScale+ MPSoC +====================================================== + +ARM Trusted Firmware implements the EL3 firmware layer for Xilinx Zynq +UltraScale + MPSoC. +The platform only uses the runtime part of ATF as ZynqMP already has a +BootROM (BL1) and FSBL (BL2). + +BL31 is ATF. +BL32 is an optional Secure Payload. +BL33 is the non-secure world software (U-Boot, Linux etc). + +To build: + +.. code:: bash + + make ERROR_DEPRECATED=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp bl31 + +To build bl32 TSP you have to rebuild bl31 too: + +.. code:: bash + + make ERROR_DEPRECATED=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp SPD=tspd bl31 bl32 + +ZynqMP platform specific build options +====================================== + +- ``ZYNQMP_ATF_MEM_BASE``: Specifies the base address of the bl31 binary. +- ``ZYNQMP_ATF_MEM_SIZE``: Specifies the size of the memory region of the bl31 binary. +- ``ZYNQMP_BL32_MEM_BASE``: Specifies the base address of the bl32 binary. +- ``ZYNQMP_BL32_MEM_SIZE``: Specifies the size of the memory region of the bl32 binary. + +- ``ZYNQMP_CONSOLE``: Select the console driver. Options: + + - ``cadence``, ``cadence0``: Cadence UART 0 + - ``cadence1`` : Cadence UART 1 + +FSBL->ATF Parameter Passing +=========================== + +The FSBL populates a data structure with image information for the ATF. The ATF +uses that data to hand off to the loaded images. The address of the handoff data +structure is passed in the ``PMU_GLOBAL.GLOBAL_GEN_STORAGE6`` register. The +register is free to be used by other software once the ATF is bringing up +further firmware images. + +Power Domain Tree +================= + +The following power domain tree represents the power domain model used by the +ATF for ZynqMP: + +:: + + +-+ + |0| + +-+ + +-------+---+---+-------+ + | | | | + | | | | + v v v v + +-+ +-+ +-+ +-+ + |0| |1| |2| |3| + +-+ +-+ +-+ +-+ + +The 4 leaf power domains represent the individual A53 cores, while resources +common to the cluster are grouped in the power domain on the top. diff --git a/docs/platform-migration-guide.rst b/docs/platform-migration-guide.rst new file mode 100644 index 0000000..5e8eeba --- /dev/null +++ b/docs/platform-migration-guide.rst @@ -0,0 +1,596 @@ +Guide to migrate to new Platform porting interface +================================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +-------------- + +Introduction +------------ + +The PSCI implementation in Trusted Firmware has undergone a redesign because of +three requirements that the PSCI 1.0 specification introduced : + +- Removing the framework assumption about the structure of the MPIDR, and + its relation to the power topology enables support for deeper and more + complex hierarchies. + +- Reworking the power state coordination implementation in the framework + to support the more detailed PSCI 1.0 requirements and reduce platform + port complexity + +- Enable the use of the extended power\_state parameter and the larger StateID + field + +The PSCI 1.0 implementation introduces new frameworks to fulfill the above +requirements. These framework changes mean that the platform porting API must +also be modified. This document is a guide to assist migration of the existing +platform ports to the new platform API. + +This document describes the new platform API and compares it with the +deprecated API. It also describes the compatibility layer that enables the +existing platform ports to work with the PSCI 1.0 implementation. The +deprecated platform API is documented for reference. + +Platform API modification due to PSCI framework changes +------------------------------------------------------- + +This section describes changes to the platform APIs. + +Power domain topology framework platform API modifications +---------------------------------------------------------- + +This removes the assumption in the PSCI implementation that MPIDR +based affinity instances map directly to power domains. A power domain, as +described in section 4.2 of `PSCI`_, could contain a core or a logical group +of cores (a cluster) which share some state on which power management +operations can be performed. The existing affinity instance based APIs +``plat_get_aff_count()`` and ``plat_get_aff_state()`` are deprecated. The new +platform interfaces that are introduced for this framework are: + +- ``plat_core_pos_by_mpidr()`` +- ``plat_my_core_pos()`` +- ``plat_get_power_domain_tree_desc()`` + +``plat_my_core_pos()`` and ``plat_core_pos_by_mpidr()`` are mandatory +and are meant to replace the existing ``platform_get_core_pos()`` API. +The description of these APIs can be found in the `Porting Guide`_. +These are used by the power domain topology framework such that: + +#. The generic PSCI code does not generate MPIDRs or use them to query the + platform about the number of power domains at a particular power level. The + ``plat_get_power_domain_tree_desc()`` provides a description of the power + domain tree on the SoC through a pointer to the byte array containing the + power domain topology tree description data structure. + +#. The linear indices returned by ``plat_core_pos_by_mpidr()`` and + ``plat_my_core_pos()`` are used to retrieve core power domain nodes from + the power domain tree. These core indices are unique for a core and it is a + number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. The platform can choose + to implement a static mapping between ``MPIDR`` and core index or implement + a dynamic mapping, choosing to skip the unavailable/unused cores to compact + the core indices. + +In addition, the platforms must define the macros ``PLAT_NUM_PWR_DOMAINS`` and +``PLAT_MAX_PWR_LVL`` which replace the macros ``PLAT_NUM_AFFS`` and +``PLATFORM_MAX_AFFLVL`` respectively. On platforms where the affinity instances +correspond to power domains, the values of new macros remain the same as the +old ones. + +More details on the power domain topology description and its platform +interface can be found in `psci pd tree`_. + +Composite power state framework platform API modifications +---------------------------------------------------------- + +The state-ID field in the power-state parameter of a CPU\_SUSPEND call can be +used to describe the composite power states specific to a platform. The existing +PSCI state coordination had the limitation that it operates on a run/off +granularity of power states and it did not interpret the state-ID field. This +was acceptable as the specification requirement in PSCI 0.2 and the framework's +approach to coordination only required maintaining a reference +count of the number of cores that have requested the cluster to remain powered. + +In the PSCI 1.0 specification, this approach is non optimal. If composite +power states are used, the PSCI implementation cannot make global +decisions about state coordination required because it does not understand the +platform specific states. + +The PSCI 1.0 implementation now defines a generic representation of the +power-state parameter : + +.. code:: c + + typedef struct psci_power_state { + plat_local_state_t pwr_domain_state[PLAT_MAX_PWR_LVL + 1]; + } psci_power_state_t; + +``pwr_domain_state`` is an array where each index corresponds to a power level. +Each entry in the array contains the local power state the power domain at +that power level could enter. The meaning of the local power state value is +platform defined, and can vary between levels in a single platform. The PSCI +implementation constraints the values only so that it can classify the state +as RUN, RETENTION or OFF as required by the specification: + +#. Zero means RUN + +#. All OFF state values at all levels must be higher than all + RETENTION state values at all levels + +The platform is required to define the macros ``PLAT_MAX_RET_STATE`` and +``PLAT_MAX_OFF_STATE`` to the framework. The requirement for these macros can +be found in the `Porting Guide `__. + +The PSCI 1.0 implementation adds support to involve the platform in state +coordination. This enables the platform to decide the final target state. +During a request to place a power domain in a low power state, the platform +is passed an array of requested ``plat_local_state_t`` for that power domain by +each core within it through the ``plat_get_target_pwr_state()`` API. This API +coordinates amongst these requested states to determine a target +``plat_local_state_t`` for that power domain. A default weak implementation of +this API is provided in the platform layer which returns the minimum of the +requested local states back to the PSCI state coordination. More details +of ``plat_get_target_pwr_state()`` API can be found in the +`Porting Guide `__. + +The PSCI Generic implementation expects platform ports to populate the handlers +for the ``plat_psci_ops`` structure which is declared as : + +.. code:: c + + typedef struct plat_psci_ops { + void (*cpu_standby)(plat_local_state_t cpu_state); + int (*pwr_domain_on)(u_register_t mpidr); + void (*pwr_domain_off)(const psci_power_state_t *target_state); + void (*pwr_domain_suspend)(const psci_power_state_t *target_state); + void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); + void (*pwr_domain_suspend_finish)( + const psci_power_state_t *target_state); + void (*system_off)(void) __dead2; + void (*system_reset)(void) __dead2; + int (*validate_power_state)(unsigned int power_state, + psci_power_state_t *req_state); + int (*validate_ns_entrypoint)(unsigned long ns_entrypoint); + void (*get_sys_suspend_power_state)( + psci_power_state_t *req_state); + } plat_psci_ops_t; + +The description of these handlers can be found in the `Porting Guide `__. +The previous ``plat_pm_ops`` structure is deprecated. Compared with the previous +handlers, the major differences are: + +- Difference in parameters + +The PSCI 1.0 implementation depends on the ``validate_power_state`` handler to +convert the power-state parameter (possibly encoding a composite power state) +passed in a PSCI ``CPU_SUSPEND`` to the ``psci_power_state`` format. This handler +is now mandatory for PSCI ``CPU_SUSPEND`` support. + +The ``plat_psci_ops`` handlers, ``pwr_domain_off`` and ``pwr_domain_suspend``, are +passed the target local state for each affected power domain. The platform +must execute operations specific to these target states. Similarly, +``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish`` are passed the local +states of the affected power domains before wakeup. The platform +must execute actions to restore these power domains from these specific +local states. + +- Difference in invocation + +Whereas the power management handlers in ``plat_pm_ops`` used to be invoked +for each affinity level till the target affinity level, the new handlers +are only invoked once. The ``target_state`` encodes the target low power +state or the low power state woken up from for each affected power domain. + +- Difference in semantics + +Although the previous ``suspend`` handlers could be used for power down as well +as retention at different affinity levels, the new handlers make this support +explicit. The ``pwr_domain_suspend`` can be used to specify powerdown and +retention at various power domain levels subject to the conditions mentioned +in section 4.2.1 of `PSCI`_ + +Unlike the previous ``standby`` handler, the ``cpu_standby()`` handler is only used +as a fast path for placing a core power domain into a standby or retention +state. + +The below diagram shows the sequence of a PSCI SUSPEND call and the interaction +with the platform layer depicting the exchange of data between PSCI Generic +layer and the platform layer. + +|Image 1| + +Refer `plat/arm/board/fvp/fvp\_pm.c`_ for the implementation details of +these handlers for the FVP. The commit `38dce70f51fb83b27958ba3e2ad15f5635cb1061`_ +demonstrates the migration of ARM reference platforms to the new platform API. + +Miscellaneous modifications +--------------------------- + +In addition to the framework changes, unification of warm reset entry points on +wakeup from low power modes has led to a change in the platform API. In the +earlier implementation, the warm reset entry used to be programmed into the +mailboxes by the 'ON' and 'SUSPEND' power management hooks. In the PSCI 1.0 +implementation, this information is not required, because it can figure that +out by querying affinity info state whether to execute the 'suspend\_finisher\` +or 'on\_finisher'. + +As a result, the warm reset entry point must be programmed only once. The +``plat_setup_psci_ops()`` API takes the secure entry point as an +additional parameter to enable the platforms to configure their mailbox. The +plat\_psci\_ops handlers ``pwr_domain_on`` and ``pwr_domain_suspend`` no longer take +the warm reset entry point as a parameter. + +Also, some platform APIs which took ``MPIDR`` as an argument were only ever +invoked to perform actions specific to the caller core which makes the argument +redundant. Therefore the platform APIs ``plat_get_my_entrypoint()``, +``plat_is_my_cpu_primary()``, ``plat_set_my_stack()`` and +``plat_get_my_stack()`` are defined which are meant to be invoked only for +operations on the current caller core instead of ``platform_get_entrypoint()``, +``platform_is_primary_cpu()``, ``platform_set_stack()`` and ``platform_get_stack()``. + +Compatibility layer +------------------- + +To ease the migration of the platform ports to the new porting interface, +a compatibility layer is introduced that essentially implements a glue layer +between the old platform API and the new API. The build flag +``ENABLE_PLAT_COMPAT`` (enabled by default), specifies whether to enable this +layer or not. A platform port which has migrated to the new API can disable +this flag within the platform specific makefile. + +The compatibility layer works on the assumption that the onus of +state coordination, in case multiple low power states are supported, +is with the platform. The generic PSCI implementation only takes into +account whether the suspend request is power down or not. This corresponds +with the behavior of the PSCI implementation before the introduction of +new frameworks. Also, it assumes that the affinity levels of the platform +correspond directly to the power domain levels. + +The compatibility layer dynamically constructs the new topology +description array by querying the platform using ``plat_get_aff_count()`` +and ``plat_get_aff_state()`` APIs. The linear index returned by +``platform_get_core_pos()`` is used as the core index for the cores. The +higher level (non-core) power domain nodes must know the cores contained +within its domain. It does so by storing the core index of first core +within it and number of core indexes following it. This means that core +indices returned by ``platform_get_core_pos()`` for cores within a particular +power domain must be consecutive. We expect that this is the case for most +platform ports including ARM reference platforms. + +The old PSCI helpers like ``psci_get_suspend_powerstate()``, +``psci_get_suspend_stateid()``, ``psci_get_suspend_stateid_by_mpidr()``, +``psci_get_max_phys_off_afflvl()`` and ``psci_get_suspend_afflvl()`` are also +implemented for the compatibility layer. This allows the existing +platform ports to work with the new PSCI frameworks without significant +rework. + +Deprecated Platform API +----------------------- + +This section documents the deprecated platform porting API. + +Common mandatory modifications +------------------------------ + +The mandatory macros to be defined by the platform port in ``platform_def.h`` + +- **#define : PLATFORM\_NUM\_AFFS** + + Defines the total number of nodes in the affinity hierarchy at all affinity + levels used by the platform. + +- **#define : PLATFORM\_MAX\_AFFLVL** + + Defines the maximum affinity level that the power management operations + should apply to. ARMv8-A has support for four affinity levels. It is likely + that hardware will implement fewer affinity levels. This macro allows the + PSCI implementation to consider only those affinity levels in the system + that the platform implements. For example, the Base AEM FVP implements two + clusters with a configurable number of cores. It reports the maximum + affinity level as 1, resulting in PSCI power control up to the cluster + level. + +The following functions must be implemented by the platform port to enable +the reset vector code to perform the required tasks. + +Function : platform\_get\_entrypoint() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned long + Return : unsigned long + +This function is called with the ``SCTLR.M`` and ``SCTLR.C`` bits disabled. The core +is identified by its ``MPIDR``, which is passed as the argument. The function is +responsible for distinguishing between a warm and cold reset using platform- +specific means. If it is a warm reset, it returns the entrypoint into the +BL31 image that the core must jump to. If it is a cold reset, this function +must return zero. + +This function is also responsible for implementing a platform-specific mechanism +to handle the condition where the core has been warm reset but there is no +entrypoint to jump to. + +This function does not follow the Procedure Call Standard used by the +Application Binary Interface for the ARM 64-bit architecture. The caller should +not assume that callee saved registers are preserved across a call to this +function. + +Function : platform\_is\_primary\_cpu() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned long + Return : unsigned int + +This function identifies a core by its ``MPIDR``, which is passed as the argument, +to determine whether this core is the primary core or a secondary core. A return +value of zero indicates that the core is not the primary core, while a non-zero +return value indicates that the core is the primary core. + +Common optional modifications +----------------------------- + +Function : platform\_get\_core\_pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned long + Return : int + +A platform may need to convert the ``MPIDR`` of a core to an absolute number, which +can be used as a core-specific linear index into blocks of memory (for example +while allocating per-core stacks). This routine contains a simple mechanism +to perform this conversion, using the assumption that each cluster contains a +maximum of four cores: + +:: + + linear index = cpu_id + (cluster_id * 4) + + cpu_id = 8-bit value in MPIDR at affinity level 0 + cluster_id = 8-bit value in MPIDR at affinity level 1 + +Function : platform\_set\_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned long + Return : void + +This function sets the current stack pointer to the normal memory stack that +has been allocated for the core specified by MPIDR. For BL images that only +require a stack for the primary core the parameter is ignored. The size of +the stack allocated to each core is specified by the platform defined constant +``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in `plat/common/aarch64/platform\_up\_stack.S`_ and +`plat/common/aarch64/platform\_mp\_stack.S`_ + +Function : platform\_get\_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned long + Return : unsigned long + +This function returns the base address of the normal memory stack that +has been allocated for the core specificed by MPIDR. For BL images that only +require a stack for the primary core the parameter is ignored. The size of +the stack allocated to each core is specified by the platform defined constant +``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in `plat/common/aarch64/platform\_up\_stack.S`_ and +`plat/common/aarch64/platform\_mp\_stack.S`_ + +Modifications for Power State Coordination Interface (in BL31) +-------------------------------------------------------------- + +The following functions must be implemented to initialize PSCI functionality in +the ARM Trusted Firmware. + +Function : plat\_get\_aff\_count() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, unsigned long + Return : unsigned int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary core. + +This function is called by the PSCI initialization code to detect the system +topology. Its purpose is to return the number of affinity instances implemented +at a given ``affinity level`` (specified by the first argument) and a given +``MPIDR`` (specified by the second argument). For example, on a dual-cluster +system where first cluster implements two cores and the second cluster +implements four cores, a call to this function with an ``MPIDR`` corresponding +to the first cluster (``0x0``) and affinity level 0, would return 2. A call +to this function with an ``MPIDR`` corresponding to the second cluster (``0x100``) +and affinity level 0, would return 4. + +Function : plat\_get\_aff\_state() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, unsigned long + Return : unsigned int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary core. + +This function is called by the PSCI initialization code. Its purpose is to +return the state of an affinity instance. The affinity instance is determined by +the affinity ID at a given ``affinity level`` (specified by the first argument) +and an ``MPIDR`` (specified by the second argument). The state can be one of +``PSCI_AFF_PRESENT`` or ``PSCI_AFF_ABSENT``. The latter state is used to cater for +system topologies where certain affinity instances are unimplemented. For +example, consider a platform that implements a single cluster with four cores and +another core implemented directly on the interconnect with the cluster. The +``MPIDR``\ s of the cluster would range from ``0x0-0x3``. The ``MPIDR`` of the single +core is 0x100 to indicate that it does not belong to cluster 0. Cluster 1 +is missing but needs to be accounted for to reach this single core in the +topology tree. Therefore it is marked as ``PSCI_AFF_ABSENT``. + +Function : platform\_setup\_pm() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const plat_pm_ops ** + Return : int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary core. + +This function is called by PSCI initialization code. Its purpose is to export +handler routines for platform-specific power management actions by populating +the passed pointer with a pointer to the private ``plat_pm_ops`` structure of +BL31. + +A description of each member of this structure is given below. A platform port +is expected to implement these handlers if the corresponding PSCI operation +is to be supported and these handlers are expected to succeed if the return +type is ``void``. + +plat\_pm\_ops.affinst\_standby() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Perform the platform-specific setup to enter the standby state indicated by the +passed argument. The generic code expects the handler to succeed. + +plat\_pm\_ops.affinst\_on() +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Perform the platform specific setup to power on an affinity instance, specified +by the ``MPIDR`` (first argument) and ``affinity level`` (third argument). The +``state`` (fourth argument) contains the current state of that affinity instance +(ON or OFF). This is useful to determine whether any action must be taken. For +example, while powering on a core, the cluster that contains this core might +already be in the ON state. The platform decides what actions must be taken to +transition from the current state to the target state (indicated by the power +management operation). The generic code expects the platform to return +E\_SUCCESS on success or E\_INTERN\_FAIL for any failure. + +plat\_pm\_ops.affinst\_off() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Perform the platform specific setup to power off an affinity instance of the +calling core. It is called by the PSCI ``CPU_OFF`` API implementation. + +The ``affinity level`` (first argument) and ``state`` (second argument) have +a similar meaning as described in the ``affinst_on()`` operation. They +identify the affinity instance on which the call is made and its +current state. This gives the platform port an indication of the +state transition it must make to perform the requested action. For example, if +the calling core is the last powered on core in the cluster, after powering down +affinity level 0 (the core), the platform port should power down affinity +level 1 (the cluster) as well. The generic code expects the handler to succeed. + +plat\_pm\_ops.affinst\_suspend() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Perform the platform specific setup to power off an affinity instance of the +calling core. It is called by the PSCI ``CPU_SUSPEND`` API and ``SYSTEM_SUSPEND`` +API implementation + +The ``affinity level`` (second argument) and ``state`` (third argument) have a +similar meaning as described in the ``affinst_on()`` operation. They are used to +identify the affinity instance on which the call is made and its current state. +This gives the platform port an indication of the state transition it must +make to perform the requested action. For example, if the calling core is the +last powered on core in the cluster, after powering down affinity level 0 +(the core), the platform port should power down affinity level 1 (the cluster) +as well. + +The difference between turning an affinity instance off and suspending it +is that in the former case, the affinity instance is expected to re-initialize +its state when it is next powered on (see ``affinst_on_finish()``). In the latter +case, the affinity instance is expected to save enough state so that it can +resume execution by restoring this state when it is powered on (see +``affinst_suspend_finish()``).The generic code expects the handler to succeed. + +plat\_pm\_ops.affinst\_on\_finish() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function is called by the PSCI implementation after the calling core is +powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. +It performs the platform-specific setup required to initialize enough state for +this core to enter the Normal world and also provide secure runtime firmware +services. + +The ``affinity level`` (first argument) and ``state`` (second argument) have a +similar meaning as described in the previous operations. The generic code +expects the handler to succeed. + +plat\_pm\_ops.affinst\_suspend\_finish() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function is called by the PSCI implementation after the calling core is +powered on and released from reset in response to an asynchronous wakeup +event, for example a timer interrupt that was programmed by the core during the +``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific +setup required to restore the saved state for this core to resume execution +in the Normal world and also provide secure runtime firmware services. + +The ``affinity level`` (first argument) and ``state`` (second argument) have a +similar meaning as described in the previous operations. The generic code +expects the platform to succeed. + +plat\_pm\_ops.validate\_power\_state() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function is called by the PSCI implementation during the ``CPU_SUSPEND`` +call to validate the ``power_state`` parameter of the PSCI API. If the +``power_state`` is known to be invalid, the platform must return +PSCI\_E\_INVALID\_PARAMS as an error, which is propagated back to the Normal +world PSCI client. + +plat\_pm\_ops.validate\_ns\_entrypoint() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function is called by the PSCI implementation during the ``CPU_SUSPEND``, +``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the Non-secure ``entry_point`` +parameter passed by the Normal world. If the ``entry_point`` is known to be +invalid, the platform must return PSCI\_E\_INVALID\_PARAMS as an error, which is +propagated back to the Normal world PSCI client. + +plat\_pm\_ops.get\_sys\_suspend\_power\_state() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` +call to return the ``power_state`` parameter. This allows the platform to encode +the appropriate State-ID field within the ``power_state`` parameter which can be +utilized in ``affinst_suspend()`` to suspend to system affinity level. The +``power_state`` parameter should be in the same format as specified by the +PSCI specification for the CPU\_SUSPEND API. + +-------------- + +*Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.* + +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _Porting Guide: porting-guide.rst#user-content-function--plat_my_core_pos +.. _psci pd tree: psci-pd-tree.rst +.. _plat/arm/board/fvp/fvp\_pm.c: ../plat/arm/board/fvp/fvp_pm.c +.. _38dce70f51fb83b27958ba3e2ad15f5635cb1061: https://github.com/ARM-software/arm-trusted-firmware/commit/38dce70f51fb83b27958ba3e2ad15f5635cb1061 +.. _plat/common/aarch64/platform\_up\_stack.S: ../plat/common/aarch64/platform_up_stack.S +.. _plat/common/aarch64/platform\_mp\_stack.S: ../plat/common/aarch64/platform_mp_stack.S + +.. |Image 1| image:: diagrams/psci-suspend-sequence.png?raw=true diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst new file mode 100644 index 0000000..66fe0f1 --- /dev/null +++ b/docs/porting-guide.rst @@ -0,0 +1,2599 @@ +ARM Trusted Firmware Porting Guide +================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +-------------- + +Introduction +------------ + +Please note that this document has been updated for the new platform API +as required by the PSCI v1.0 implementation. Please refer to the +`Migration Guide`_ for the previous platform API. + +Porting the ARM Trusted Firmware to a new platform involves making some +mandatory and optional modifications for both the cold and warm boot paths. +Modifications consist of: + +- Implementing a platform-specific function or variable, +- Setting up the execution context in a certain way, or +- Defining certain constants (for example #defines). + +The platform-specific functions and variables are declared in +`include/plat/common/platform.h`_. The firmware provides a default implementation +of variables and functions to fulfill the optional requirements. These +implementations are all weakly defined; they are provided to ease the porting +effort. Each platform port can override them with its own implementation if the +default implementation is inadequate. + +Platform ports that want to be aligned with standard ARM platforms (for example +FVP and Juno) may also use `include/plat/arm/common/plat\_arm.h`_ and the +corresponding source files in ``plat/arm/common/``. These provide standard +implementations for some of the required platform porting functions. However, +using these functions requires the platform port to implement additional +ARM standard platform porting functions. These additional functions are not +documented here. + +Some modifications are common to all Boot Loader (BL) stages. Section 2 +discusses these in detail. The subsequent sections discuss the remaining +modifications for each BL stage in detail. + +This document should be read in conjunction with the ARM Trusted Firmware +`User Guide`_. + +Common modifications +-------------------- + +This section covers the modifications that should be made by the platform for +each BL stage to correctly port the firmware stack. They are categorized as +either mandatory or optional. + +Common mandatory modifications +------------------------------ + +A platform port must enable the Memory Management Unit (MMU) as well as the +instruction and data caches for each BL stage. Setting up the translation +tables is the responsibility of the platform port because memory maps differ +across platforms. A memory translation library (see ``lib/xlat_tables/``) is +provided to help in this setup. Note that although this library supports +non-identity mappings, this is intended only for re-mapping peripheral physical +addresses and allows platforms with high I/O addresses to reduce their virtual +address space. All other addresses corresponding to code and data must currently +use an identity mapping. + +In ARM standard platforms, each BL stage configures the MMU in the +platform-specific architecture setup function, ``blX_plat_arch_setup()``, and uses +an identity mapping for all addresses. + +If the build option ``USE_COHERENT_MEM`` is enabled, each platform can allocate a +block of identity mapped secure memory with Device-nGnRE attributes aligned to +page boundary (4K) for each BL stage. All sections which allocate coherent +memory are grouped under ``coherent_ram``. For ex: Bakery locks are placed in a +section identified by name ``bakery_lock`` inside ``coherent_ram`` so that its +possible for the firmware to place variables in it using the following C code +directive: + +:: + + __section("bakery_lock") + +Or alternatively the following assembler code directive: + +:: + + .section bakery_lock + +The ``coherent_ram`` section is a sum of all sections like ``bakery_lock`` which are +used to allocate any data structures that are accessed both when a CPU is +executing with its MMU and caches enabled, and when it's running with its MMU +and caches disabled. Examples are given below. + +The following variables, functions and constants must be defined by the platform +for the firmware to work correctly. + +File : platform\_def.h [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure that a header file of this name is in the system +include path with the following constants defined. This may require updating the +list of ``PLAT_INCLUDES`` in the ``platform.mk`` file. In the ARM development +platforms, this file is found in ``plat/arm/board//include/``. + +Platform ports may optionally use the file `include/plat/common/common\_def.h`_, +which provides typical values for some of the constants below. These values are +likely to be suitable for all platform ports. + +Platform ports that want to be aligned with standard ARM platforms (for example +FVP and Juno) may also use `include/plat/arm/common/arm\_def.h`_, which provides +standard values for some of the constants below. However, this requires the +platform port to define additional platform porting constants in +``platform_def.h``. These additional constants are not documented here. + +- **#define : PLATFORM\_LINKER\_FORMAT** + + Defines the linker format used by the platform, for example + ``elf64-littleaarch64``. + +- **#define : PLATFORM\_LINKER\_ARCH** + + Defines the processor architecture for the linker by the platform, for + example ``aarch64``. + +- **#define : PLATFORM\_STACK\_SIZE** + + Defines the normal stack memory available to each CPU. This constant is used + by `plat/common/aarch64/platform\_mp\_stack.S`_ and + `plat/common/aarch64/platform\_up\_stack.S`_. + +- **define : CACHE\_WRITEBACK\_GRANULE** + + Defines the size in bits of the largest cache line across all the cache + levels in the platform. + +- **#define : FIRMWARE\_WELCOME\_STR** + + Defines the character string printed by BL1 upon entry into the ``bl1_main()`` + function. + +- **#define : PLATFORM\_CORE\_COUNT** + + Defines the total number of CPUs implemented by the platform across all + clusters in the system. + +- **#define : PLAT\_NUM\_PWR\_DOMAINS** + + Defines the total number of nodes in the power domain topology + tree at all the power domain levels used by the platform. + This macro is used by the PSCI implementation to allocate + data structures to represent power domain topology. + +- **#define : PLAT\_MAX\_PWR\_LVL** + + Defines the maximum power domain level that the power management operations + should apply to. More often, but not always, the power domain level + corresponds to affinity level. This macro allows the PSCI implementation + to know the highest power domain level that it should consider for power + management operations in the system that the platform implements. For + example, the Base AEM FVP implements two clusters with a configurable + number of CPUs and it reports the maximum power domain level as 1. + +- **#define : PLAT\_MAX\_OFF\_STATE** + + Defines the local power state corresponding to the deepest power down + possible at every power domain level in the platform. The local power + states for each level may be sparsely allocated between 0 and this value + with 0 being reserved for the RUN state. The PSCI implementation uses this + value to initialize the local power states of the power domain nodes and + to specify the requested power state for a PSCI\_CPU\_OFF call. + +- **#define : PLAT\_MAX\_RET\_STATE** + + Defines the local power state corresponding to the deepest retention state + possible at every power domain level in the platform. This macro should be + a value less than PLAT\_MAX\_OFF\_STATE and greater than 0. It is used by the + PSCI implementation to distinguish between retention and power down local + power states within PSCI\_CPU\_SUSPEND call. + +- **#define : PLAT\_MAX\_PWR\_LVL\_STATES** + + Defines the maximum number of local power states per power domain level + that the platform supports. The default value of this macro is 2 since + most platforms just support a maximum of two local power states at each + power domain level (power-down and retention). If the platform needs to + account for more local power states, then it must redefine this macro. + + Currently, this macro is used by the Generic PSCI implementation to size + the array used for PSCI\_STAT\_COUNT/RESIDENCY accounting. + +- **#define : BL1\_RO\_BASE** + + Defines the base address in secure ROM where BL1 originally lives. Must be + aligned on a page-size boundary. + +- **#define : BL1\_RO\_LIMIT** + + Defines the maximum address in secure ROM that BL1's actual content (i.e. + excluding any data section allocated at runtime) can occupy. + +- **#define : BL1\_RW\_BASE** + + Defines the base address in secure RAM where BL1's read-write data will live + at runtime. Must be aligned on a page-size boundary. + +- **#define : BL1\_RW\_LIMIT** + + Defines the maximum address in secure RAM that BL1's read-write data can + occupy at runtime. + +- **#define : BL2\_BASE** + + Defines the base address in secure RAM where BL1 loads the BL2 binary image. + Must be aligned on a page-size boundary. + +- **#define : BL2\_LIMIT** + + Defines the maximum address in secure RAM that the BL2 image can occupy. + +- **#define : BL31\_BASE** + + Defines the base address in secure RAM where BL2 loads the BL31 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL31\_LIMIT** + + Defines the maximum address in secure RAM that the BL31 image can occupy. + +For every image, the platform must define individual identifiers that will be +used by BL1 or BL2 to load the corresponding image into memory from non-volatile +storage. For the sake of performance, integer numbers will be used as +identifiers. The platform will use those identifiers to return the relevant +information about the image to be loaded (file handler, load address, +authentication information, etc.). The following image identifiers are +mandatory: + +- **#define : BL2\_IMAGE\_ID** + + BL2 image identifier, used by BL1 to load BL2. + +- **#define : BL31\_IMAGE\_ID** + + BL31 image identifier, used by BL2 to load BL31. + +- **#define : BL33\_IMAGE\_ID** + + BL33 image identifier, used by BL2 to load BL33. + +If Trusted Board Boot is enabled, the following certificate identifiers must +also be defined: + +- **#define : TRUSTED\_BOOT\_FW\_CERT\_ID** + + BL2 content certificate identifier, used by BL1 to load the BL2 content + certificate. + +- **#define : TRUSTED\_KEY\_CERT\_ID** + + Trusted key certificate identifier, used by BL2 to load the trusted key + certificate. + +- **#define : SOC\_FW\_KEY\_CERT\_ID** + + BL31 key certificate identifier, used by BL2 to load the BL31 key + certificate. + +- **#define : SOC\_FW\_CONTENT\_CERT\_ID** + + BL31 content certificate identifier, used by BL2 to load the BL31 content + certificate. + +- **#define : NON\_TRUSTED\_FW\_KEY\_CERT\_ID** + + BL33 key certificate identifier, used by BL2 to load the BL33 key + certificate. + +- **#define : NON\_TRUSTED\_FW\_CONTENT\_CERT\_ID** + + BL33 content certificate identifier, used by BL2 to load the BL33 content + certificate. + +- **#define : FWU\_CERT\_ID** + + Firmware Update (FWU) certificate identifier, used by NS\_BL1U to load the + FWU content certificate. + +- **#define : PLAT\_CRYPTOCELL\_BASE** + + This defines the base address of ARM® TrustZone® CryptoCell and must be + defined if CryptoCell crypto driver is used for Trusted Board Boot. For + capable ARM platforms, this driver is used if ``ARM_CRYPTOCELL_INTEG`` is + set. + +If the AP Firmware Updater Configuration image, BL2U is used, the following +must also be defined: + +- **#define : BL2U\_BASE** + + Defines the base address in secure memory where BL1 copies the BL2U binary + image. Must be aligned on a page-size boundary. + +- **#define : BL2U\_LIMIT** + + Defines the maximum address in secure memory that the BL2U image can occupy. + +- **#define : BL2U\_IMAGE\_ID** + + BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to BL2U. + +If the SCP Firmware Update Configuration Image, SCP\_BL2U is used, the following +must also be defined: + +- **#define : SCP\_BL2U\_IMAGE\_ID** + + SCP\_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to SCP\_BL2U. + NOTE: TF does not provide source code for this image. + +If the Non-Secure Firmware Updater ROM, NS\_BL1U is used, the following must +also be defined: + +- **#define : NS\_BL1U\_BASE** + + Defines the base address in non-secure ROM where NS\_BL1U executes. + Must be aligned on a page-size boundary. + NOTE: TF does not provide source code for this image. + +- **#define : NS\_BL1U\_IMAGE\_ID** + + NS\_BL1U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS\_BL1U. + +If the Non-Secure Firmware Updater, NS\_BL2U is used, the following must also +be defined: + +- **#define : NS\_BL2U\_BASE** + + Defines the base address in non-secure memory where NS\_BL2U executes. + Must be aligned on a page-size boundary. + NOTE: TF does not provide source code for this image. + +- **#define : NS\_BL2U\_IMAGE\_ID** + + NS\_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS\_BL2U. + +For the the Firmware update capability of TRUSTED BOARD BOOT, the following +macros may also be defined: + +- **#define : PLAT\_FWU\_MAX\_SIMULTANEOUS\_IMAGES** + + Total number of images that can be loaded simultaneously. If the platform + doesn't specify any value, it defaults to 10. + +If a SCP\_BL2 image is supported by the platform, the following constants must +also be defined: + +- **#define : SCP\_BL2\_IMAGE\_ID** + + SCP\_BL2 image identifier, used by BL2 to load SCP\_BL2 into secure memory + from platform storage before being transfered to the SCP. + +- **#define : SCP\_FW\_KEY\_CERT\_ID** + + SCP\_BL2 key certificate identifier, used by BL2 to load the SCP\_BL2 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : SCP\_FW\_CONTENT\_CERT\_ID** + + SCP\_BL2 content certificate identifier, used by BL2 to load the SCP\_BL2 + content certificate (mandatory when Trusted Board Boot is enabled). + +If a BL32 image is supported by the platform, the following constants must +also be defined: + +- **#define : BL32\_IMAGE\_ID** + + BL32 image identifier, used by BL2 to load BL32. + +- **#define : TRUSTED\_OS\_FW\_KEY\_CERT\_ID** + + BL32 key certificate identifier, used by BL2 to load the BL32 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : TRUSTED\_OS\_FW\_CONTENT\_CERT\_ID** + + BL32 content certificate identifier, used by BL2 to load the BL32 content + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : BL32\_BASE** + + Defines the base address in secure memory where BL2 loads the BL32 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL32\_LIMIT** + + Defines the maximum address that the BL32 image can occupy. + +If the Test Secure-EL1 Payload (TSP) instantiation of BL32 is supported by the +platform, the following constants must also be defined: + +- **#define : TSP\_SEC\_MEM\_BASE** + + Defines the base address of the secure memory used by the TSP image on the + platform. This must be at the same address or below ``BL32_BASE``. + +- **#define : TSP\_SEC\_MEM\_SIZE** + + Defines the size of the secure memory used by the BL32 image on the + platform. ``TSP_SEC_MEM_BASE`` and ``TSP_SEC_MEM_SIZE`` must fully accomodate + the memory required by the BL32 image, defined by ``BL32_BASE`` and + ``BL32_LIMIT``. + +- **#define : TSP\_IRQ\_SEC\_PHY\_TIMER** + + Defines the ID of the secure physical generic timer interrupt used by the + TSP's interrupt handling code. + +If the platform port uses the translation table library code, the following +constants must also be defined: + +- **#define : PLAT\_XLAT\_TABLES\_DYNAMIC** + + Optional flag that can be set per-image to enable the dynamic allocation of + regions even when the MMU is enabled. If not defined, only static + functionality will be available, if defined and set to 1 it will also + include the dynamic functionality. + +- **#define : MAX\_XLAT\_TABLES** + + Defines the maximum number of translation tables that are allocated by the + translation table library code. To minimize the amount of runtime memory + used, choose the smallest value needed to map the required virtual addresses + for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is enabled for a BL + image, ``MAX_XLAT_TABLES`` must be defined to accommodate the dynamic regions + as well. + +- **#define : MAX\_MMAP\_REGIONS** + + Defines the maximum number of regions that are allocated by the translation + table library code. A region consists of physical base address, virtual base + address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as + defined in the ``mmap_region_t`` structure. The platform defines the regions + that should be mapped. Then, the translation table library will create the + corresponding tables and descriptors at runtime. To minimize the amount of + runtime memory used, choose the smallest value needed to register the + required regions for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is + enabled for a BL image, ``MAX_MMAP_REGIONS`` must be defined to accommodate + the dynamic regions as well. + +- **#define : ADDR\_SPACE\_SIZE** + + Defines the total size of the address space in bytes. For example, for a 32 + bit address space, this value should be ``(1ull << 32)``. This definition is + now deprecated, platforms should use ``PLAT_PHY_ADDR_SPACE_SIZE`` and + ``PLAT_VIRT_ADDR_SPACE_SIZE`` instead. + +- **#define : PLAT\_VIRT\_ADDR\_SPACE\_SIZE** + + Defines the total size of the virtual address space in bytes. For example, + for a 32 bit virtual address space, this value should be ``(1ull << 32)``. + +- **#define : PLAT\_PHY\_ADDR\_SPACE\_SIZE** + + Defines the total size of the physical address space in bytes. For example, + for a 32 bit physical address space, this value should be ``(1ull << 32)``. + +If the platform port uses the IO storage framework, the following constants +must also be defined: + +- **#define : MAX\_IO\_DEVICES** + + Defines the maximum number of registered IO devices. Attempting to register + more devices than this value using ``io_register_device()`` will fail with + -ENOMEM. + +- **#define : MAX\_IO\_HANDLES** + + Defines the maximum number of open IO handles. Attempting to open more IO + entities than this value using ``io_open()`` will fail with -ENOMEM. + +- **#define : MAX\_IO\_BLOCK\_DEVICES** + + Defines the maximum number of registered IO block devices. Attempting to + register more devices this value using ``io_dev_open()`` will fail + with -ENOMEM. MAX\_IO\_BLOCK\_DEVICES should be less than MAX\_IO\_DEVICES. + With this macro, multiple block devices could be supported at the same + time. + +If the platform needs to allocate data within the per-cpu data framework in +BL31, it should define the following macro. Currently this is only required if +the platform decides not to use the coherent memory section by undefining the +``USE_COHERENT_MEM`` build flag. In this case, the framework allocates the +required memory within the the per-cpu data to minimize wastage. + +- **#define : PLAT\_PCPU\_DATA\_SIZE** + + Defines the memory (in bytes) to be reserved within the per-cpu data + structure for use by the platform layer. + +The following constants are optional. They should be defined when the platform +memory layout implies some image overlaying like in ARM standard platforms. + +- **#define : BL31\_PROGBITS\_LIMIT** + + Defines the maximum address in secure RAM that the BL31's progbits sections + can occupy. + +- **#define : TSP\_PROGBITS\_LIMIT** + + Defines the maximum address that the TSP's progbits sections can occupy. + +If the platform port uses the PL061 GPIO driver, the following constant may +optionally be defined: + +- **PLAT\_PL061\_MAX\_GPIOS** + Maximum number of GPIOs required by the platform. This allows control how + much memory is allocated for PL061 GPIO controllers. The default value is + + #. $(eval $(call add\_define,PLAT\_PL061\_MAX\_GPIOS)) + +If the platform port uses the partition driver, the following constant may +optionally be defined: + +- **PLAT\_PARTITION\_MAX\_ENTRIES** + Maximum number of partition entries required by the platform. This allows + control how much memory is allocated for partition entries. The default + value is 128. + `For example, define the build flag in platform.mk`_: + PLAT\_PARTITION\_MAX\_ENTRIES := 12 + $(eval $(call add\_define,PLAT\_PARTITION\_MAX\_ENTRIES)) + +The following constant is optional. It should be defined to override the default +behaviour of the ``assert()`` function (for example, to save memory). + +- **PLAT\_LOG\_LEVEL\_ASSERT** + If ``PLAT_LOG_LEVEL_ASSERT`` is higher or equal than ``LOG_LEVEL_VERBOSE``, + ``assert()`` prints the name of the file, the line number and the asserted + expression. Else if it is higher than ``LOG_LEVEL_INFO``, it prints the file + name and the line number. Else if it is lower than ``LOG_LEVEL_INFO``, it + doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't + defined, it defaults to ``LOG_LEVEL``. + +File : plat\_macros.S [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure a file of this name is in the system include path with +the following macro defined. In the ARM development platforms, this file is +found in ``plat/arm/board//include/plat_macros.S``. + +- **Macro : plat\_crash\_print\_regs** + + This macro allows the crash reporting routine to print relevant platform + registers in case of an unhandled exception in BL31. This aids in debugging + and this macro can be defined to be empty in case register reporting is not + desired. + + For instance, GIC or interconnect registers may be helpful for + troubleshooting. + +Handling Reset +-------------- + +BL1 by default implements the reset vector where execution starts from a cold +or warm boot. BL31 can be optionally set as a reset vector using the +``RESET_TO_BL31`` make variable. + +For each CPU, the reset vector code is responsible for the following tasks: + +#. Distinguishing between a cold boot and a warm boot. + +#. In the case of a cold boot and the CPU being a secondary CPU, ensuring that + the CPU is placed in a platform-specific state until the primary CPU + performs the necessary steps to remove it from this state. + +#. In the case of a warm boot, ensuring that the CPU jumps to a platform- + specific address in the BL31 image in the same processor mode as it was + when released from reset. + +The following functions need to be implemented by the platform port to enable +reset vector code to perform the above tasks. + +Function : plat\_get\_my\_entrypoint() [mandatory when PROGRAMMABLE\_RESET\_ADDRESS == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function is called with the MMU and caches disabled +(``SCTLR_EL3.M`` = 0 and ``SCTLR_EL3.C`` = 0). The function is responsible for +distinguishing between a warm and cold reset for the current CPU using +platform-specific means. If it's a warm reset, then it returns the warm +reset entrypoint point provided to ``plat_setup_psci_ops()`` during +BL31 initialization. If it's a cold reset then this function must return zero. + +This function does not follow the Procedure Call Standard used by the +Application Binary Interface for the ARM 64-bit architecture. The caller should +not assume that callee saved registers are preserved across a call to this +function. + +This function fulfills requirement 1 and 3 listed above. + +Note that for platforms that support programming the reset address, it is +expected that a CPU will start executing code directly at the right address, +both on a cold and warm reset. In this case, there is no need to identify the +type of reset nor to query the warm reset entrypoint. Therefore, implementing +this function is not required on such platforms. + +Function : plat\_secondary\_cold\_boot\_setup() [mandatory when COLD\_BOOT\_SINGLE\_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + +This function is called with the MMU and data caches disabled. It is responsible +for placing the executing secondary CPU in a platform-specific state until the +primary CPU performs the necessary actions to bring it out of that state and +allow entry into the OS. This function must not return. + +In the ARM FVP port, when using the normal boot flow, each secondary CPU powers +itself off. The primary CPU is responsible for powering up the secondary CPUs +when normal world software requires them. When booting an EL3 payload instead, +they stay powered on and are put in a holding pen until their mailbox gets +populated. + +This function fulfills requirement 2 above. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, implementing this +function is not required on such platforms. + +Function : plat\_is\_my\_cpu\_primary() [mandatory when COLD\_BOOT\_SINGLE\_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function identifies whether the current CPU is the primary CPU or a +secondary CPU. A return value of zero indicates that the CPU is not the +primary CPU, while a non-zero return value indicates that the CPU is the +primary CPU. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, there is no need to +distinguish between primary and secondary CPUs and implementing this function is +not required. + +Function : platform\_mem\_init() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called before any access to data is made by the firmware, in +order to carry out any essential memory initialization. + +Function: plat\_get\_rotpk\_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, void **, unsigned int *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns a +pointer to the ROTPK stored in the platform (or a hash of it) and its length. +The ROTPK must be encoded in DER format according to the following ASN.1 +structure: + +:: + + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL + } + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING + } + +In case the function returns a hash of the key: + +:: + + DigestInfo ::= SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING + } + +The function returns 0 on success. Any other value is treated as error by the +Trusted Board Boot. The function also reports extra information related +to the ROTPK in the flags parameter: + +:: + + ROTPK_IS_HASH : Indicates that the ROTPK returned by the platform is a + hash. + ROTPK_NOT_DEPLOYED : This allows the platform to skip certificate ROTPK + verification while the platform ROTPK is not deployed. + When this flag is set, the function does not need to + return a platform ROTPK, and the authentication + framework uses the ROTPK in the certificate without + verifying it against the platform value. This flag + must not be used in a deployed production environment. + +Function: plat\_get\_nv\_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns the +non-volatile counter value stored in the platform in the second argument. The +cookie in the first argument may be used to select the counter in case the +platform provides more than one (for example, on platforms that use the default +TBBR CoT, the cookie will correspond to the OID values defined in +TRUSTED\_FW\_NVCOUNTER\_OID or NON\_TRUSTED\_FW\_NVCOUNTER\_OID). + +The function returns 0 on success. Any other value means the counter value could +not be retrieved from the platform. + +Function: plat\_set\_nv\_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It sets a new +counter value in the platform. The cookie in the first argument may be used to +select the counter (as explained in plat\_get\_nv\_ctr()). The second argument is +the updated counter value to be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value could +not be updated. + +Function: plat\_set\_nv\_ctr2() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, const auth_img_desc_t *, unsigned int + Return : int + +This function is optional when Trusted Board Boot is enabled. If this +interface is defined, then ``plat_set_nv_ctr()`` need not be defined. The +first argument passed is a cookie and is typically used to +differentiate between a Non Trusted NV Counter and a Trusted NV +Counter. The second argument is a pointer to an authentication image +descriptor and may be used to decide if the counter is allowed to be +updated or not. The third argument is the updated counter value to +be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value +either could not be updated or the authentication image descriptor indicates +that it is not allowed to be updated. + +Common mandatory function modifications +--------------------------------------- + +The following functions are mandatory functions which need to be implemented +by the platform port. + +Function : plat\_my\_core\_pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This funtion returns the index of the calling CPU which is used as a +CPU-specific linear index into blocks of memory (for example while allocating +per-CPU stacks). This function will be invoked very early in the +initialization sequence which mandates that this function should be +implemented in assembly and should not rely on the avalability of a C +runtime environment. This function can clobber x0 - x8 and must preserve +x9 - x29. + +This function plays a crucial role in the power domain topology framework in +PSCI and details of this can be found in `Power Domain Topology Design`_. + +Function : plat\_core\_pos\_by\_mpidr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int + +This function validates the ``MPIDR`` of a CPU and converts it to an index, +which can be used as a CPU-specific linear index into blocks of memory. In +case the ``MPIDR`` is invalid, this function returns -1. This function will only +be invoked by BL31 after the power domain topology is initialized and can +utilize the C runtime environment. For further details about how ARM Trusted +Firmware represents the power domain topology and how this relates to the +linear CPU index, please refer `Power Domain Topology Design`_. + +Common optional modifications +----------------------------- + +The following are helper functions implemented by the firmware that perform +common platform-specific tasks. A platform may choose to override these +definitions. + +Function : plat\_set\_my\_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function sets the current stack pointer to the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in `plat/common/aarch64/platform\_up\_stack.S`_ and +`plat/common/aarch64/platform\_mp\_stack.S`_ + +Function : plat\_get\_my\_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function returns the base address of the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in `plat/common/aarch64/platform\_up\_stack.S`_ and +`plat/common/aarch64/platform\_mp\_stack.S`_ + +Function : plat\_report\_exception() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +A platform may need to report various information about its status when an +exception is taken, for example the current exception level, the CPU security +state (secure/non-secure), the exception type, and so on. This function is +called in the following circumstances: + +- In BL1, whenever an exception is taken. +- In BL2, whenever an exception is taken. + +The default implementation doesn't do anything, to avoid making assumptions +about the way the platform displays its status information. + +For AArch64, this function receives the exception type as its argument. +Possible values for exceptions types are listed in the +`include/common/bl\_common.h`_ header file. Note that these constants are not +related to any architectural exception code; they are just an ARM Trusted +Firmware convention. + +For AArch32, this function receives the exception mode as its argument. +Possible values for exception modes are listed in the +`include/lib/aarch32/arch.h`_ header file. + +Function : plat\_reset\_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +A platform may need to do additional initialization after reset. This function +allows the platform to do the platform specific intializations. Platform +specific errata workarounds could also be implemented here. The api should +preserve the values of callee saved registers x19 to x29. + +The default implementation doesn't do anything. If a platform needs to override +the default implementation, refer to the `Firmware Design`_ for general +guidelines. + +Function : plat\_disable\_acp() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This api allows a platform to disable the Accelerator Coherency Port (if +present) during a cluster power down sequence. The default weak implementation +doesn't do anything. Since this api is called during the power down sequence, +it has restrictions for stack usage and it can use the registers x0 - x17 as +scratch registers. It should preserve the value in x18 register as it is used +by the caller to store the return address. + +Function : plat\_error\_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : void + +This API is called when the generic code encounters an error situation from +which it cannot continue. It allows the platform to perform error reporting or +recovery actions (for example, reset the system). This function must not return. + +The parameter indicates the type of error using standard codes from ``errno.h``. +Possible errors reported by the generic code are: + +- ``-EAUTH``: a certificate or image could not be authenticated (when Trusted + Board Boot is enabled) +- ``-ENOENT``: the requested image or certificate could not be found or an IO + error was detected +- ``-ENOMEM``: resources exhausted. Trusted Firmware does not use dynamic + memory, so this error is usually an indication of an incorrect array size + +The default implementation simply spins. + +Function : plat\_panic\_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API is called when the generic code encounters an unexpected error +situation from which it cannot recover. This function must not return, +and must be implemented in assembly because it may be called before the C +environment is initialized. + +Note: The address from where it was called is stored in x30 (Link Register). +The default implementation simply spins. + +Function : plat\_get\_bl\_image\_load\_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_load_info_t * + +This function returns pointer to the list of images that the platform has +populated to load. This function is currently invoked in BL2 to load the +BL3xx images, when LOAD\_IMAGE\_V2 is enabled. + +Function : plat\_get\_next\_bl\_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_params_t * + +This function returns a pointer to the shared memory that the platform has +kept aside to pass trusted firmware related information that next BL image +needs. This function is currently invoked in BL2 to pass this information to +the next BL image, when LOAD\_IMAGE\_V2 is enabled. + +Function : plat\_get\_stack\_protector\_canary() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : u_register_t + +This function returns a random value that is used to initialize the canary used +when the stack protector is enabled with ENABLE\_STACK\_PROTECTOR. A predictable +value will weaken the protection as the attacker could easily write the right +value as part of the attack most of the time. Therefore, it should return a +true random number. + +Note: For the protection to be effective, the global data need to be placed at +a lower address than the stack bases. Failure to do so would allow an attacker +to overwrite the canary as part of the stack buffer overflow attack. + +Function : plat\_flush\_next\_bl\_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function flushes to main memory all the image params that are passed to +next image. This function is currently invoked in BL2 to flush this information +to the next BL image, when LOAD\_IMAGE\_V2 is enabled. + +Modifications specific to a Boot Loader stage +--------------------------------------------- + +Boot Loader Stage 1 (BL1) +------------------------- + +BL1 implements the reset vector where execution starts from after a cold or +warm boot. For each CPU, BL1 is responsible for the following tasks: + +#. Handling the reset as described in section 2.2 + +#. In the case of a cold boot and the CPU being the primary CPU, ensuring that + only this CPU executes the remaining BL1 code, including loading and passing + control to the BL2 stage. + +#. Identifying and starting the Firmware Update process (if required). + +#. Loading the BL2 image from non-volatile storage into secure memory at the + address specified by the platform defined constant ``BL2_BASE``. + +#. Populating a ``meminfo`` structure with the following information in memory, + accessible by BL2 immediately upon entry. + + :: + + meminfo.total_base = Base address of secure RAM visible to BL2 + meminfo.total_size = Size of secure RAM visible to BL2 + meminfo.free_base = Base address of secure RAM available for + allocation to BL2 + meminfo.free_size = Size of secure RAM available for allocation to BL2 + + BL1 places this ``meminfo`` structure at the beginning of the free memory + available for its use. Since BL1 cannot allocate memory dynamically at the + moment, its free memory will be available for BL2's use as-is. However, this + means that BL2 must read the ``meminfo`` structure before it starts using its + free memory (this is discussed in Section 3.2). + + In future releases of the ARM Trusted Firmware it will be possible for + the platform to decide where it wants to place the ``meminfo`` structure for + BL2. + + BL1 implements the ``bl1_init_bl2_mem_layout()`` function to populate the + BL2 ``meminfo`` structure. The platform may override this implementation, for + example if the platform wants to restrict the amount of memory visible to + BL2. Details of how to do this are given below. + +The following functions need to be implemented by the platform port to enable +BL1 to perform the above tasks. + +Function : bl1\_early\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +On ARM standard platforms, this function: + +- Enables a secure instance of SP805 to act as the Trusted Watchdog. + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL1. + +- Enables issuing of snoop and DVM (Distributed Virtual Memory) requests to + the CCI slave interface corresponding to the cluster that includes the + primary CPU. + +Function : bl1\_plat\_arch\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs any platform-specific and architectural setup that the +platform requires. Platform-specific setup might include configuration of +memory controllers and the interconnect. + +In ARM standard platforms, this function enables the MMU. + +This function helps fulfill requirement 2 above. + +Function : bl1\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches enabled. It is responsible +for performing any remaining platform-specific setup that can occur after the +MMU and data cache have been enabled. + +In ARM standard platforms, this function initializes the storage abstraction +layer used to load the next bootloader image. + +This function helps fulfill requirement 4 above. + +Function : bl1\_plat\_sec\_mem\_layout() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : meminfo * + +This function should only be called on the cold boot path. It executes with the +MMU and data caches enabled. The pointer returned by this function must point to +a ``meminfo`` structure containing the extents and availability of secure RAM for +the BL1 stage. + +:: + + meminfo.total_base = Base address of secure RAM visible to BL1 + meminfo.total_size = Size of secure RAM visible to BL1 + meminfo.free_base = Base address of secure RAM available for allocation + to BL1 + meminfo.free_size = Size of secure RAM available for allocation to BL1 + +This information is used by BL1 to load the BL2 image in secure RAM. BL1 also +populates a similar structure to tell BL2 the extents of memory available for +its own use. + +This function helps fulfill requirements 4 and 5 above. + +Function : bl1\_init\_bl2\_mem\_layout() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo *, meminfo * + Return : void + +BL1 needs to tell the next stage the amount of secure RAM available +for it to use. This information is populated in a ``meminfo`` +structure. + +Depending upon where BL2 has been loaded in secure RAM (determined by +``BL2_BASE``), BL1 calculates the amount of free memory available for BL2 to use. +BL1 also ensures that its data sections resident in secure RAM are not visible +to BL2. An illustration of how this is done in ARM standard platforms is given +in the **Memory layout on ARM development platforms** section in the +`Firmware Design`_. + +Function : bl1\_plat\_prepare\_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t * + Return : void + +This function is called prior to exiting BL1 in response to the +``BL1_SMC_RUN_IMAGE`` SMC request raised by BL2. It should be used to perform +platform specific clean up or bookkeeping operations before transferring +control to the next image. It receives the address of the ``entry_point_info_t`` +structure passed from BL2. This function runs with MMU disabled. + +Function : bl1\_plat\_set\_ep\_info() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, entry_point_info_t *ep_info + Return : void + +This function allows platforms to override ``ep_info`` for the given ``image_id``. + +The default implementation just returns. + +Function : bl1\_plat\_get\_next\_image\_id() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This and the following function must be overridden to enable the FWU feature. + +BL1 calls this function after platform setup to identify the next image to be +loaded and executed. If the platform returns ``BL2_IMAGE_ID`` then BL1 proceeds +with the normal boot sequence, which loads and executes BL2. If the platform +returns a different image id, BL1 assumes that Firmware Update is required. + +The default implementation always returns ``BL2_IMAGE_ID``. The ARM development +platforms override this function to detect if firmware update is required, and +if so, return the first image in the firmware update process. + +Function : bl1\_plat\_get\_image\_desc() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : image_desc_t * + +BL1 calls this function to get the image descriptor information ``image_desc_t`` +for the provided ``image_id`` from the platform. + +The default implementation always returns a common BL2 image descriptor. ARM +standard platforms return an image descriptor corresponding to BL2 or one of +the firmware update images defined in the Trusted Board Boot Requirements +specification. + +Function : bl1\_plat\_fwu\_done() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, uintptr_t image_src, + unsigned int image_size + Return : void + +BL1 calls this function when the FWU process is complete. It must not return. +The platform may override this function to take platform specific action, for +example to initiate the normal boot flow. + +The default implementation spins forever. + +Function : bl1\_plat\_mem\_check() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t mem_base, unsigned int mem_size, + unsigned int flags + Return : int + +BL1 calls this function while handling FWU related SMCs, more specifically when +copying or authenticating an image. Its responsibility is to ensure that the +region of memory identified by ``mem_base`` and ``mem_size`` is mapped in BL1, and +that this memory corresponds to either a secure or non-secure memory region as +indicated by the security state of the ``flags`` argument. + +This function can safely assume that the value resulting from the addition of +``mem_base`` and ``mem_size`` fits into a ``uintptr_t`` type variable and does not +overflow. + +This function must return 0 on success, a non-null error code otherwise. + +The default implementation of this function asserts therefore platforms must +override it when using the FWU feature. + +Boot Loader Stage 2 (BL2) +------------------------- + +The BL2 stage is executed only by the primary CPU, which is determined in BL1 +using the ``platform_is_primary_cpu()`` function. BL1 passed control to BL2 at +``BL2_BASE``. BL2 executes in Secure EL1 and is responsible for: + +#. (Optional) Loading the SCP\_BL2 binary image (if present) from platform + provided non-volatile storage. To load the SCP\_BL2 image, BL2 makes use of + the ``meminfo`` returned by the ``bl2_plat_get_scp_bl2_meminfo()`` function. + The platform also defines the address in memory where SCP\_BL2 is loaded + through the optional constant ``SCP_BL2_BASE``. BL2 uses this information + to determine if there is enough memory to load the SCP\_BL2 image. + Subsequent handling of the SCP\_BL2 image is platform-specific and is + implemented in the ``bl2_plat_handle_scp_bl2()`` function. + If ``SCP_BL2_BASE`` is not defined then this step is not performed. + +#. Loading the BL31 binary image into secure RAM from non-volatile storage. To + load the BL31 image, BL2 makes use of the ``meminfo`` structure passed to it + by BL1. This structure allows BL2 to calculate how much secure RAM is + available for its use. The platform also defines the address in secure RAM + where BL31 is loaded through the constant ``BL31_BASE``. BL2 uses this + information to determine if there is enough memory to load the BL31 image. + +#. (Optional) Loading the BL32 binary image (if present) from platform + provided non-volatile storage. To load the BL32 image, BL2 makes use of + the ``meminfo`` returned by the ``bl2_plat_get_bl32_meminfo()`` function. + The platform also defines the address in memory where BL32 is loaded + through the optional constant ``BL32_BASE``. BL2 uses this information + to determine if there is enough memory to load the BL32 image. + If ``BL32_BASE`` is not defined then this and the next step is not performed. + +#. (Optional) Arranging to pass control to the BL32 image (if present) that + has been pre-loaded at ``BL32_BASE``. BL2 populates an ``entry_point_info`` + structure in memory provided by the platform with information about how + BL31 should pass control to the BL32 image. + +#. (Optional) Loading the normal world BL33 binary image (if not loaded by + other means) into non-secure DRAM from platform storage and arranging for + BL31 to pass control to this image. This address is determined using the + ``plat_get_ns_image_entrypoint()`` function described below. + +#. BL2 populates an ``entry_point_info`` structure in memory provided by the + platform with information about how BL31 should pass control to the + other BL images. + +The following functions must be implemented by the platform port to enable BL2 +to perform the above tasks. + +Function : bl2\_early\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo * + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. The arguments to this function is the address of the +``meminfo`` structure populated by BL1. + +The platform may copy the contents of the ``meminfo`` structure into a private +variable as the original memory may be subsequently overwritten by BL2. The +copied structure is made available to all BL2 code through the +``bl2_plat_sec_mem_layout()`` function. + +On ARM standard platforms, this function also: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP\_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP\_BL2 is loaded. + +Function : bl2\_plat\_arch\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On ARM standard platforms, this function enables the MMU. + +Function : bl2\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2. + +In ARM standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2\_plat\_sec\_mem\_layout() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : meminfo * + +This function should only be called on the cold boot path. It may execute with +the MMU and data caches enabled if the platform port does the necessary +initialization in ``bl2_plat_arch_setup()``. It is only called by the primary CPU. + +The purpose of this function is to return a pointer to a ``meminfo`` structure +populated with the extents of secure RAM available for BL2 to use. See +``bl2_early_platform_setup()`` above. + +Following function is required only when LOAD\_IMAGE\_V2 is enabled. + +Function : bl2\_plat\_handle\_post\_image\_load() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 to handle +BL image specific information based on the ``image_id`` passed, when +LOAD\_IMAGE\_V2 is enabled. + +Following functions are required only when LOAD\_IMAGE\_V2 is disabled. + +Function : bl2\_plat\_get\_scp\_bl2\_meminfo() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo * + Return : void + +This function is used to get the memory limits where BL2 can load the +SCP\_BL2 image. The meminfo provided by this is used by load\_image() to +validate whether the SCP\_BL2 image can be loaded within the given +memory from the given base. + +Function : bl2\_plat\_handle\_scp\_bl2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : image_info * + Return : int + +This function is called after loading SCP\_BL2 image and it is used to perform +any platform-specific actions required to handle the SCP firmware. Typically it +transfers the image into SCP memory using a platform-specific protocol and waits +until SCP executes it and signals to the Application Processor (AP) for BL2 +execution to continue. + +This function returns 0 on success, a negative error code otherwise. + +Function : bl2\_plat\_get\_bl31\_params() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl31_params * + +BL2 platform code needs to return a pointer to a ``bl31_params`` structure it +will use for passing information to BL31. The ``bl31_params`` structure carries +the following information. +- Header describing the version information for interpreting the bl31\_param +structure +- Information about executing the BL33 image in the ``bl33_ep_info`` field +- Information about executing the BL32 image in the ``bl32_ep_info`` field +- Information about the type and extents of BL31 image in the +``bl31_image_info`` field +- Information about the type and extents of BL32 image in the +``bl32_image_info`` field +- Information about the type and extents of BL33 image in the +``bl33_image_info`` field + +The memory pointed by this structure and its sub-structures should be +accessible from BL31 initialisation code. BL31 might choose to copy the +necessary content, or maintain the structures until BL33 is initialised. + +Funtion : bl2\_plat\_get\_bl31\_ep\_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : entry_point_info * + +BL2 platform code returns a pointer which is used to populate the entry point +information for BL31 entry point. The location pointed by it should be +accessible from BL1 while processing the synchronous exception to run to BL31. + +In ARM standard platforms this is allocated inside a bl2\_to\_bl31\_params\_mem +structure in BL2 memory. + +Function : bl2\_plat\_set\_bl31\_ep\_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : image_info *, entry_point_info * + Return : void + +In the normal boot flow, this function is called after loading BL31 image and +it can be used to overwrite the entry point set by loader and also set the +security state and SPSR which represents the entry point system state for BL31. + +When booting an EL3 payload instead, this function is called after populating +its entry point address and can be used for the same purpose for the payload +image. It receives a null pointer as its first argument in this case. + +Function : bl2\_plat\_set\_bl32\_ep\_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : image_info *, entry_point_info * + Return : void + +This function is called after loading BL32 image and it can be used to +overwrite the entry point set by loader and also set the security state +and SPSR which represents the entry point system state for BL32. + +Function : bl2\_plat\_set\_bl33\_ep\_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : image_info *, entry_point_info * + Return : void + +This function is called after loading BL33 image and it can be used to +overwrite the entry point set by loader and also set the security state +and SPSR which represents the entry point system state for BL33. + +In the preloaded BL33 alternative boot flow, this function is called after +populating its entry point address. It is passed a null pointer as its first +argument in this case. + +Function : bl2\_plat\_get\_bl32\_meminfo() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo * + Return : void + +This function is used to get the memory limits where BL2 can load the +BL32 image. The meminfo provided by this is used by load\_image() to +validate whether the BL32 image can be loaded with in the given +memory from the given base. + +Function : bl2\_plat\_get\_bl33\_meminfo() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo * + Return : void + +This function is used to get the memory limits where BL2 can load the +BL33 image. The meminfo provided by this is used by load\_image() to +validate whether the BL33 image can be loaded with in the given +memory from the given base. + +This function isn't needed if either ``PRELOADED_BL33_BASE`` or ``EL3_PAYLOAD_BASE`` +build options are used. + +Function : bl2\_plat\_flush\_bl31\_params() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +Once BL2 has populated all the structures that needs to be read by BL1 +and BL31 including the bl31\_params structures and its sub-structures, +the bl31\_ep\_info structure and any platform specific data. It flushes +all these data to the main memory so that it is available when we jump to +later Bootloader stages with MMU off + +Function : plat\_get\_ns\_image\_entrypoint() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +As previously described, BL2 is responsible for arranging for control to be +passed to a normal world BL image through BL31. This function returns the +entrypoint of that image, which BL31 uses to jump to it. + +BL2 is responsible for loading the normal world BL33 image (e.g. UEFI). + +This function isn't needed if either ``PRELOADED_BL33_BASE`` or ``EL3_PAYLOAD_BASE`` +build options are used. + +FWU Boot Loader Stage 2 (BL2U) +------------------------------ + +The AP Firmware Updater Configuration, BL2U, is an optional part of the FWU +process and is executed only by the primary CPU. BL1 passes control to BL2U at +``BL2U_BASE``. BL2U executes in Secure-EL1 and is responsible for: + +#. (Optional) Transfering the optional SCP\_BL2U binary image from AP secure + memory to SCP RAM. BL2U uses the SCP\_BL2U ``image_info`` passed by BL1. + ``SCP_BL2U_BASE`` defines the address in AP secure memory where SCP\_BL2U + should be copied from. Subsequent handling of the SCP\_BL2U image is + implemented by the platform specific ``bl2u_plat_handle_scp_bl2u()`` function. + If ``SCP_BL2U_BASE`` is not defined then this step is not performed. + +#. Any platform specific setup required to perform the FWU process. For + example, ARM standard platforms initialize the TZC controller so that the + normal world can access DDR memory. + +The following functions must be implemented by the platform port to enable +BL2U to perform the tasks mentioned above. + +Function : bl2u\_early\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo *mem_info, void *plat_info + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. The arguments to this function is the address +of the ``meminfo`` structure and platform specific info provided by BL1. + +The platform may copy the contents of the ``mem_info`` and ``plat_info`` into +private storage as the original memory may be subsequently overwritten by BL2U. + +On ARM CSS platforms ``plat_info`` is interpreted as an ``image_info_t`` structure, +to extract SCP\_BL2U image information, which is then copied into a private +variable. + +Function : bl2u\_plat\_arch\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms, for example enabling the MMU (since the memory +map differs across platforms). + +Function : bl2u\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2u_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2U. + +In ARM standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2u\_plat\_handle\_scp\_bl2u() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This function is used to perform any platform-specific actions required to +handle the SCP firmware. Typically it transfers the image into SCP memory using +a platform-specific protocol and waits until SCP executes it and signals to the +Application Processor (AP) for BL2U execution to continue. + +This function returns 0 on success, a negative error code otherwise. +This function is included if SCP\_BL2U\_BASE is defined. + +Boot Loader Stage 3-1 (BL31) +---------------------------- + +During cold boot, the BL31 stage is executed only by the primary CPU. This is +determined in BL1 using the ``platform_is_primary_cpu()`` function. BL1 passes +control to BL31 at ``BL31_BASE``. During warm boot, BL31 is executed by all +CPUs. BL31 executes at EL3 and is responsible for: + +#. Re-initializing all architectural and platform state. Although BL1 performs + some of this initialization, BL31 remains resident in EL3 and must ensure + that EL3 architectural and platform state is completely initialized. It + should make no assumptions about the system state when it receives control. + +#. Passing control to a normal world BL image, pre-loaded at a platform- + specific address by BL2. BL31 uses the ``entry_point_info`` structure that BL2 + populated in memory to do this. + +#. Providing runtime firmware services. Currently, BL31 only implements a + subset of the Power State Coordination Interface (PSCI) API as a runtime + service. See Section 3.3 below for details of porting the PSCI + implementation. + +#. Optionally passing control to the BL32 image, pre-loaded at a platform- + specific address by BL2. BL31 exports a set of apis that allow runtime + services to specify the security state in which the next image should be + executed and run the corresponding image. BL31 uses the ``entry_point_info`` + structure populated by BL2 to do this. + +If BL31 is a reset vector, It also needs to handle the reset as specified in +section 2.2 before the tasks described above. + +The following functions must be implemented by the platform port to enable BL31 +to perform the above tasks. + +Function : bl31\_early\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : bl31_params *, void * + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. The arguments to this function are: + +- The address of the ``bl31_params`` structure populated by BL2. +- An opaque pointer that the platform may use as needed. + +The platform can copy the contents of the ``bl31_params`` structure and its +sub-structures into private variables if the original memory may be +subsequently overwritten by BL31 and similarly the ``void *`` pointing +to the platform data also needs to be saved. + +In ARM standard platforms, BL2 passes a pointer to a ``bl31_params`` structure +in BL2 memory. BL31 copies the information in this pointer to internal data +structures. It also performs the following: + +- Initialize a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL31. + +- Enable issuing of snoop and DVM (Distributed Virtual Memory) requests to the + CCI slave interface corresponding to the cluster that includes the primary + CPU. + +Function : bl31\_plat\_arch\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On ARM standard platforms, this function enables the MMU. + +Function : bl31\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to complete platform initialization so that both +BL31 runtime services and normal world software can function correctly. + +On ARM standard platforms, this function does the following: + +- Initialize the generic interrupt controller. + + Depending on the GIC driver selected by the platform, the appropriate GICv2 + or GICv3 initialization will be done, which mainly consists of: + + - Enable secure interrupts in the GIC CPU interface. + - Disable the legacy interrupt bypass mechanism. + - Configure the priority mask register to allow interrupts of all priorities + to be signaled to the CPU interface. + - Mark SGIs 8-15 and the other secure interrupts on the platform as secure. + - Target all secure SPIs to CPU0. + - Enable these secure interrupts in the GIC distributor. + - Configure all other interrupts as non-secure. + - Enable signaling of secure interrupts in the GIC distributor. + +- Enable system-level implementation of the generic timer counter through the + memory mapped interface. + +- Grant access to the system counter timer module + +- Initialize the power controller device. + + In particular, initialise the locks that prevent concurrent accesses to the + power controller device. + +Function : bl31\_plat\_runtime\_setup() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +The purpose of this function is allow the platform to perform any BL31 runtime +setup just prior to BL31 exit during cold boot. The default weak +implementation of this function will invoke ``console_uninit()`` which will +suppress any BL31 runtime logs. + +In ARM Standard platforms, this function will initialize the BL31 runtime +console which will cause all further BL31 logs to be output to the +runtime console. + +Function : bl31\_get\_next\_image\_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : entry_point_info * + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. + +This function is called by ``bl31_main()`` to retrieve information provided by +BL2 for the next image in the security state specified by the argument. BL31 +uses this information to pass control to that image in the specified security +state. This function must return a pointer to the ``entry_point_info`` structure +(that was copied during ``bl31_early_platform_setup()``) if the image exists. It +should return NULL otherwise. + +Function : plat\_get\_syscnt\_freq2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function is used by the architecture setup code to retrieve the counter +frequency for the CPU's generic timer. This value will be programmed into the +``CNTFRQ_EL0`` register. In ARM standard platforms, it returns the base frequency +of the system counter, which is retrieved from the first entry in the frequency +modes table. + +#define : PLAT\_PERCPU\_BAKERY\_LOCK\_SIZE [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When ``USE_COHERENT_MEM = 0``, this constant defines the total memory (in +bytes) aligned to the cache line boundary that should be allocated per-cpu to +accommodate all the bakery locks. + +If this constant is not defined when ``USE_COHERENT_MEM = 0``, the linker +calculates the size of the ``bakery_lock`` input section, aligns it to the +nearest ``CACHE_WRITEBACK_GRANULE``, multiplies it with ``PLATFORM_CORE_COUNT`` +and stores the result in a linker symbol. This constant prevents a platform +from relying on the linker and provide a more efficient mechanism for +accessing per-cpu bakery lock information. + +If this constant is defined and its value is not equal to the value +calculated by the linker then a link time assertion is raised. A compile time +assertion is raised if the value of the constant is not aligned to the cache +line boundary. + +Power State Coordination Interface (in BL31) +-------------------------------------------- + +The ARM Trusted Firmware's implementation of the PSCI API is based around the +concept of a *power domain*. A *power domain* is a CPU or a logical group of +CPUs which share some state on which power management operations can be +performed as specified by `PSCI`_. Each CPU in the system is assigned a cpu +index which is a unique number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. +The *power domains* are arranged in a hierarchical tree structure and +each *power domain* can be identified in a system by the cpu index of any CPU +that is part of that domain and a *power domain level*. A processing element +(for example, a CPU) is at level 0. If the *power domain* node above a CPU is +a logical grouping of CPUs that share some state, then level 1 is that group +of CPUs (for example, a cluster), and level 2 is a group of clusters +(for example, the system). More details on the power domain topology and its +organization can be found in `Power Domain Topology Design`_. + +BL31's platform initialization code exports a pointer to the platform-specific +power management operations required for the PSCI implementation to function +correctly. This information is populated in the ``plat_psci_ops`` structure. The +PSCI implementation calls members of the ``plat_psci_ops`` structure for performing +power management operations on the power domains. For example, the target +CPU is specified by its ``MPIDR`` in a PSCI ``CPU_ON`` call. The ``pwr_domain_on()`` +handler (if present) is called for the CPU power domain. + +The ``power-state`` parameter of a PSCI ``CPU_SUSPEND`` call can be used to +describe composite power states specific to a platform. The PSCI implementation +defines a generic representation of the power-state parameter viz which is an +array of local power states where each index corresponds to a power domain +level. Each entry contains the local power state the power domain at that power +level could enter. It depends on the ``validate_power_state()`` handler to +convert the power-state parameter (possibly encoding a composite power state) +passed in a PSCI ``CPU_SUSPEND`` call to this representation. + +The following functions form part of platform port of PSCI functionality. + +Function : plat\_psci\_stat\_accounting\_start() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting before entering a low power state. The ``pwr_domain_state`` field of +``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat\_psci\_stat\_accounting\_stop() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting after exiting from a low power state. The ``pwr_domain_state`` field +of ``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat\_psci\_stat\_get\_residency() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const psci_power_state_t *, int + Return : u_register_t + +This is an optional interface that is is invoked after resuming from a low power +state and provides the time spent resident in that low power state by the power +domain at a particular power domain level. When a CPU wakes up from suspend, +all its parent power domain levels are also woken up. The generic PSCI code +invokes this function for each parent power domain that is resumed and it +identified by the ``lvl`` (first argument) parameter. The ``state_info`` (second +argument) describes the low power state that the power domain has resumed from. +The current CPU is the first CPU in the power domain to resume from the low +power state and the ``last_cpu_idx`` (third parameter) is the index of the last +CPU in the power domain to suspend and may be needed to calculate the residency +for that power domain. + +Function : plat\_get\_target\_pwr\_state() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const plat_local_state_t *, unsigned int + Return : plat_local_state_t + +The PSCI generic code uses this function to let the platform participate in +state coordination during a power management operation. The function is passed +a pointer to an array of platform specific local power state ``states`` (second +argument) which contains the requested power state for each CPU at a particular +power domain level ``lvl`` (first argument) within the power domain. The function +is expected to traverse this array of upto ``ncpus`` (third argument) and return +a coordinated target power state by the comparing all the requested power +states. The target power state should not be deeper than any of the requested +power states. + +A weak definition of this API is provided by default wherein it assumes +that the platform assigns a local state value in order of increasing depth +of the power state i.e. for two power states X & Y, if X < Y +then X represents a shallower power state than Y. As a result, the +coordinated target local power state for a power domain will be the minimum +of the requested local power state values. + +Function : plat\_get\_power\_domain\_tree\_desc() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const unsigned char * + +This function returns a pointer to the byte array containing the power domain +topology tree description. The format and method to construct this array are +described in `Power Domain Topology Design`_. The BL31 PSCI initilization code +requires this array to be described by the platform, either statically or +dynamically, to initialize the power domain topology tree. In case the array +is populated dynamically, then plat\_core\_pos\_by\_mpidr() and +plat\_my\_core\_pos() should also be implemented suitably so that the topology +tree description matches the CPU indices returned by these APIs. These APIs +together form the platform interface for the PSCI topology framework. + +Function : plat\_setup\_psci\_ops() [mandatory] +----------------------------------------------- + +:: + + Argument : uintptr_t, const plat_psci_ops ** + Return : int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +This function is called by PSCI initialization code. Its purpose is to let +the platform layer know about the warm boot entrypoint through the +``sec_entrypoint`` (first argument) and to export handler routines for +platform-specific psci power management actions by populating the passed +pointer with a pointer to BL31's private ``plat_psci_ops`` structure. + +A description of each member of this structure is given below. Please refer to +the ARM FVP specific implementation of these handlers in +`plat/arm/board/fvp/fvp\_pm.c`_ as an example. For each PSCI function that the +platform wants to support, the associated operation or operations in this +structure must be provided and implemented (Refer section 4 of +`Firmware Design`_ for the PSCI API supported in Trusted Firmware). To disable +a PSCI function in a platform port, the operation should be removed from this +structure instead of providing an empty implementation. + +plat\_psci\_ops.cpu\_standby() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perform the platform-specific actions to enter the standby state for a cpu +indicated by the passed argument. This provides a fast path for CPU standby +wherein overheads of PSCI state management and lock acquistion is avoided. +For this handler to be invoked by the PSCI ``CPU_SUSPEND`` API implementation, +the suspend state type specified in the ``power-state`` parameter should be +STANDBY and the target power domain level specified should be the CPU. The +handler should put the CPU into a low power retention state (usually by +issuing a wfi instruction) and ensure that it can be woken up from that +state by a normal interrupt. The generic code expects the handler to succeed. + +plat\_psci\_ops.pwr\_domain\_on() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perform the platform specific actions to power on a CPU, specified +by the ``MPIDR`` (first argument). The generic code expects the platform to +return PSCI\_E\_SUCCESS on success or PSCI\_E\_INTERN\_FAIL for any failure. + +plat\_psci\_ops.pwr\_domain\_off() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perform the platform specific actions to prepare to power off the calling CPU +and its higher parent power domain levels as indicated by the ``target_state`` +(first argument). It is called by the PSCI ``CPU_OFF`` API implementation. + +The ``target_state`` encodes the platform coordinated target local power states +for the CPU power domain and its parent power domain levels. The handler +needs to perform power management operation corresponding to the local state +at each power level. + +For this handler, the local power state for the CPU power domain will be a +power down state where as it could be either power down, retention or run state +for the higher power domain levels depending on the result of state +coordination. The generic code expects the handler to succeed. + +plat\_psci\_ops.pwr\_domain\_suspend() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perform the platform specific actions to prepare to suspend the calling +CPU and its higher parent power domain levels as indicated by the +``target_state`` (first argument). It is called by the PSCI ``CPU_SUSPEND`` +API implementation. + +The ``target_state`` has a similar meaning as described in +the ``pwr_domain_off()`` operation. It encodes the platform coordinated +target local power states for the CPU power domain and its parent +power domain levels. The handler needs to perform power management operation +corresponding to the local state at each power level. The generic code +expects the handler to succeed. + +The difference between turning a power domain off versus suspending it +is that in the former case, the power domain is expected to re-initialize +its state when it is next powered on (see ``pwr_domain_on_finish()``). In the +latter case, the power domain is expected to save enough state so that it can +resume execution by restoring this state when its powered on (see +``pwr_domain_suspend_finish()``). + +plat\_psci\_ops.pwr\_domain\_pwr\_down\_wfi() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an optional function and, if implemented, is expected to perform +platform specific actions including the ``wfi`` invocation which allows the +CPU to powerdown. Since this function is invoked outside the PSCI locks, +the actions performed in this hook must be local to the CPU or the platform +must ensure that races between multiple CPUs cannot occur. + +The ``target_state`` has a similar meaning as described in the ``pwr_domain_off()`` +operation and it encodes the platform coordinated target local power states for +the CPU power domain and its parent power domain levels. This function must +not return back to the caller. + +If this function is not implemented by the platform, PSCI generic +implementation invokes ``psci_power_down_wfi()`` for power down. + +plat\_psci\_ops.pwr\_domain\_on\_finish() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. +It performs the platform-specific setup required to initialize enough state for +this CPU to enter the normal world and also provide secure runtime firmware +services. + +The ``target_state`` (first argument) is the prior state of the power domains +immediately before the CPU was turned on. It indicates which power domains +above the CPU might require initialization due to having previously been in +low power states. The generic code expects the handler to succeed. + +plat\_psci\_ops.pwr\_domain\_suspend\_finish() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an asynchronous wakeup +event, for example a timer interrupt that was programmed by the CPU during the +``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific +setup required to restore the saved state for this CPU to resume execution +in the normal world and also provide secure runtime firmware services. + +The ``target_state`` (first argument) has a similar meaning as described in +the ``pwr_domain_on_finish()`` operation. The generic code expects the platform +to succeed. + +plat\_psci\_ops.system\_off() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by PSCI implementation in response to a ``SYSTEM_OFF`` +call. It performs the platform-specific system poweroff sequence after +notifying the Secure Payload Dispatcher. + +plat\_psci\_ops.system\_reset() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by PSCI implementation in response to a ``SYSTEM_RESET`` +call. It performs the platform-specific system reset sequence after +notifying the Secure Payload Dispatcher. + +plat\_psci\_ops.validate\_power\_state() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by the PSCI implementation during the ``CPU_SUSPEND`` +call to validate the ``power_state`` parameter of the PSCI API and if valid, +populate it in ``req_state`` (second argument) array as power domain level +specific local states. If the ``power_state`` is invalid, the platform must +return PSCI\_E\_INVALID\_PARAMS as error, which is propagated back to the +normal world PSCI client. + +plat\_psci\_ops.validate\_ns\_entrypoint() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by the PSCI implementation during the ``CPU_SUSPEND``, +``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the non-secure ``entry_point`` +parameter passed by the normal world. If the ``entry_point`` is invalid, +the platform must return PSCI\_E\_INVALID\_ADDRESS as error, which is +propagated back to the normal world PSCI client. + +plat\_psci\_ops.get\_sys\_suspend\_power\_state() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` +call to get the ``req_state`` parameter from platform which encodes the power +domain level specific local states to suspend to system affinity level. The +``req_state`` will be utilized to do the PSCI state coordination and +``pwr_domain_suspend()`` will be invoked with the coordinated target state to +enter system suspend. + +plat\_psci\_ops.get\_pwr\_lvl\_state\_idx() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an optional function and, if implemented, is invoked by the PSCI +implementation to convert the ``local_state`` (first argument) at a specified +``pwr_lvl`` (second argument) to an index between 0 and +``PLAT_MAX_PWR_LVL_STATES`` - 1. This function is only needed if the platform +supports more than two local power states at each power domain level, that is +``PLAT_MAX_PWR_LVL_STATES`` is greater than 2, and needs to account for these +local power states. + +plat\_psci\_ops.translate\_power\_state\_by\_mpidr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an optional function and, if implemented, verifies the ``power_state`` +(second argument) parameter of the PSCI API corresponding to a target power +domain. The target power domain is identified by using both ``MPIDR`` (first +argument) and the power domain level encoded in ``power_state``. The power domain +level specific local states are to be extracted from ``power_state`` and be +populated in the ``output_state`` (third argument) array. The functionality +is similar to the ``validate_power_state`` function described above and is +envisaged to be used in case the validity of ``power_state`` depend on the +targeted power domain. If the ``power_state`` is invalid for the targeted power +domain, the platform must return PSCI\_E\_INVALID\_PARAMS as error. If this +function is not implemented, then the generic implementation relies on +``validate_power_state`` function to translate the ``power_state``. + +This function can also be used in case the platform wants to support local +power state encoding for ``power_state`` parameter of PSCI\_STAT\_COUNT/RESIDENCY +APIs as described in Section 5.18 of `PSCI`_. + +plat\_psci\_ops.get\_node\_hw\_state() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an optional function. If implemented this function is intended to return +the power state of a node (identified by the first parameter, the ``MPIDR``) in +the power domain topology (identified by the second parameter, ``power_level``), +as retrieved from a power controller or equivalent component on the platform. +Upon successful completion, the implementation must map and return the final +status among ``HW_ON``, ``HW_OFF`` or ``HW_STANDBY``. Upon encountering failures, it +must return either ``PSCI_E_INVALID_PARAMS`` or ``PSCI_E_NOT_SUPPORTED`` as +appropriate. + +Implementations are not expected to handle ``power_levels`` greater than +``PLAT_MAX_PWR_LVL``. + +Interrupt Management framework (in BL31) +---------------------------------------- + +BL31 implements an Interrupt Management Framework (IMF) to manage interrupts +generated in either security state and targeted to EL1 or EL2 in the non-secure +state or EL3/S-EL1 in the secure state. The design of this framework is +described in the `IMF Design Guide`_ + +A platform should export the following APIs to support the IMF. The following +text briefly describes each api and its implementation in ARM standard +platforms. The API implementation depends upon the type of interrupt controller +present in the platform. ARM standard platform layer supports both +`ARM Generic Interrupt Controller version 2.0 (GICv2)`_ +and `3.0 (GICv3)`_. Juno builds the ARM +Standard layer to use GICv2 and the FVP can be configured to use either GICv2 or +GICv3 depending on the build flag ``FVP_USE_GIC_DRIVER`` (See FVP platform +specific build options in `User Guide`_ for more details). + +Function : plat\_interrupt\_type\_to\_line() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t, uint32_t + Return : uint32_t + +The ARM processor signals an interrupt exception either through the IRQ or FIQ +interrupt line. The specific line that is signaled depends on how the interrupt +controller (IC) reports different interrupt types from an execution context in +either security state. The IMF uses this API to determine which interrupt line +the platform IC uses to signal each type of interrupt supported by the framework +from a given security state. This API must be invoked at EL3. + +The first parameter will be one of the ``INTR_TYPE_*`` values (see +`IMF Design Guide`_) indicating the target type of the interrupt, the second parameter is the +security state of the originating execution context. The return result is the +bit position in the ``SCR_EL3`` register of the respective interrupt trap: IRQ=1, +FIQ=2. + +In the case of ARM standard platforms using GICv2, S-EL1 interrupts are +configured as FIQs and Non-secure interrupts as IRQs from either security +state. + +In the case of ARM standard platforms using GICv3, the interrupt line to be +configured depends on the security state of the execution context when the +interrupt is signalled and are as follows: + +- The S-EL1 interrupts are signaled as IRQ in S-EL0/1 context and as FIQ in + NS-EL0/1/2 context. +- The Non secure interrupts are signaled as FIQ in S-EL0/1 context and as IRQ + in the NS-EL0/1/2 context. +- The EL3 interrupts are signaled as FIQ in both S-EL0/1 and NS-EL0/1/2 + context. + +Function : plat\_ic\_get\_pending\_interrupt\_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the type of the highest priority pending interrupt at the +platform IC. The IMF uses the interrupt type to retrieve the corresponding +handler function. ``INTR_TYPE_INVAL`` is returned when there is no interrupt +pending. The valid interrupt types that can be returned are ``INTR_TYPE_EL3``, +``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``. This API must be invoked at EL3. + +In the case of ARM standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of +the pending interrupt. The type of interrupt depends upon the id value as +follows. + +#. id < 1022 is reported as a S-EL1 interrupt +#. id = 1022 is reported as a Non-secure interrupt. +#. id = 1023 is reported as an invalid interrupt type. + +In the case of ARM standard platforms using GICv3, the system register +``ICC_HPPIR0_EL1``, *Highest Priority Pending group 0 Interrupt Register*, +is read to determine the id of the pending interrupt. The type of interrupt +depends upon the id value as follows. + +#. id = ``PENDING_G1S_INTID`` (1020) is reported as a S-EL1 interrupt +#. id = ``PENDING_G1NS_INTID`` (1021) is reported as a Non-secure interrupt. +#. id = ``GIC_SPURIOUS_INTERRUPT`` (1023) is reported as an invalid interrupt type. +#. All other interrupt id's are reported as EL3 interrupt. + +Function : plat\_ic\_get\_pending\_interrupt\_id() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the id of the highest priority pending interrupt at the +platform IC. ``INTR_ID_UNAVAILABLE`` is returned when there is no interrupt +pending. + +In the case of ARM standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of the +pending interrupt. The id that is returned by API depends upon the value of +the id read from the interrupt controller as follows. + +#. id < 1022. id is returned as is. +#. id = 1022. The *Aliased Highest Priority Pending Interrupt Register* + (``GICC_AHPPIR``) is read to determine the id of the non-secure interrupt. + This id is returned by the API. +#. id = 1023. ``INTR_ID_UNAVAILABLE`` is returned. + +In the case of ARM standard platforms using GICv3, if the API is invoked from +EL3, the system register ``ICC_HPPIR0_EL1``, *Highest Priority Pending Interrupt +group 0 Register*, is read to determine the id of the pending interrupt. The id +that is returned by API depends upon the value of the id read from the +interrupt controller as follows. + +#. id < ``PENDING_G1S_INTID`` (1020). id is returned as is. +#. id = ``PENDING_G1S_INTID`` (1020) or ``PENDING_G1NS_INTID`` (1021). The system + register ``ICC_HPPIR1_EL1``, *Highest Priority Pending Interrupt group 1 + Register* is read to determine the id of the group 1 interrupt. This id + is returned by the API as long as it is a valid interrupt id +#. If the id is any of the special interrupt identifiers, + ``INTR_ID_UNAVAILABLE`` is returned. + +When the API invoked from S-EL1 for GICv3 systems, the id read from system +register ``ICC_HPPIR1_EL1``, *Highest Priority Pending group 1 Interrupt +Register*, is returned if is not equal to GIC\_SPURIOUS\_INTERRUPT (1023) else +``INTR_ID_UNAVAILABLE`` is returned. + +Function : plat\_ic\_acknowledge\_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API is used by the CPU to indicate to the platform IC that processing of +the highest pending interrupt has begun. It should return the id of the +interrupt which is being processed. + +This function in ARM standard platforms using GICv2, reads the *Interrupt +Acknowledge Register* (``GICC_IAR``). This changes the state of the highest +priority pending interrupt from pending to active in the interrupt controller. +It returns the value read from the ``GICC_IAR``. This value is the id of the +interrupt whose state has been changed. + +In the case of ARM standard platforms using GICv3, if the API is invoked +from EL3, the function reads the system register ``ICC_IAR0_EL1``, *Interrupt +Acknowledge Register group 0*. If the API is invoked from S-EL1, the function +reads the system register ``ICC_IAR1_EL1``, *Interrupt Acknowledge Register +group 1*. The read changes the state of the highest pending interrupt from +pending to active in the interrupt controller. The value read is returned +and is the id of the interrupt whose state has been changed. + +The TSP uses this API to start processing of the secure physical timer +interrupt. + +Function : plat\_ic\_end\_of\_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This API is used by the CPU to indicate to the platform IC that processing of +the interrupt corresponding to the id (passed as the parameter) has +finished. The id should be the same as the id returned by the +``plat_ic_acknowledge_interrupt()`` API. + +ARM standard platforms write the id to the *End of Interrupt Register* +(``GICC_EOIR``) in case of GICv2, and to ``ICC_EOIR0_EL1`` or ``ICC_EOIR1_EL1`` +system register in case of GICv3 depending on where the API is invoked from, +EL3 or S-EL1. This deactivates the corresponding interrupt in the interrupt +controller. + +The TSP uses this API to finish processing of the secure physical timer +interrupt. + +Function : plat\_ic\_get\_interrupt\_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : uint32_t + +This API returns the type of the interrupt id passed as the parameter. +``INTR_TYPE_INVAL`` is returned if the id is invalid. If the id is valid, a valid +interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``) is +returned depending upon how the interrupt has been configured by the platform +IC. This API must be invoked at EL3. + +ARM standard platforms using GICv2 configures S-EL1 interrupts as Group0 interrupts +and Non-secure interrupts as Group1 interrupts. It reads the group value +corresponding to the interrupt id from the relevant *Interrupt Group Register* +(``GICD_IGROUPRn``). It uses the group value to determine the type of interrupt. + +In the case of ARM standard platforms using GICv3, both the *Interrupt Group +Register* (``GICD_IGROUPRn``) and *Interrupt Group Modifier Register* +(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured +as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt. + +Crash Reporting mechanism (in BL31) +----------------------------------- + +BL31 implements a crash reporting mechanism which prints the various registers +of the CPU to enable quick crash analysis and debugging. It requires that a +console is designated as the crash console by the platform which will be used to +print the register dump. + +The following functions must be implemented by the platform if it wants crash +reporting mechanism in BL31. The functions are implemented in assembly so that +they can be invoked without a C Runtime stack. + +Function : plat\_crash\_console\_init +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This API is used by the crash reporting mechanism to initialize the crash +console. It must only use the general purpose registers x0 to x4 to do the +initialization and returns 1 on success. + +Function : plat\_crash\_console\_putc +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : int + +This API is used by the crash reporting mechanism to print a character on the +designated crash console. It must only use general purpose registers x1 and +x2 to do its work. The parameter and the return value are in general purpose +register x0. + +Function : plat\_crash\_console\_flush +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This API is used by the crash reporting mechanism to force write of all buffered +data on the designated crash console. It should only use general purpose +registers x0 and x1 to do its work. The return value is 0 on successful +completion; otherwise the return value is -1. + +Build flags +----------- + +- **ENABLE\_PLAT\_COMPAT** + All the platforms ports conforming to this API specification should define + the build flag ``ENABLE_PLAT_COMPAT`` to 0 as the compatibility layer should + be disabled. For more details on compatibility layer, refer + `Migration Guide`_. + +There are some build flags which can be defined by the platform to control +inclusion or exclusion of certain BL stages from the FIP image. These flags +need to be defined in the platform makefile which will get included by the +build system. + +- **NEED\_BL33** + By default, this flag is defined ``yes`` by the build system and ``BL33`` + build option should be supplied as a build option. The platform has the + option of excluding the BL33 image in the ``fip`` image by defining this flag + to ``no``. If any of the options ``EL3_PAYLOAD_BASE`` or ``PRELOADED_BL33_BASE`` + are used, this flag will be set to ``no`` automatically. + +C Library +--------- + +To avoid subtle toolchain behavioral dependencies, the header files provided +by the compiler are not used. The software is built with the ``-nostdinc`` flag +to ensure no headers are included from the toolchain inadvertently. Instead the +required headers are included in the ARM Trusted Firmware source tree. The +library only contains those C library definitions required by the local +implementation. If more functionality is required, the needed library functions +will need to be added to the local implementation. + +Versions of `FreeBSD`_ headers can be found in ``include/lib/stdlib``. Some of +these headers have been cut down in order to simplify the implementation. In +order to minimize changes to the header files, the `FreeBSD`_ layout has been +maintained. The generic C library definitions can be found in +``include/lib/stdlib`` with more system and machine specific declarations in +``include/lib/stdlib/sys`` and ``include/lib/stdlib/machine``. + +The local C library implementations can be found in ``lib/stdlib``. In order to +extend the C library these files may need to be modified. It is recommended to +use a release version of `FreeBSD`_ as a starting point. + +The C library header files in the `FreeBSD`_ source tree are located in the +``include`` and ``sys/sys`` directories. `FreeBSD`_ machine specific definitions +can be found in the ``sys/`` directories. These files define things +like 'the size of a pointer' and 'the range of an integer'. Since an AArch64 +port for `FreeBSD`_ does not yet exist, the machine specific definitions are +based on existing machine types with similar properties (for example SPARC64). + +Where possible, C library function implementations were taken from `FreeBSD`_ +as found in the ``lib/libc`` directory. + +A copy of the `FreeBSD`_ sources can be downloaded with ``git``. + +:: + + git clone git://github.com/freebsd/freebsd.git -b origin/release/9.2.0 + +Storage abstraction layer +------------------------- + +In order to improve platform independence and portability an storage abstraction +layer is used to load data from non-volatile platform storage. + +Each platform should register devices and their drivers via the Storage layer. +These drivers then need to be initialized by bootloader phases as +required in their respective ``blx_platform_setup()`` functions. Currently +storage access is only required by BL1 and BL2 phases. The ``load_image()`` +function uses the storage layer to access non-volatile platform storage. + +It is mandatory to implement at least one storage driver. For the ARM +development platforms the Firmware Image Package (FIP) driver is provided as +the default means to load data from storage (see the "Firmware Image Package" +section in the `User Guide`_). The storage layer is described in the header file +``include/drivers/io/io_storage.h``. The implementation of the common library +is in ``drivers/io/io_storage.c`` and the driver files are located in +``drivers/io/``. + +Each IO driver must provide ``io_dev_*`` structures, as described in +``drivers/io/io_driver.h``. These are returned via a mandatory registration +function that is called on platform initialization. The semi-hosting driver +implementation in ``io_semihosting.c`` can be used as an example. + +The Storage layer provides mechanisms to initialize storage devices before +IO operations are called. The basic operations supported by the layer +include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. +Drivers do not have to implement all operations, but each platform must +provide at least one driver for a device capable of supporting generic +operations such as loading a bootloader image. + +The current implementation only allows for known images to be loaded by the +firmware. These images are specified by using their identifiers, as defined in +[include/plat/common/platform\_def.h] (or a separate header file included from +there). The platform layer (``plat_get_image_source()``) then returns a reference +to a device and a driver-specific ``spec`` which will be understood by the driver +to allow access to the image data. + +The layer is designed in such a way that is it possible to chain drivers with +other drivers. For example, file-system drivers may be implemented on top of +physical block devices, both represented by IO devices with corresponding +drivers. In such a case, the file-system "binding" with the block device may +be deferred until the file-system device is initialised. + +The abstraction currently depends on structures being statically allocated +by the drivers and callers, as the system does not yet provide a means of +dynamically allocating memory. This may also have the affect of limiting the +amount of open resources per driver. + +-------------- + +*Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.* + +.. _Migration Guide: platform-migration-guide.rst +.. _include/plat/common/platform.h: ../include/plat/common/platform.h +.. _include/plat/arm/common/plat\_arm.h: ../include/plat/arm/common/plat_arm.h%5D +.. _User Guide: user-guide.rst +.. _include/plat/common/common\_def.h: ../include/plat/common/common_def.h +.. _include/plat/arm/common/arm\_def.h: ../include/plat/arm/common/arm_def.h +.. _plat/common/aarch64/platform\_mp\_stack.S: ../plat/common/aarch64/platform_mp_stack.S +.. _plat/common/aarch64/platform\_up\_stack.S: ../plat/common/aarch64/platform_up_stack.S +.. _For example, define the build flag in platform.mk: PLAT_PL061_MAX_GPIOS%20:=%20160 +.. _Power Domain Topology Design: psci-pd-tree.rst +.. _include/common/bl\_common.h: ../include/common/bl_common.h +.. _include/lib/aarch32/arch.h: ../include/lib/aarch32/arch.h +.. _Firmware Design: firmware-design.rst +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _plat/arm/board/fvp/fvp\_pm.c: ../plat/arm/board/fvp/fvp_pm.c +.. _IMF Design Guide: interrupt-framework-design.rst +.. _ARM Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html +.. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html +.. _FreeBSD: http://www.freebsd.org diff --git a/docs/psci-lib-integration-guide.rst b/docs/psci-lib-integration-guide.rst new file mode 100644 index 0000000..38eeb2f --- /dev/null +++ b/docs/psci-lib-integration-guide.rst @@ -0,0 +1,564 @@ +PSCI Library Integration guide for ARMv8-A AArch32 systems +========================================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +This document describes the PSCI library interface with a focus on how to +integrate with a suitable Trusted OS for an ARMv8-A AArch32 system. The PSCI +Library implements the PSCI Standard as described in `PSCI spec`_ and is meant +to be integrated with EL3 Runtime Software which invokes the PSCI Library +interface appropriately. **EL3 Runtime Software** refers to software executing +at the highest secure privileged mode, which is EL3 in AArch64 or Secure SVC/ +Monitor mode in AArch32, and provides runtime services to the non-secure world. +The runtime service request is made via SMC (Secure Monitor Call) and the call +must adhere to `SMCCC`_. In AArch32, EL3 Runtime Software may additionally +include Trusted OS functionality. A minimal AArch32 Secure Payload, SP-MIN, is +provided in ARM Trusted Firmware to illustrate the usage and integration of the +PSCI library. The description of PSCI library interface and its integration +with EL3 Runtime Software in this document is targeted towards AArch32 systems. + +Generic call sequence for PSCI Library interface (AArch32) +---------------------------------------------------------- + +The generic call sequence of PSCI Library interfaces (see +`section 4`_) during cold boot in AArch32 +system is described below: + +#. After cold reset, the EL3 Runtime Software performs its cold boot + initialization including the PSCI library pre-requisites mentioned in + `section 4`_, and also the necessary platform + setup. + +#. Call ``psci_setup()`` in Monitor mode. + +#. Optionally call ``psci_register_spd_pm_hook()`` to register callbacks to + do bookkeeping for the EL3 Runtime Software during power management. + +#. Call ``psci_prepare_next_non_secure_ctx()`` to initialize the non-secure CPU + context. + +#. Get the non-secure ``cpu_context_t`` for the current CPU by calling + ``cm_get_context()`` , then programming the registers in the non-secure + context and exiting to non-secure world. If the EL3 Runtime Software needs + additional configuration to be set for non-secure context, like routing + FIQs to the secure world, the values of the registers can be modified prior + to programming. See `section 3`_ for more + details on CPU context management. + +The generic call sequence of PSCI library interfaces during warm boot in +AArch32 systems is described below: + +#. After warm reset, the EL3 Runtime Software performs the necessary warm + boot initialization including the PSCI library pre-requisites mentioned in + `section 4`_ (Note that the Data cache + **must not** be enabled). + +#. Call ``psci_warmboot_entrypoint()`` in Monitor mode. This interface + initializes/restores the non-secure CPU context as well. + +#. Do step 5 of the cold boot call sequence described above. + +The generic call sequence of PSCI library interfaces on receipt of a PSCI SMC +on an AArch32 system is described below: + +#. On receipt of an SMC, save the register context as per `SMCCC`_. + +#. If the SMC function identifier corresponds to a SMC32 PSCI API, construct + the appropriate arguments and call the ``psci_smc_handler()`` interface. + The invocation may or may not return back to the caller depending on + whether the PSCI API resulted in power down of the CPU. + +#. If ``psci_smc_handler()`` returns, populate the return value in R0 (AArch32)/ + X0 (AArch64) and restore other registers as per `SMCCC`_. + +#. .. rubric:: PSCI CPU context management + :name: psci-cpu-context-management + +PSCI library is in charge of initializing/restoring the non-secure CPU system +registers according to `PSCI specification`_ during cold/warm boot. +This is referred to as ``PSCI CPU Context Management``. Registers that need to +be preserved across CPU power down/power up cycles are maintained in +``cpu_context_t`` data structure. The initialization of other non-secure CPU +system registers which do not require coordination with the EL3 Runtime +Software is done directly by the PSCI library (see ``cm_prepare_el3_exit()``). + +The EL3 Runtime Software is responsible for managing register context +during switch between Normal and Secure worlds. The register context to be +saved and restored depends on the mechanism used to trigger the world switch. +For example, if the world switch was triggered by an SMC call, then the +registers need to be saved and restored according to `SMCCC`_. In AArch64, +due to the tight integration with BL31, both BL31 and PSCI library +use the same ``cpu_context_t`` data structure for PSCI CPU context management +and register context management during world switch. This cannot be assumed +for AArch32 EL3 Runtime Software since most AArch32 Trusted OSes already implement +a mechanism for register context management during world switch. Hence, when +the PSCI library is integrated with a AArch32 EL3 Runtime Software, the +``cpu_context_t`` is stripped down for just PSCI CPU context management. + +During cold/warm boot, after invoking appropriate PSCI library interfaces, it +is expected that the EL3 Runtime Software will query the ``cpu_context_t`` and +write appropriate values to the corresponding system registers. This mechanism +resolves 2 additional problems for AArch32 EL3 Runtime Software: + +#. Values for certain system registers like SCR and SCTLR cannot be + unilaterally determined by PSCI library and need inputs from the EL3 + Runtime Software. Using ``cpu_context_t`` as an intermediary data store + allows EL3 Runtime Software to modify the register values appropriately + before programming them. + +#. The PSCI library provides appropriate LR and SPSR values (entrypoint + information) for exit into non-secure world. Using ``cpu_context_t`` as an + intermediary data store allows the EL3 Runtime Software to store these + values safely until it is ready for exit to non-secure world. + +Currently the ``cpu_context_t`` data structure for AArch32 stores the following +registers: R0 - R3, LR (R14), SCR, SPSR, SCTLR. + +The EL3 Runtime Software must implement accessors to get/set pointers +to CPU context ``cpu_context_t`` data and these are described in +`section 5.2`_. + +PSCI Library Interface +---------------------- + +The PSCI library implements the `PSCI Specification`_. The interfaces +to this library are declared in ``psci.h`` and are as listed below: + +.. code:: c + + u_register_t psci_smc_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags); + int psci_setup(const psci_lib_args_t *lib_args); + void psci_warmboot_entrypoint(void); + void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); + void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info); + +The CPU context data 'cpu\_context\_t' is programmed to the registers differently +when PSCI is integrated with an AArch32 EL3 Runtime Software compared to +when the PSCI is integrated with an AArch64 EL3 Runtime Software (BL31). For +example, in the case of AArch64, there is no need to retrieve ``cpu_context_t`` +data and program the registers as it will done implicitly as part of +``el3_exit``. The description below of the PSCI interfaces is targeted at +integration with an AArch32 EL3 Runtime Software. + +The PSCI library is responsible for initializing/restoring the non-secure world +to an appropriate state after boot and may choose to directly program the +non-secure system registers. The PSCI generic code takes care not to directly +modify any of the system registers affecting the secure world and instead +returns the values to be programmed to these registers via ``cpu_context_t``. +The EL3 Runtime Software is responsible for programming those registers and +can use the proposed values provided in the ``cpu_context_t``, modifying the +values if required. + +PSCI library needs the flexibility to access both secure and non-secure +copies of banked registers. Hence it needs to be invoked in Monitor mode +for AArch32 and in EL3 for AArch64. The NS bit in SCR (in AArch32) or SCR\_EL3 +(in AArch64) must be set to 0. Additional requirements for the PSCI library +interfaces are: + +- Instruction cache must be enabled +- Both IRQ and FIQ must be masked for the current CPU +- The page tables must be setup and the MMU enabled +- The C runtime environment must be setup and stack initialized +- The Data cache must be enabled prior to invoking any of the PSCI library + interfaces except for ``psci_warmboot_entrypoint()``. For + ``psci_warmboot_entrypoint()``, if the build option ``HW_ASSISTED_COHERENCY`` + is enabled however, data caches are expected to be enabled. + +Further requirements for each interface can be found in the interface +description. + +Interface : psci\_setup() +~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_lib_args_t *lib_args + Return : void + +This function is to be called by the primary CPU during cold boot before +any other interface to the PSCI library. It takes ``lib_args``, a const pointer +to ``psci_lib_args_t``, as the argument. The ``psci_lib_args_t`` is a versioned +structure and is declared in ``psci.h`` header as follows: + +.. code:: c + + typedef struct psci_lib_args { + /* The version information of PSCI Library Interface */ + param_header_t h; + /* The warm boot entrypoint function */ + mailbox_entrypoint_t mailbox_ep; + } psci_lib_args_t; + +The first field ``h``, of ``param_header_t`` type, provides the version +information. The second field ``mailbox_ep`` is the warm boot entrypoint address +and is used to configure the platform mailbox. Helper macros are provided in +psci.h to construct the ``lib_args`` argument statically or during runtime. Prior +to calling the ``psci_setup()`` interface, the platform setup for cold boot +must have completed. Major actions performed by this interface are: + +- Initializes architecture. +- Initializes PSCI power domain and state coordination data structures. +- Calls ``plat_setup_psci_ops()`` with warm boot entrypoint ``mailbox_ep`` as + argument. +- Calls ``cm_set_context_by_index()`` (see + `section 5.2`_) for all the CPUs in the + platform + +Interface : psci\_prepare\_next\_non\_secure\_ctx() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t *next_image_info + Return : void + +After ``psci_setup()`` and prior to exit to the non-secure world, this function +must be called by the EL3 Runtime Software to initialize the non-secure world +context. The non-secure world entrypoint information ``next_image_info`` (first +argument) will be used to determine the non-secure context. After this function +returns, the EL3 Runtime Software must retrieve the ``cpu_context_t`` (using +cm\_get\_context()) for the current CPU and program the registers prior to exit +to the non-secure world. + +Interface : psci\_register\_spd\_pm\_hook() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const spd_pm_ops_t * + Return : void + +As explained in `section 5.4`_, +the EL3 Runtime Software may want to perform some bookkeeping during power +management operations. This function is used to register the ``spd_pm_ops_t`` +(first argument) callbacks with the PSCI library which will be called +ppropriately during power management. Calling this function is optional and +need to be called by the primary CPU during the cold boot sequence after +``psci_setup()`` has completed. + +Interface : psci\_smc\_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags + Return : u_register_t + +This function is the top level handler for SMCs which fall within the +PSCI service range specified in `SMCCC`_. The function ID ``smc_fid`` (first +argument) determines the PSCI API to be called. The ``x1`` to ``x4`` (2nd to 5th +arguments), are the values of the registers r1 - r4 (in AArch32) or x1 - x4 +(in AArch64) when the SMC is received. These are the arguments to PSCI API as +described in `PSCI spec`_. The 'flags' (8th argument) is a bit field parameter +and is detailed in 'smcc.h' header. It includes whether the call is from the +secure or non-secure world. The ``cookie`` (6th argument) and the ``handle`` +(7th argument) are not used and are reserved for future use. + +The return value from this interface is the return value from the underlying +PSCI API corresponding to ``smc_fid``. This function may not return back to the +caller if PSCI API causes power down of the CPU. In this case, when the CPU +wakes up, it will start execution from the warm reset address. + +Interface : psci\_warmboot\_entrypoint() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs the warm boot initialization/restoration as mandated by +`PSCI spec`_. For AArch32, on wakeup from power down the CPU resets to secure SVC +mode and the EL3 Runtime Software must perform the prerequisite initializations +mentioned at top of this section. This function must be called with Data cache +disabled (unless build option ``HW_ASSISTED_COHERENCY`` is enabled) but with MMU +initialized and enabled. The major actions performed by this function are: + +- Invalidates the stack and enables the data cache. +- Initializes architecture and PSCI state coordination. +- Restores/Initializes the peripheral drivers to the required state via + appropriate ``plat_psci_ops_t`` hooks +- Restores the EL3 Runtime Software context via appropriate ``spd_pm_ops_t`` + callbacks. +- Restores/Initializes the non-secure context and populates the + ``cpu_context_t`` for the current CPU. + +Upon the return of this function, the EL3 Runtime Software must retrieve the +non-secure ``cpu_context_t`` using ``cm_get_context()`` and program the registers +prior to exit to the non-secure world. + +EL3 Runtime Software dependencies +--------------------------------- + +The PSCI Library includes supporting frameworks like context management, +cpu operations (cpu\_ops) and per-cpu data framework. Other helper library +functions like bakery locks and spin locks are also included in the library. +The dependencies which must be fulfilled by the EL3 Runtime Software +for integration with PSCI library are described below. + +General dependencies +~~~~~~~~~~~~~~~~~~~~ + +The PSCI library being a Multiprocessor (MP) implementation, EL3 Runtime +Software must provide an SMC handling framework capable of MP adhering to +`SMCCC`_ specification. + +The EL3 Runtime Software must also export cache maintenance primitives +and some helper utilities for assert, print and memory operations as listed +below. The ARM Trusted Firmware source tree provides implementations for all +these functions but the EL3 Runtime Software may use its own implementation. + +**Functions : assert(), memcpy(), memset** + +These must be implemented as described in ISO C Standard. + +**Function : flush\_dcache\_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function cleans and invalidates (flushes) the data cache for memory +at address ``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : inv\_dcache\_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function invalidates (flushes) the data cache for memory at address +``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : do\_panic()** + +:: + + Argument : void + Return : void + +This function will be called by the PSCI library on encountering a critical +failure that cannot be recovered from. This function **must not** return. + +**Function : tf\_printf()** + +This is printf-compatible function, but unlike printf, it does not return any +value. The ARM Trusted Firmware source tree provides an implementation which +is optimized for stack usage and supports only a subset of format specifiers. +The details of the format specifiers supported can be found in the +``tf_printf.c`` file in ARM Trusted Firmware source tree. + +CPU Context management API +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CPU context management data memory is statically allocated by PSCI library +in BSS section. The PSCI library requires the EL3 Runtime Software to implement +APIs to store and retrieve pointers to this CPU context data. SP-MIN +demonstrates how these APIs can be implemented but the EL3 Runtime Software can +choose a more optimal implementation (like dedicating the secure TPIDRPRW +system register (in AArch32) for storing these pointers). + +**Function : cm\_set\_context\_by\_index()** + +:: + + Argument : unsigned int cpu_idx, void *context, unsigned int security_state + Return : void + +This function is called during cold boot when the ``psci_setup()`` PSCI library +interface is called. + +This function must store the pointer to the CPU context data, ``context`` (2nd +argument), for the specified ``security_state`` (3rd argument) and CPU identified +by ``cpu_idx`` (first argument). The ``security_state`` will always be non-secure +when called by PSCI library and this argument is retained for compatibility +with BL31. The ``cpu_idx`` will correspond to the index returned by the +``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +The actual method of storing the ``context`` pointers is implementation specific. +For example, SP-MIN stores the pointers in the array ``sp_min_cpu_ctx_ptr`` +declared in ``sp_min_main.c``. + +**Function : cm\_get\_context()** + +:: + + Argument : uint32_t security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (first argument) for the current CPU. The caller +must ensure that ``cm_set_context_by_index`` is called first and the appropriate +context pointers are stored prior to invoking this API. The ``security_state`` +will always be non-secure when called by PSCI library and this argument +is retained for compatibility with BL31. + +**Function : cm\_get\_context\_by\_index()** + +:: + + Argument : unsigned int cpu_idx, unsigned int security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (second argument) for the CPU identified by +``cpu_idx`` (first argument). The caller must ensure that +``cm_set_context_by_index`` is called first and the appropriate context +pointers are stored prior to invoking this API. The ``security_state`` will +always be non-secure when called by PSCI library and this argument is +retained for compatibility with BL31. The ``cpu_idx`` will correspond to the +index returned by the ``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +Platform API +~~~~~~~~~~~~ + +The platform layer abstracts the platform-specific details from the generic +PSCI library. The following platform APIs/macros must be defined by the EL3 +Runtime Software for integration with the PSCI library. + +The mandatory platform APIs are: + +- plat\_my\_core\_pos +- plat\_core\_pos\_by\_mpidr +- plat\_get\_syscnt\_freq2 +- plat\_get\_power\_domain\_tree\_desc +- plat\_setup\_psci\_ops +- plat\_reset\_handler +- plat\_panic\_handler +- plat\_get\_my\_stack + +The mandatory platform macros are: + +- PLATFORM\_CORE\_COUNT +- PLAT\_MAX\_PWR\_LVL +- PLAT\_NUM\_PWR\_DOMAINS +- CACHE\_WRITEBACK\_GRANULE +- PLAT\_MAX\_OFF\_STATE +- PLAT\_MAX\_RET\_STATE +- PLAT\_MAX\_PWR\_LVL\_STATES (optional) +- PLAT\_PCPU\_DATA\_SIZE (optional) + +The details of these APIs/macros can be found in `Porting Guide`_. + +All platform specific operations for power management are done via +``plat_psci_ops_t`` callbacks registered by the platform when +``plat_setup_psci_ops()`` API is called. The description of each of +the callbacks in ``plat_psci_ops_t`` can be found in PSCI section of the +`Porting Guide`_. If any these callbacks are not registered, then the +PSCI API associated with that callback will not be supported by PSCI +library. + +Secure payload power management callback +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During PSCI power management operations, the EL3 Runtime Software may +need to perform some bookkeeping, and PSCI library provides +``spd_pm_ops_t`` callbacks for this purpose. These hooks must be +populated and registered by using ``psci_register_spd_pm_hook()`` PSCI +library interface. + +Typical bookkeeping during PSCI power management calls include save/restore +of the EL3 Runtime Software context. Also if the EL3 Runtime Software makes +use of secure interrupts, then these interrupts must also be managed +appropriately during CPU power down/power up. Any secure interrupt targeted +to the current CPU must be disabled or re-targeted to other running CPU prior +to power down of the current CPU. During power up, these interrupt can be +enabled/re-targeted back to the current CPU. + +.. code:: c + + typedef struct spd_pm_ops { + void (*svc_on)(u_register_t target_cpu); + int32_t (*svc_off)(u_register_t __unused); + void (*svc_suspend)(u_register_t max_off_pwrlvl); + void (*svc_on_finish)(u_register_t __unused); + void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); + int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); + int32_t (*svc_migrate_info)(u_register_t *resident_cpu); + void (*svc_system_off)(void); + void (*svc_system_reset)(void); + } spd_pm_ops_t; + +A brief description of each callback is given below: + +- svc\_on, svc\_off, svc\_on\_finish + + The ``svc_on``, ``svc_off`` callbacks are called during PSCI\_CPU\_ON, + PSCI\_CPU\_OFF APIs respectively. The ``svc_on_finish`` is called when the + target CPU of PSCI\_CPU\_ON API powers up and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. + +- svc\_suspend, svc\_suspend\_finish + + The ``svc_suspend`` callback is called during power down bu either + PSCI\_SUSPEND or PSCI\_SYSTEM\_SUSPEND APIs. The ``svc_suspend_finish`` is + called when the CPU wakes up from suspend and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. The ``max_off_pwrlvl`` + (first parameter) denotes the highest power domain level being powered down + to or woken up from suspend. + +- svc\_system\_off, svc\_system\_reset + + These callbacks are called during PSCI\_SYSTEM\_OFF and PSCI\_SYSTEM\_RESET + PSCI APIs respectively. + +- svc\_migrate\_info + + This callback is called in response to PSCI\_MIGRATE\_INFO\_TYPE or + PSCI\_MIGRATE\_INFO\_UP\_CPU APIs. The return value of this callback must + correspond to the return value of PSCI\_MIGRATE\_INFO\_TYPE API as described + in `PSCI spec`_. If the secure payload is a Uniprocessor (UP) + implementation, then it must update the mpidr of the CPU it is resident in + via ``resident_cpu`` (first argument). The updates to ``resident_cpu`` is + ignored if the secure payload is a multiprocessor (MP) implementation. + +- svc\_migrate + + This callback is only relevant if the secure payload in EL3 Runtime + Software is a Uniprocessor (UP) implementation and supports migration from + the current CPU ``from_cpu`` (first argument) to another CPU ``to_cpu`` + (second argument). This callback is called in response to PSCI\_MIGRATE + API. This callback is never called if the secure payload is a + Multiprocessor (MP) implementation. + +CPU operations +~~~~~~~~~~~~~~ + +The CPU operations (cpu\_ops) framework implement power down sequence specific +to the CPU and the details of which can be found in the ``CPU specific operations framework`` section of `Firmware Design`_. The ARM Trusted Firmware +tree implements the ``cpu_ops`` for various supported CPUs and the EL3 Runtime +Software needs to include the required ``cpu_ops`` in its build. The start and +end of the ``cpu_ops`` descriptors must be exported by the EL3 Runtime Software +via the ``__CPU_OPS_START__`` and ``__CPU_OPS_END__`` linker symbols. + +The ``cpu_ops`` descriptors also include reset sequences and may include errata +workarounds for the CPU. The EL3 Runtime Software can choose to call this +during cold/warm reset if it does not implement its own reset sequence/errata +workarounds. + +-------------- + +*Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.* + +.. _PSCI spec: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _SMCCC: https://silver.arm.com/download/ARM_and_AMBA_Architecture/AR570-DA-80002-r0p0-00rel0/ARM_DEN0028A_SMC_Calling_Convention.pdf +.. _section 4: #user-content-psci-library-interface +.. _section 3: #user-content-psci-cpu-context-management +.. _PSCI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _section 5.2: #user-content-cpu-context-management-api +.. _PSCI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _section 5.4: #user-content-secure-payload-power-management-callback +.. _Porting Guide: porting-guide.rst +.. _Firmware Design: ./firmware-design.rst diff --git a/docs/psci-pd-tree.rst b/docs/psci-pd-tree.rst new file mode 100644 index 0000000..329106c --- /dev/null +++ b/docs/psci-pd-tree.rst @@ -0,0 +1,312 @@ +PSCI Library Integration guide for ARMv8-A AArch32 systems +========================================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +-------------- + +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: + +:: + + #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. + +:: + + 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, ARM Limited and Contributors. All rights reserved.* diff --git a/docs/reset-design.rst b/docs/reset-design.rst new file mode 100644 index 0000000..0b14dec --- /dev/null +++ b/docs/reset-design.rst @@ -0,0 +1,166 @@ +ARM Trusted Firmware Reset Design +================================= + + +.. section-numbering:: + :suffix: . + +.. contents:: + +This document describes the high-level design of the framework to handle CPU +resets in ARM Trusted Firmware. 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 `Firmware Design`_, which +provides greater implementation details around the reset code, specifically +for the cold boot path. + +General reset code flow +----------------------- + +The ARM Trusted Firmware (TF) 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 Trusted Firmware 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, the TF 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 the TF with ``PROGRAMMABLE_RESET_ADDRESS=1``. +This option only affects the TF 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, the TF 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 the TF with ``COLD_BOOT_SINGLE_CPU=1``. This +option only affects the TF 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 the TF with both ``COLD_BOOT_SINGLE_CPU=1`` +and ``PROGRAMMABLE_RESET_ADDRESS=1``. These options only affect the TF 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 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 `User Guide`_ 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 are 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. + +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, ARM Limited and Contributors. All rights reserved.* + +.. _Firmware Design: firmware-design.rst +.. _User Guide: user-guide.rst + +.. |Default reset code flow| image:: diagrams/default_reset_code.png?raw=true +.. |Reset code flow with programmable reset address| image:: diagrams/reset_code_no_boot_type_check.png?raw=true +.. |Reset code flow with single CPU released out of reset| image:: diagrams/reset_code_no_cpu_check.png?raw=true +.. |Reset code flow with programmable reset address and single CPU released out of reset| image:: diagrams/reset_code_no_checks.png?raw=true diff --git a/docs/rt-svc-writers-guide.rst b/docs/rt-svc-writers-guide.rst new file mode 100644 index 0000000..6a64ade --- /dev/null +++ b/docs/rt-svc-writers-guide.rst @@ -0,0 +1,316 @@ +EL3 Runtime Service Writers Guide for ARM Trusted Firmware +========================================================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +-------------- + +Introduction +------------ + +This document describes how to add a runtime service to the EL3 Runtime +Firmware component of ARM Trusted Firmware (BL31). + +Software executing in the normal world and in the trusted world at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +results are returned. + +SMC Functions are grouped together based on the implementor of the service, for +example a subset of the Function IDs are designated as "OEM Calls" (see `SMCCC`_ +for full details). The EL3 runtime services framework in BL31 enables the +independent implementation of services for each group, which are then compiled +into the BL31 image. This simplifies the integration of common software from +ARM to support `PSCI`_, Secure Monitor for a Trusted OS and SoC specific +software. The common runtime services framework ensures that SMC Functions are +dispatched to their respective service implementation - the `Firmware Design`_ +provides details of how this is achieved. + +The interface and operation of the runtime services depends heavily on the +concepts and definitions described in the `SMCCC`_, in particular SMC Function +IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and +SMC64 calling conventions. Please refer to that document for a full explanation +of these terms. + +Owning Entities, Call Types and Function IDs +-------------------------------------------- + +The SMC Function Identifier includes a OEN field. These values and their +meaning are described in `SMCCC`_ and summarized in table 1 below. Some entities +are allocated a range of of OENs. The OEN must be interpreted in conjunction +with the SMC call type, which is either *Fast* or *Yielding*. Fast calls are +uninterruptible whereas Yielding calls can be pre-empted. The majority of +Owning Entities only have allocated ranges for Fast calls: Yielding calls are +reserved exclusively for Trusted OS providers or for interoperability with +legacy 32-bit software that predates the `SMCCC`_. + +:: + + Type OEN Service + Fast 0 ARM Architecture calls + Fast 1 CPU Service calls + Fast 2 SiP Service calls + Fast 3 OEM Service calls + Fast 4 Standard Service calls + Fast 5-47 Reserved for future use + Fast 48-49 Trusted Application calls + Fast 50-63 Trusted OS calls + + Yielding 0- 1 Reserved for existing ARMv7 calls + Yielding 2-63 Trusted OS Standard Calls + +*Table 1: Service types and their corresponding Owning Entity Numbers* + +Each individual entity can allocate the valid identifiers within the entity +range as they need - it is not necessary to coordinate with other entities of +the same type. For example, two SoC providers can use the same Function ID +within the SiP Service calls OEN range to mean different things - as these +calls should be specific to the SoC. The Standard Runtime Calls OEN is used for +services defined by ARM standards, such as `PSCI`_. + +The SMC Function ID also indicates whether the call has followed the SMC32 +calling convention, where all parameters are 32-bit, or the SMC64 calling +convention, where the parameters are 64-bit. The framework identifies and +rejects invalid calls that use the SMC64 calling convention but that originate +from an AArch32 caller. + +The EL3 runtime services framework uses the call type and OEN to identify a +specific handler for each SMC call, but it is expected that an individual +handler will be responsible for all SMC Functions within a given service type. + +Getting started +--------------- + +ARM Trusted Firmware has a `services`_ directory in the source tree under which +each owning entity can place the implementation of its runtime service. The +`PSCI`_ implementation is located here in the `lib/psci`_ directory. + +Runtime service sources will need to include the `runtime\_svc.h`_ header file. + +Registering a runtime service +----------------------------- + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. + +:: + + #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) + +- ``_name`` is used to identify the data structure declared by this macro, and + is also used for diagnostic purposes + +- ``_start`` and ``_end`` values must be based on the ``OEN_*`` values defined in + `smcc.h`_ + +- ``_type`` must be one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` + +- ``_setup`` is the initialization function with the ``rt_svc_init`` signature: + + .. code:: c + + typedef int32_t (*rt_svc_init)(void); + +- ``_smch`` is the SMC handler function with the ``rt_svc_handle`` signature: + + .. code:: c + + typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, + u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +Details of the requirements and behavior of the two callbacks is provided in +the following sections. + +During initialization the services framework validates each declared service +to ensure that the following conditions are met: + +#. The ``_start`` OEN is not greater than the ``_end`` OEN +#. The ``_end`` OEN does not exceed the maximum OEN value (63) +#. The ``_type`` is one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` +#. ``_setup`` and ``_smch`` routines have been specified + +`std\_svc\_setup.c`_ provides an example of registering a runtime service: + +.. code:: c + + /* Register Standard Service Calls as runtime service */ + DECLARE_RT_SVC( + std_svc, + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler + ); + +Initializing a runtime service +------------------------------ + +Runtime services are initialized once, during cold boot, by the primary CPU +after platform and architectural initialization is complete. The framework +performs basic validation of the declared service before calling +the service initialization function (``_setup`` in the declaration). This +function must carry out any essential EL3 initialization prior to receiving a +SMC Function call via the handler function. + +On success, the initialization function must return ``0``. Any other return value +will cause the framework to issue a diagnostic: + +:: + + Error initializing runtime service + +and then ignore the service - the system will continue to boot but SMC calls +will not be passed to the service handler and instead return the *Unknown SMC +Function ID* result ``0xFFFFFFFF``. + +If the system must not be allowed to proceed without the service, the +initialization function must itself cause the firmware boot to be halted. + +If the service uses per-CPU data this must either be initialized for all CPUs +during this call, or be done lazily when a CPU first issues an SMC call to that +service. + +Handling runtime service requests +--------------------------------- + +SMC calls for a service are forwarded by the framework to the service's SMC +handler function (``_smch`` in the service declaration). This function must have +the following signature: + +.. code:: c + + typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, + u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +The handler is responsible for: + +#. Determining that ``smc_fid`` is a valid and supported SMC Function ID, + otherwise completing the request with the *Unknown SMC Function ID*: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Determining if the requested function is valid for the calling security + state. SMC Calls can be made from both the normal and trusted worlds and + the framework will forward all calls to the service handler. + + The ``flags`` parameter to this function indicates the caller security state + in bit[0], where a value of ``1`` indicates a non-secure caller. The + ``is_caller_secure(flags)`` and ``is_caller_non_secure(flags)`` can be used to + test this condition. + + If invalid, the request should be completed with: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Truncating parameters for calls made using the SMC32 calling convention. + Such calls can be determined by checking the CC field in bit[30] of the + ``smc_fid`` parameter, for example by using: + + :: + + if (GET_SMC_CC(smc_fid) == SMC_32) ... + + For such calls, the upper bits of the parameters x1-x4 and the saved + parameters X5-X7 are UNDEFINED and must be explicitly ignored by the + handler. This can be done by truncating the values to a suitable 32-bit + integer type before use, for example by ensuring that functions defined + to handle individual SMC Functions use appropriate 32-bit parameters. + +#. Providing the service requested by the SMC Function, utilizing the + immediate parameters x1-x4 and/or the additional saved parameters X5-X7. + The latter can be retrieved using the ``SMC_GET_GP(handle, ref)`` function, + supplying the appropriate ``CTX_GPREG_Xn`` reference, e.g. + + .. code:: c + + uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6); + +#. Implementing the standard SMC32 Functions that provide information about + the implementation of the service. These are the Call Count, Implementor + UID and Revision Details for each service documented in section 6 of the + `SMCCC`_. + + The ARM Trusted Firmware expects owning entities to follow this + recommendation. + +#. Returning the result to the caller. The `SMCCC`_ allows for up to 256 bits + of return value in SMC64 using X0-X3 and 128 bits in SMC32 using W0-W3. The + framework provides a family of macros to set the multi-register return + value and complete the handler: + + .. code:: c + + SMC_RET1(handle, x0); + SMC_RET2(handle, x0, x1); + SMC_RET3(handle, x0, x1, x2); + SMC_RET4(handle, x0, x1, x2, x3); + +The ``cookie`` parameter to the handler is reserved for future use and can be +ignored. The ``handle`` is returned by the SMC handler - completion of the +handler function must always be via one of the ``SMC_RETn()`` macros. + +NOTE: The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow +all of the above requirements yet. + +Services that contain multiple sub-services +------------------------------------------- + +It is possible that a single owning entity implements multiple sub-services. For +example, the Standard calls service handles ``0x84000000``-``0x8400FFFF`` and +``0xC4000000``-``0xC400FFFF`` functions. Within that range, the `PSCI`_ service +handles the ``0x84000000``-``0x8400001F`` and ``0xC4000000``-``0xC400001F`` functions. +In that respect, `PSCI`_ is a 'sub-service' of the Standard calls service. In +future, there could be additional such sub-services in the Standard calls +service which perform independent functions. + +In this situation it may be valuable to introduce a second level framework to +enable independent implementation of sub-services. Such a framework might look +very similar to the current runtime services framework, but using a different +part of the SMC Function ID to identify the sub-service. Trusted Firmware does +not provide such a framework at present. + +Secure-EL1 Payload Dispatcher service (SPD) +------------------------------------------- + +Services that handle SMC Functions targeting a Trusted OS, Trusted Application, +or other Secure-EL1 Payload are special. These services need to manage the +Secure-EL1 context, provide the *Secure Monitor* functionality of switching +between the normal and secure worlds, deliver SMC Calls through to Secure-EL1 +and generally manage the Secure-EL1 Payload through CPU power-state transitions. + +TODO: Provide details of the additional work required to implement a SPD and +the BL31 support for these services. Or a reference to the document that will +provide this information.... + +-------------- + +*Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.* + +.. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _Firmware Design: ./firmware-design.rst +.. _services: ../services +.. _lib/psci: ../lib/psci +.. _runtime\_svc.h: ../include/common/runtime_svc.h +.. _smcc.h: ../include/lib/smcc.h +.. _std\_svc\_setup.c: ../services/std_svc/std_svc_setup.c diff --git a/docs/spd/optee-dispatcher.rst b/docs/spd/optee-dispatcher.rst new file mode 100644 index 0000000..e55926b --- /dev/null +++ b/docs/spd/optee-dispatcher.rst @@ -0,0 +1,14 @@ +OP-TEE Dispatcher +================= + +`OP-TEE OS`_ is a Trusted OS running as Secure EL1. + +To build and execute OP-TEE follow the instructions at +`OP-TEE build.git`_ + +-------------- + +*Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.* + +.. _OP-TEE OS: https://github.com/OP-TEE/build +.. _OP-TEE build.git: https://github.com/OP-TEE/build diff --git a/docs/spd/tlk-dispatcher.rst b/docs/spd/tlk-dispatcher.rst new file mode 100644 index 0000000..cd37652 --- /dev/null +++ b/docs/spd/tlk-dispatcher.rst @@ -0,0 +1,76 @@ +Trusted Little Kernel (TLK) Dispatcher +====================================== + +TLK dispatcher adds support for NVIDIA's Trusted Little Kernel (TLK) to work +with the Trusted Firmware. TLK-D can be compiled by including it in the +platform's makefile. TLK is primarily meant to work with Tegra SoCs, so until +Trusted Firmware starts supporting Tegra, the dispatcher code can only be +compiled for other platforms. + +In order to compile TLK-D, we need a BL32 image to be present. Since, TLKD +just needs to compile, any BL32 image would do. To use TLK as the BL32, please +refer to the "Build TLK" section. + +Once a BL32 is ready, TLKD can be included in the image by adding "SPD=tlkd" +to the build command. + +Trusted Little Kernel (TLK) +=========================== + +TLK is a Trusted OS running as Secure EL1. It is a Free Open Source Software +(FOSS) release of the NVIDIA® Trusted Little Kernel (TLK) technology, which +extends technology made available with the development of the Little Kernel (LK). +You can download the LK modular embedded preemptive kernel for use on ARM, +x86, and AVR32 systems from https://github.com/travisg/lk + +NVIDIA implemented its Trusted Little Kernel (TLK) technology, designed as a +free and open-source trusted execution environment (OTE). + +TLK features include: + +• Small, pre-emptive kernel +• Supports multi-threading, IPCs, and thread scheduling +• Added TrustZone features +• Added Secure Storage +• Under MIT/FreeBSD license + +NVIDIA extensions to Little Kernel (LK) include: + +• User mode +• Address-space separation for TAs +• TLK Client Application (CA) library +• TLK TA library +• Crypto library (encrypt/decrypt, key handling) via OpenSSL +• Linux kernel driver +• Cortex A9/A15 support +• Power Management +• TrustZone memory carve-out (reconfigurable) +• Page table management +• Debugging support over UART (USB planned) + +TLK is hosted by NVIDIA on http://nv-tegra.nvidia.com under the +3rdparty/ote\_partner/tlk.git repository. Detailed information about +TLK and OTE can be found in the Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf +manual located under the "documentation" directory\_. + +Build TLK +========= + +To build and execute TLK, follow the instructions from "Building a TLK Device" +section from Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf manual. + +Input parameters to TLK +======================= + +TLK expects the TZDRAM size and a structure containing the boot arguments. BL2 +passes this information to the EL3 software as members of the bl32\_ep\_info +struct, where bl32\_ep\_info is part of bl31\_params\_t (passed by BL2 in X0) + +Example: +-------- + +:: + + bl32_ep_info->args.arg0 = TZDRAM size available for BL32 + bl32_ep_info->args.arg1 = unused (used only on ARMv7) + bl32_ep_info->args.arg2 = pointer to boot args diff --git a/docs/spd/trusty-dispatcher.rst b/docs/spd/trusty-dispatcher.rst new file mode 100644 index 0000000..f1982ea --- /dev/null +++ b/docs/spd/trusty-dispatcher.rst @@ -0,0 +1,15 @@ +Trusty Dispatcher +================= + +Trusty is a a set of software components, supporting a Trusted Execution +Environment (TEE) on mobile devices, published and maintained by Google. + +Detailed information and build instructions can be found on the Android +Open Source Project (AOSP) webpage for Trusty hosted at +https://source.android.com/security/trusty + +Supported platforms +=================== + +Out of all the platforms supported by the ARM Trusted Firmware, Trusty is +verified and supported by NVIDIA's Tegra SoCs. diff --git a/docs/trusted-board-boot.rst b/docs/trusted-board-boot.rst new file mode 100644 index 0000000..6a28da0 --- /dev/null +++ b/docs/trusted-board-boot.rst @@ -0,0 +1,238 @@ +Trusted Board Boot Design Guide +=============================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +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 ARM Trusted Firmware TBB, which is an +implementation of the Trusted Board Boot Requirements (TBBR) specification, +ARM DEN0006C-1. It should be used in conjunction with the `Firmware Update`_ +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. + +- 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, the PKCS#1 SHA-256 with RSA Encryption +signature scheme is used with a RSA key length of 2048 bits. Future version of +Trusted Firmware will support additional cryptographic algorithms. + +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. The SHA-256 function is +used to calculate all hashes. 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. + +- **BL3-X keys** + + For each of SCP\_BL2, BL31, BL32 and BL33, the private part is used to + sign the content certificate for the BL3-X 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 the `User Guide`_. + +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 the Trusted Firmware. + +The mechanism used for generating the FIP and the Authentication module are +described in the following sections. + +Authentication Framework +------------------------ + +The authentication framework included in the Trusted Firmware provides support +to implement the desired trusted boot sequence. ARM platforms use this framework +to implement the boot requirements specified in the TBBR-client document. + +More information about the authentication framework can be found in the +`Auth Framework`_ document. + +Certificate Generation Tool +--------------------------- + +The ``cert_create`` tool is built and runs on the host machine as part of the +Trusted Firmware 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 in the output build +directory. + +The tool resides in the ``tools/cert_create`` directory. It uses OpenSSL SSL +library version 1.0.1 or later to generate the X.509 certificates. Instructions +for building and using the tool can be found in the `User Guide`_. + +-------------- + +*Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.* + +.. _Firmware Update: firmware-update.rst +.. _X.509 v3: http://www.ietf.org/rfc/rfc5280.txt +.. _User Guide: user-guide.rst +.. _Auth Framework: auth-framework.rst diff --git a/docs/user-guide.rst b/docs/user-guide.rst new file mode 100644 index 0000000..6962cb6 --- /dev/null +++ b/docs/user-guide.rst @@ -0,0 +1,1737 @@ +ARM Trusted Firmware User Guide +=============================== + + +.. section-numbering:: + :suffix: . + +.. contents:: + +This document describes how to build ARM Trusted Firmware (TF) and run it with a +tested set of other software components using defined configurations on the Juno +ARM development platform and ARM Fixed Virtual Platform (FVP) models. It is +possible to use other software components, configurations and platforms but that +is outside the scope of this document. + +This document assumes that the reader has previous experience running a fully +bootable Linux software stack on Juno or FVP using the prebuilt binaries and +filesystems provided by `Linaro`_. Further information may +be found in the `Instructions for using the Linaro software deliverables`_. It also assumes that the user understands the role of +the different software components required to boot a Linux system: + +- Specific firmware images required by the platform (e.g. SCP firmware on Juno) +- Normal world bootloader (e.g. UEFI or U-Boot) +- Device tree +- Linux kernel image +- Root filesystem + +Note: the ARM TF v1.3 release was tested with Linaro Release 16.06, and the +latest version of ARM TF is tested with Linaro Release 17.01. + +This document also assumes that the user is familiar with the FVP models and +the different command line options available to launch the model. + +This document should be used in conjunction with the `Firmware Design`_. + +Host machine requirements +------------------------- + +The minimum recommended machine specification for building the software and +running the FVP models is a dual-core processor running at 2GHz with 12GB of +RAM. For best performance, use a machine with a quad-core processor running at +2.6GHz with 16GB of RAM. + +The software has been tested on Ubuntu 14.04 LTS (64-bit). Packages used for +building the software were installed from that distribution unless otherwise +specified. + +The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE, +Cygwin, and Msys (MinGW) shells, using version 4.9.1 of the GNU toolchain. + +Tools +----- + +Install the required packages to build Trusted Firmware with the following +command: + +:: + + sudo apt-get install build-essential gcc make git libssl-dev + +Download and install the AArch32 or AArch64 little-endian GCC cross compiler. +The `Linaro Release Notes`_ documents which version of the +compiler to use for a given Linaro Release. Also, these +`Linaro instructions`_ provide further guidance. + +Optionally, Trusted Firmware can be built using clang or ARM Compiler 6. +See instructions below on how to switch the default compiler. + +In addition, the following optional packages and tools may be needed: + +- ``device-tree-compiler`` package if you need to rebuild the Flattened Device + Tree (FDT) source files (``.dts`` files) provided with this software. + +- For debugging, ARM `Development Studio 5 (DS-5)`_. + +Getting the Trusted Firmware source code +---------------------------------------- + +Download the Trusted Firmware source code from Github: + +:: + + git clone https://github.com/ARM-software/arm-trusted-firmware.git + +Building the Trusted Firmware +----------------------------- + +- Before building Trusted Firmware, the environment variable ``CROSS_COMPILE`` + must point to the Linaro cross compiler. + + For AArch64: + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + + For AArch32: + + :: + + export CROSS_COMPILE=/bin/arm-linux-gnueabihf- + + It is possible to build Trusted Firmware using clang or ARM Compiler 6. + To do so ``CC`` needs to point to the clang or armclang binary. Only the + compiler is switched; the assembler and linker need to be provided by + the GNU toolchain, thus ``CROSS_COMPILE`` should be set as described above. + + ARM Compiler 6 will be selected when the base name of the path assigned + to ``CC`` matches the string 'armclang'. + + For AArch64 using ARM Compiler 6: + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + make CC=/bin/armclang PLAT= all + + Clang will be selected when the base name of the path assigned to ``CC`` + contains the string 'clang'. This is to allow both clang and clang-X.Y + to work. + + For AArch64 using clang: + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + make CC=/bin/clang PLAT= all + +- Change to the root directory of the Trusted Firmware source tree and build. + + For AArch64: + + :: + + make PLAT= all + + For AArch32: + + :: + + make PLAT= ARCH=aarch32 AARCH32_SP=sp_min all + + Notes: + + - If ``PLAT`` is not specified, ``fvp`` is assumed by default. See the + `Summary of build options`_ for more information on available build + options. + + - (AArch32 only) Currently only ``PLAT=fvp`` is supported. + + - (AArch32 only) ``AARCH32_SP`` is the AArch32 EL3 Runtime Software and it + corresponds to the BL32 image. A minimal ``AARCH32_SP``, sp\_min, is + provided by ARM Trusted Firmware to demonstrate how PSCI Library can + be integrated with an AArch32 EL3 Runtime Software. Some AArch32 EL3 + Runtime Software may include other runtime services, for example + Trusted OS services. A guide to integrate PSCI library with AArch32 + EL3 Runtime Software can be found `here`_. + + - (AArch64 only) The TSP (Test Secure Payload), corresponding to the BL32 + image, is not compiled in by default. Refer to the + `Building the Test Secure Payload`_ section below. + + - By default this produces a release version of the build. To produce a + debug version instead, refer to the "Debugging options" section below. + + - The build process creates products in a ``build`` directory tree, building + the objects and binaries for each boot loader stage in separate + sub-directories. The following boot loader binary files are created + from the corresponding ELF files: + + - ``build///bl1.bin`` + - ``build///bl2.bin`` + - ``build///bl31.bin`` (AArch64 only) + - ``build///bl32.bin`` (mandatory for AArch32) + + where ```` is the name of the chosen platform and ```` + is either ``debug`` or ``release``. The actual number of images might differ + depending on the platform. + +- Build products for a specific build variant can be removed using: + + :: + + make DEBUG= PLAT= clean + + ... where ```` is ``0`` or ``1``, as specified when building. + + The build tree can be removed completely using: + + :: + + make realclean + +Summary of build options +~~~~~~~~~~~~~~~~~~~~~~~~ + +ARM Trusted Firmware build system supports the following build options. Unless +mentioned otherwise, these options are expected to be specified at the build +command line and are not to be modified in any component makefiles. Note that +the build system doesn't track dependency for build options. Therefore, if any +of the build options are changed from a previous build, a clean build must be +performed. + +Common build options +^^^^^^^^^^^^^^^^^^^^ + +- ``AARCH32_SP`` : Choose the AArch32 Secure Payload component to be built as + as the BL32 image when ``ARCH=aarch32``. The value should be the path to the + directory containing the SP source, relative to the ``bl32/``; the directory + is expected to contain a makefile called ``.mk``. + +- ``ARCH`` : Choose the target build architecture for ARM Trusted Firmware. + It can take either ``aarch64`` or ``aarch32`` as values. By default, it is + defined to ``aarch64``. + +- ``ARM_CCI_PRODUCT_ID``: Choice of ARM CCI product used by the platform. This + is used to determine the number of valid slave interfaces available in the + ARM CCI driver. Default is 400 (that is, CCI-400). + +- ``ARM_ARCH_MAJOR``: The major version of ARM Architecture to target when + compiling ARM Trusted Firmware. Its value must be numeric, and defaults to + 8 . See also, *ARMv8 Architecture Extensions* in `Firmware Design`_. + +- ``ARM_ARCH_MINOR``: The minor version of ARM Architecture to target when + compiling ARM Trusted Firmware. Its value must be a numeric, and defaults + to 0. See also, *ARMv8 Architecture Extensions* in `Firmware Design`_. + +- ``ARM_GIC_ARCH``: Choice of ARM GIC architecture version used by the ARM + Legacy GIC driver for implementing the platform GIC API. This API is used + by the interrupt management framework. Default is 2 (that is, version 2.0). + This build option is deprecated. + +- ``ARM_PLAT_MT``: This flag determines whether the ARM platform layer has to + cater for the multi-threading ``MT`` bit when accessing MPIDR. When this + flag is set, the functions which deal with MPIDR assume that the ``MT`` bit + in MPIDR is set and access the bit-fields in MPIDR accordingly. Default + value of this flag is 0. + +- ``BL2``: This is an optional build option which specifies the path to BL2 + image for the ``fip`` target. In this case, the BL2 in the ARM Trusted + Firmware will not be built. + +- ``BL2U``: This is an optional build option which specifies the path to + BL2U image. In this case, the BL2U in the ARM Trusted Firmware will not + be built. + +- ``BL31``: This is an optional build option which specifies the path to + BL31 image for the ``fip`` target. In this case, the BL31 in the ARM + Trusted Firmware will not be built. + +- ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL31 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL32``: This is an optional build option which specifies the path to + BL32 image for the ``fip`` target. In this case, the BL32 in the ARM + Trusted Firmware will not be built. + +- ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL32 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL33``: Path to BL33 image in the host file system. This is mandatory for + ``fip`` target in case the BL2 from ARM Trusted Firmware is used. + +- ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL33 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BUILD_MESSAGE_TIMESTAMP``: String used to identify the time and date of the + compilation of each build. It must be set to a C string (including quotes + where applicable). Defaults to a string that contains the time and date of + the compilation. + +- ``BUILD_STRING``: Input string for VERSION\_STRING, which allows the TF build + to be uniquely identified. Defaults to the current git commit id. + +- ``CFLAGS``: Extra user options appended on the compiler's command line in + addition to the options set by the build system. + +- ``COLD_BOOT_SINGLE_CPU``: This option indicates whether the platform may + release several CPUs out of reset. It can take either 0 (several CPUs may be + brought up) or 1 (only one CPU will ever be brought up during cold reset). + Default is 0. If the platform always brings up a single CPU, there is no + need to distinguish between primary and secondary CPUs and the boot path can + be optimised. The ``plat_is_my_cpu_primary()`` and + ``plat_secondary_cold_boot_setup()`` platform porting interfaces do not need + to be implemented in this case. + +- ``CRASH_REPORTING``: A non-zero value enables a console dump of processor + register state when an unexpected exception occurs during execution of + BL31. This option defaults to the value of ``DEBUG`` - i.e. by default + this is only enabled for a debug build of the firmware. + +- ``CREATE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to create new keys in case no valid keys are + present or specified. Allowed options are '0' or '1'. Default is '1'. + +- ``CTX_INCLUDE_AARCH32_REGS`` : Boolean option that, when set to 1, will cause + the AArch32 system registers to be included when saving and restoring the + CPU context. The option must be set to 0 for AArch64-only platforms (that + is on hardware that does not implement AArch32, or at least not at EL1 and + higher ELs). Default value is 1. + +- ``CTX_INCLUDE_FPREGS``: Boolean option that, when set to 1, will cause the FP + registers to be included when saving and restoring the CPU context. Default + is 0. + +- ``DEBUG``: Chooses between a debug and release build. It can take either 0 + (release) or 1 (debug) as values. 0 is the default. + +- ``EL3_PAYLOAD_BASE``: This option enables booting an EL3 payload instead of + the normal boot flow. It must specify the entry point address of the EL3 + payload. Please refer to the "Booting an EL3 payload" section for more + details. + +- ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` + are compiled out. For debug builds, this option defaults to 1, and calls to + ``assert()`` are left in place. For release builds, this option defaults to 0 + and calls to ``assert()`` function are compiled out. This option can be set + independently of ``DEBUG``. It can also be used to hide any auxiliary code + that is only required for the assertion and does not fit in the assertion + itself. + +- ``ENABLE_PMF``: Boolean option to enable support for optional Performance + Measurement Framework(PMF). Default is 0. + +- ``ENABLE_PSCI_STAT``: Boolean option to enable support for optional PSCI + functions ``PSCI_STAT_RESIDENCY`` and ``PSCI_STAT_COUNT``. Default is 0. + In the absence of an alternate stat collection backend, ``ENABLE_PMF`` must + be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in + software. + +- ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime + instrumentation which injects timestamp collection points into + Trusted Firmware to allow runtime performance to be measured. + Currently, only PSCI is instrumented. Enabling this option enables + the ``ENABLE_PMF`` build option as well. Default is 0. + +- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection + checks in GCC. Allowed values are "all", "strong" and "0" (default). + "strong" is the recommended stack protection level if this feature is + desired. 0 disables the stack protection. For all values other than 0, the + ``plat_get_stack_protector_canary()`` platform hook needs to be implemented. + The value is passed as the last component of the option + ``-fstack-protector-$ENABLE_STACK_PROTECTOR``. + +- ``ERROR_DEPRECATED``: This option decides whether to treat the usage of + deprecated platform APIs, helper functions or drivers within Trusted + Firmware as error. It can take the value 1 (flag the use of deprecated + APIs as error) or 0. The default is 0. + +- ``FIP_NAME``: This is an optional build option which specifies the FIP + filename for the ``fip`` target. Default is ``fip.bin``. + +- ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU + FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``. + +- ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create`` + tool to create certificates as per the Chain of Trust described in + `Trusted Board Boot`_. The build system then calls ``fiptool`` to + include the certificates in the FIP and FWU\_FIP. Default value is '0'. + + Specify both ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=1`` to include support + for the Trusted Board Boot feature in the BL1 and BL2 images, to generate + the corresponding certificates, and to include those certificates in the + FIP and FWU\_FIP. + + Note that if ``TRUSTED_BOARD_BOOT=0`` and ``GENERATE_COT=1``, the BL1 and BL2 + images will not include support for Trusted Board Boot. The FIP will still + include the corresponding certificates. This FIP can be used to verify the + Chain of Trust on the host machine through other mechanisms. + + Note that if ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=0``, the BL1 and BL2 + images will include support for Trusted Board Boot, but the FIP and FWU\_FIP + will not include the corresponding certificates, causing a boot failure. + +- ``HANDLE_EA_EL3_FIRST``: When defined External Aborts and SError Interrupts + will be always trapped in EL3 i.e. in BL31 at runtime. + +- ``HW_ASSISTED_COHERENCY``: On most ARM systems to-date, platform-specific + software operations are required for CPUs to enter and exit coherency. + However, there exists newer systems where CPUs' entry to and exit from + coherency is managed in hardware. Such systems require software to only + initiate the operations, and the rest is managed in hardware, minimizing + active software management. In such systems, this boolean option enables ARM + Trusted Firmware to carry out build and run-time optimizations during boot + and power management operations. This option defaults to 0 and if it is + enabled, then it implies ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled. + +- ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3 + runtime software in AArch32 mode, which is required to run AArch32 on Juno. + By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in + AArch64 and facilitates the loading of ``SP_MIN`` and BL33 as AArch32 executable + images. + +- ``LDFLAGS``: Extra user options appended to the linkers' command line in + addition to the one set by the build system. + +- ``LOAD_IMAGE_V2``: Boolean option to enable support for new version (v2) of + image loading, which provides more flexibility and scalability around what + images are loaded and executed during boot. Default is 0. + Note: ``TRUSTED_BOARD_BOOT`` is currently only supported for AArch64 when + ``LOAD_IMAGE_V2`` is enabled. + +- ``LOG_LEVEL``: Chooses the log level, which controls the amount of console log + output compiled into the build. This should be one of the following: + + :: + + 0 (LOG_LEVEL_NONE) + 10 (LOG_LEVEL_NOTICE) + 20 (LOG_LEVEL_ERROR) + 30 (LOG_LEVEL_WARNING) + 40 (LOG_LEVEL_INFO) + 50 (LOG_LEVEL_VERBOSE) + + All log output up to and including the log level is compiled into the build. + The default value is 40 in debug builds and 20 in release builds. + +- ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Non-Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``NS_BL2U``: Path to NS\_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``NS_TIMER_SWITCH``: Enable save and restore for non-secure timer register + contents upon world switch. It can take either 0 (don't save and restore) or + 1 (do save and restore). 0 is the default. An SPD may set this to 1 if it + wants the timer registers to be saved and restored. + +- ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that + the underlying hardware is not a full PL011 UART but a minimally compliant + generic UART, which is a subset of the PL011. The driver will not access + any register that is not part of the SBSA generic UART specification. + Default value is 0 (a full PL011 compliant UART is present). + +- ``PLAT``: Choose a platform to build ARM Trusted Firmware for. The chosen + platform name must be subdirectory of any depth under ``plat/``, and must + contain a platform makefile named ``platform.mk``. + +- ``PRELOADED_BL33_BASE``: This option enables booting a preloaded BL33 image + instead of the normal boot flow. When defined, it must specify the entry + point address for the preloaded BL33 image. This option is incompatible with + ``EL3_PAYLOAD_BASE``. If both are defined, ``EL3_PAYLOAD_BASE`` has priority + over ``PRELOADED_BL33_BASE``. + +- ``PROGRAMMABLE_RESET_ADDRESS``: This option indicates whether the reset + vector address can be programmed or is fixed on the platform. It can take + either 0 (fixed) or 1 (programmable). Default is 0. If the platform has a + programmable reset address, it is expected that a CPU will start executing + code directly at the right address, both on a cold and warm reset. In this + case, there is no need to identify the entrypoint on boot and the boot path + can be optimised. The ``plat_get_my_entrypoint()`` platform porting interface + does not need to be implemented in this case. + +- ``PSCI_EXTENDED_STATE_ID``: As per PSCI1.0 Specification, there are 2 formats + possible for the PSCI power-state parameter viz original and extended + State-ID formats. This flag if set to 1, configures the generic PSCI layer + to use the extended format. The default value of this flag is 0, which + means by default the original power-state format is used by the PSCI + implementation. This flag should be specified by the platform makefile + and it governs the return value of PSCI\_FEATURES API for CPU\_SUSPEND + smc function id. When this option is enabled on ARM platforms, the + option ``ARM_RECOM_STATE_ID_ENC`` needs to be set to 1 as well. + +- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead + of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to BL31 entrypoint). + The default value is 0. + +- ``RESET_TO_SP_MIN``: SP\_MIN is the minimal AArch32 Secure Payload provided in + ARM Trusted Firmware. This flag configures SP\_MIN entrypoint as the CPU + reset vector instead of the BL1 entrypoint. It can take the value 0 (CPU + reset to BL1 entrypoint) or 1 (CPU reset to SP\_MIN entrypoint). The default + value is 0. + +- ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the ROT private key in PEM format. If ``SAVE_KEYS=1``, this + file name will be used to save the key. + +- ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to save the keys used to establish the Chain of + Trust. Allowed options are '0' or '1'. Default is '0' (do not save). + +- ``SCP_BL2``: Path to SCP\_BL2 image in the host file system. This image is optional. + If a SCP\_BL2 image is present then this option must be passed for the ``fip`` + target. + +- ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the SCP\_BL2 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``SCP_BL2U``: Path to SCP\_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``SEPARATE_CODE_AND_RODATA``: Whether code and read-only data should be + isolated on separate memory pages. This is a trade-off between security and + memory usage. See "Isolating code and read-only data on separate memory + pages" section in `Firmware Design`_. This flag is disabled by default and + affects all BL images. + +- ``SPD``: Choose a Secure Payload Dispatcher component to be built into the + Trusted Firmware. This build option is only valid if ``ARCH=aarch64``. The + value should be the path to the directory containing the SPD source, + relative to ``services/spd/``; the directory is expected to + contain a makefile called ``.mk``. + +- ``SPIN_ON_BL1_EXIT``: This option introduces an infinite loop in BL1. It can + take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops + execution in BL1 just before handing over to BL31. At this point, all + firmware images have been loaded in memory, and the MMU and caches are + turned off. Refer to the "Debugging options" section for more details. + +- ``TRUSTED_BOARD_BOOT``: Boolean flag to include support for the Trusted Board + Boot feature. When set to '1', BL1 and BL2 images include support to load + and verify the certificates and images in a FIP, and BL1 includes support + for the Firmware Update. The default value is '0'. Generation and inclusion + of certificates in the FIP and FWU\_FIP depends upon the value of the + ``GENERATE_COT`` option. + + Note: This option depends on ``CREATE_KEYS`` to be enabled. If the keys + already exist in disk, they will be overwritten without further notice. + +- ``TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``TSP_INIT_ASYNC``: Choose BL32 initialization method as asynchronous or + synchronous, (see "Initializing a BL32 Image" section in + `Firmware Design`_). It can take the value 0 (BL32 is initialized using + synchronous method) or 1 (BL32 is initialized using asynchronous method). + Default is 0. + +- ``TSP_NS_INTR_ASYNC_PREEMPT``: A non zero value enables the interrupt + routing model which routes non-secure interrupts asynchronously from TSP + to EL3 causing immediate preemption of TSP. The EL3 is responsible + for saving and restoring the TSP context in this routing model. The + default routing model (when the value is 0) is to route non-secure + interrupts to TSP allowing it to save its context and hand over + synchronously to EL3 via an SMC. + +- ``USE_COHERENT_MEM``: This flag determines whether to include the coherent + memory region in the BL memory map or not (see "Use of Coherent memory in + Trusted Firmware" section in `Firmware Design`_). It can take the value 1 + (Coherent memory region is included) or 0 (Coherent memory region is + excluded). Default is 1. + +- ``V``: Verbose build. If assigned anything other than 0, the build commands + are printed. Default is 0. + +- ``VERSION_STRING``: String used in the log output for each TF image. Defaults + to a string formed by concatenating the version number, build type and build + string. + +- ``WARMBOOT_ENABLE_DCACHE_EARLY`` : Boolean option to enable D-cache early on + the CPU after warm boot. This is applicable for platforms which do not + require interconnect programming to enable cache coherency (eg: single + cluster platforms). If this option is enabled, then warm boot path + enables D-caches immediately after enabling MMU. This option defaults to 0. + +- ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling + extensions. This is an optional architectural feature available only for + AArch64 8.2 onwards. This option defaults to 1 but is automatically + disabled when the target architecture is AArch32 or AArch64 8.0/8.1. + +ARM development platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``ARM_BL31_IN_DRAM``: Boolean option to select loading of BL31 in TZC secured + DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load + BL31 in TZC secured DRAM. If TSP is present, then setting this option also + sets the TSP location to DRAM and ignores the ``ARM_TSP_RAM_LOCATION`` build + flag. + +- ``ARM_BOARD_OPTIMISE_MEM``: Boolean option to enable or disable optimisation + of the memory reserved for each image. This affects the maximum size of each + BL image as well as the number of allocated memory regions and translation + tables. By default this flag is 0, which means it uses the default + unoptimised values for these macros. ARM development platforms that wish to + optimise memory usage need to set this flag to 1 and must override the + related macros. + +- ``ARM_CONFIG_CNTACR``: boolean option to unlock access to the ``CNTBase`` + frame registers by setting the ``CNTCTLBase.CNTACR`` register bits. The + frame number ```` is defined by ``PLAT_ARM_NSTIMER_FRAME_ID``, which should + match the frame used by the Non-Secure image (normally the Linux kernel). + Default is true (access to the frame is allowed). + +- ``ARM_DISABLE_TRUSTED_WDOG``: boolean option to disable the Trusted Watchdog. + By default, ARM platforms use a watchdog to trigger a system reset in case + an error is encountered during the boot process (for example, when an image + could not be loaded or authenticated). The watchdog is enabled in the early + platform setup hook at BL1 and disabled in the BL1 prepare exit hook. The + Trusted Watchdog may be disabled at build time for testing or development + purposes. + +- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding + for the construction of composite state-ID in the power-state parameter. + The existing PSCI clients currently do not support this encoding of + State-ID yet. Hence this flag is used to configure whether to use the + recommended State-ID encoding or not. The default value of this flag is 0, + in which case the platform is configured to expect NULL in the State-ID + field of power-state parameter. + +- ``ARM_ROTPK_LOCATION``: used when ``TRUSTED_BOARD_BOOT=1``. It specifies the + location of the ROTPK hash returned by the function ``plat_get_rotpk_info()`` + for ARM platforms. Depending on the selected option, the proper private key + must be specified using the ``ROT_KEY`` option when building the Trusted + Firmware. This private key will be used by the certificate generation tool + to sign the BL2 and Trusted Key certificates. Available options for + ``ARM_ROTPK_LOCATION`` are: + + - ``regs`` : return the ROTPK hash stored in the Trusted root-key storage + registers. The private key corresponding to this ROTPK hash is not + currently available. + - ``devel_rsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the RSA public key + ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use + this option, ``arm_rotprivk_rsa.pem`` must be specified as ``ROT_KEY`` when + creating the certificates. + +- ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options: + + - ``tsram`` : Trusted SRAM (default option) + - ``tdram`` : Trusted DRAM (if available) + - ``dram`` : Secure region in DRAM (configured by the TrustZone controller) + +- ``ARM_XLAT_TABLES_LIB_V1``: boolean option to compile the Trusted Firmware + with version 1 of the translation tables library instead of version 2. It is + set to 0 by default, which selects version 2. + +- ``ARM_CRYPTOCELL_INTEG`` : bool option to enable Trusted Firmware to invoke + ARM® TrustZone® CryptoCell functionality for Trusted Board Boot on capable + ARM platforms. If this option is specified, then the path to the CryptoCell + SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag. + +For a better understanding of these options, the ARM development platform memory +map is explained in the `Firmware Design`_. + +ARM CSS platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``CSS_DETECT_PRE_1_7_0_SCP``: Boolean flag to detect SCP version + incompatibility. Version 1.7.0 of the SCP firmware made a non-backwards + compatible change to the MTL protocol, used for AP/SCP communication. + Trusted Firmware no longer supports earlier SCP versions. If this option is + set to 1 then Trusted Firmware will detect if an earlier version is in use. + Default is 1. + +- ``CSS_LOAD_SCP_IMAGES``: Boolean flag, which when set, adds SCP\_BL2 and + SCP\_BL2U to the FIP and FWU\_FIP respectively, and enables them to be loaded + during boot. Default is 1. + +- ``CSS_USE_SCMI_DRIVER``: Boolean flag which selects SCMI driver instead of + SCPI driver for communicating with the SCP during power management operations. + If this option is set to 1, then SCMI driver will be used. Default is 0. + +ARM FVP platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``FVP_CLUSTER_COUNT`` : Configures the cluster count to be used to + build the topology tree within Trusted Firmware. By default the + Trusted Firmware is configured for dual cluster topology and this option + can be used to override the default value. + +- ``FVP_INTERCONNECT_DRIVER``: Selects the interconnect driver to be built. The + default interconnect driver depends on the value of ``FVP_CLUSTER_COUNT`` as + explained in the options below: + + - ``FVP_CCI`` : The CCI driver is selected. This is the default + if 0 < ``FVP_CLUSTER_COUNT`` <= 2. + - ``FVP_CCN`` : The CCN driver is selected. This is the default + if ``FVP_CLUSTER_COUNT`` > 2. + +- ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options: + + - ``FVP_GIC600`` : The GIC600 implementation of GICv3 is selected + - ``FVP_GICV2`` : The GICv2 only driver is selected + - ``FVP_GICV3`` : The GICv3 only driver is selected (default option) + - ``FVP_GICV3_LEGACY``: The Legacy GICv3 driver is selected (deprecated) + Note: If Trusted Firmware is compiled with this option on FVPs with + GICv3 hardware, then it configures the hardware to run in GICv2 + emulation mode + +- ``FVP_USE_SP804_TIMER`` : Use the SP804 timer instead of the Generic Timer + for functions that wait for an arbitrary time length (udelay and mdelay). + The default value is 0. + +Debugging options +~~~~~~~~~~~~~~~~~ + +To compile a debug version and make the build more verbose use + +:: + + make PLAT= DEBUG=1 V=1 all + +AArch64 GCC uses DWARF version 4 debugging symbols by default. Some tools (for +example DS-5) might not support this and may need an older version of DWARF +symbols to be emitted by GCC. This can be achieved by using the +``-gdwarf-`` flag, with the version being set to 2 or 3. Setting the +version to 2 is recommended for DS-5 versions older than 5.16. + +When debugging logic problems it might also be useful to disable all compiler +optimizations by using ``-O0``. + +NOTE: Using ``-O0`` could cause output images to be larger and base addresses +might need to be recalculated (see the **Memory layout on ARM development +platforms** section in the `Firmware Design`_). + +Extra debug options can be passed to the build system by setting ``CFLAGS`` or +``LDFLAGS``: + +.. code:: makefile + + CFLAGS='-O0 -gdwarf-2' \ + make PLAT= DEBUG=1 V=1 all + +Note that using ``-Wl,`` style compilation driver options in ``CFLAGS`` will be +ignored as the linker is called directly. + +It is also possible to introduce an infinite loop to help in debugging the +post-BL2 phase of the Trusted Firmware. This can be done by rebuilding BL1 with +the ``SPIN_ON_BL1_EXIT=1`` build flag. Refer to the "Summary of build options" +section. In this case, the developer may take control of the target using a +debugger when indicated by the console output. When using DS-5, the following +commands can be used: + +:: + + # Stop target execution + interrupt + + # + # Prepare your debugging environment, e.g. set breakpoints + # + + # Jump over the debug loop + set var $AARCH64::$Core::$PC = $AARCH64::$Core::$PC + 4 + + # Resume execution + continue + +Building the Test Secure Payload +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The TSP is coupled with a companion runtime service in the BL31 firmware, +called the TSPD. Therefore, if you intend to use the TSP, the BL31 image +must be recompiled as well. For more information on SPs and SPDs, see the +`Secure-EL1 Payloads and Dispatchers`_ section in the `Firmware Design`_. + +First clean the Trusted Firmware build directory to get rid of any previous +BL31 binary. Then to build the TSP image use: + +:: + + make PLAT= SPD=tspd all + +An additional boot loader binary file is created in the ``build`` directory: + +:: + + build///bl32.bin + +Checking source code style +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When making changes to the source for submission to the project, the source +must be in compliance with the Linux style guide, and to assist with this check +the project Makefile contains two targets, which both utilise the +``checkpatch.pl`` script that ships with the Linux source tree. + +To check the entire source tree, you must first download a copy of +``checkpatch.pl`` (or the full Linux source), set the ``CHECKPATCH`` environment +variable to point to the script and build the target checkcodebase: + +:: + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkcodebase + +To just check the style on the files that differ between your local branch and +the remote master, use: + +:: + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkpatch + +If you wish to check your patch against something other than the remote master, +set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT`` +is set to ``origin/master``. + +Building and using the FIP tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Firmware Image Package (FIP) is a packaging format used by the Trusted Firmware +project to package firmware images in a single binary. The number and type of +images that should be packed in a FIP is platform specific and may include TF +images and other firmware images required by the platform. For example, most +platforms require a BL33 image which corresponds to the normal world bootloader +(e.g. UEFI or U-Boot). + +The TF build system provides the make target ``fip`` to create a FIP file for the +specified platform using the FIP creation tool included in the TF project. +Examples below show how to build a FIP file for FVP, packaging TF images and a +BL33 image. + +For AArch64: + +:: + + make PLAT=fvp BL33= fip + +For AArch32: + +:: + + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33= fip + +Note that AArch32 support for Normal world boot loader (BL33), like U-boot or +UEFI, on FVP is not available upstream. Hence custom solutions are required to +allow Linux boot on FVP. These instructions assume such a custom boot loader +(BL33) is available. + +The resulting FIP may be found in: + +:: + + build/fvp//fip.bin + +For advanced operations on FIP files, it is also possible to independently build +the tool and create or modify FIPs using this tool. To do this, follow these +steps: + +It is recommended to remove old artifacts before building the tool: + +:: + + make -C tools/fiptool clean + +Build the tool: + +:: + + make [DEBUG=1] [V=1] fiptool + +The tool binary can be located in: + +:: + + ./tools/fiptool/fiptool + +Invoking the tool with ``--help`` will print a help message with all available +options. + +Example 1: create a new Firmware package ``fip.bin`` that contains BL2 and BL31: + +:: + + ./tools/fiptool/fiptool create \ + --tb-fw build///bl2.bin \ + --soc-fw build///bl31.bin \ + fip.bin + +Example 2: view the contents of an existing Firmware package: + +:: + + ./tools/fiptool/fiptool info /fip.bin + +Example 3: update the entries of an existing Firmware package: + +:: + + # Change the BL2 from Debug to Release version + ./tools/fiptool/fiptool update \ + --tb-fw build//release/bl2.bin \ + build//debug/fip.bin + +Example 4: unpack all entries from an existing Firmware package: + +:: + + # Images will be unpacked to the working directory + ./tools/fiptool/fiptool unpack /fip.bin + +Example 5: remove an entry from an existing Firmware package: + +:: + + ./tools/fiptool/fiptool remove \ + --tb-fw build//debug/fip.bin + +Note that if the destination FIP file exists, the create, update and +remove operations will automatically overwrite it. + +The unpack operation will fail if the images already exist at the +destination. In that case, use -f or --force to continue. + +More information about FIP can be found in the `Firmware Design`_ document. + +Migrating from fip\_create to fiptool +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The previous version of fiptool was called fip\_create. A compatibility script +that emulates the basic functionality of the previous fip\_create is provided. +However, users are strongly encouraged to migrate to fiptool. + +- To create a new FIP file, replace "fip\_create" with "fiptool create". +- To update a FIP file, replace "fip\_create" with "fiptool update". +- To dump the contents of a FIP file, replace "fip\_create --dump" + with "fiptool info". + +Building FIP images with support for Trusted Board Boot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Trusted Board Boot primarily consists of the following two features: + +- Image Authentication, described in `Trusted Board Boot`_, and +- Firmware Update, described in `Firmware Update`_ + +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 and fixes any + known security vulnerabilities. See `mbed TLS Security Center`_ for more + information. The latest version of TF is tested with tag ``mbedtls-2.4.2``. + + 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 + Trusted Firmware 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 Trusted Firmware: + + - ``MBEDTLS_DIR=`` + - ``TRUSTED_BOARD_BOOT=1`` + - ``GENERATE_COT=1`` + + In the case of ARM platforms, the location of the ROTPK hash must also be + specified at build time. Two 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, this + registers are read-only. On FVP Base and Cortex models, the registers + are read-only, but the value can be specified using the command line + option ``bp.trusted_key_storage.public_key`` when launching the model. + On both Juno and FVP models, 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 ROTPK hash that is hardcoded + in the ARM platform port. The private/public RSA key pair may be + found in ``plat/arm/board/common/rotpk``. + + Example of command line using RSA development keys: + + :: + + MBEDTLS_DIR= \ + make PLAT= TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + 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 Chain of Trust + described in the TBBR-client document. 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 `Firmware Update`_ 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= \ + 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=/ \ + SCP_BL2=/ \ + SCP_BL2U=/ \ + NS_BL2U=/ \ + 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=/`` + 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 + Chain of Trust described in the TBBR-client document. These certificates + can also be found in the output build directory. + +Building the Certificate Generation Tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``cert_create`` tool is built as part of the TF build process when the ``fip`` +make target is specified and TBB is enabled (as described in the previous +section), but it can also be built separately with the following command: + +:: + + make PLAT= [DEBUG=1] [V=1] certtool + +For platforms that do not require their own IDs in certificate files, +the generic 'cert\_create' tool can be built with the following command: + +:: + + make USE_TBBR_DEFS=1 [DEBUG=1] [V=1] certtool + +``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more +verbose. The following command should be used to obtain help about the tool: + +:: + + ./tools/cert_create/cert_create -h + +Building a FIP for Juno and FVP +------------------------------- + +This section provides Juno and FVP specific instructions to build Trusted +Firmware, obtain the additional required firmware, and pack it all together in +a single FIP binary. It assumes that a `Linaro Release`_ +has been installed. + +Note: Linaro Release 16.06 only includes pre-built binaries for AArch64. For +AArch32, pre-built binaries are only available from Linaro Release 16.12. + +Note: follow the full instructions for one platform before switching to a +different one. Mixing instructions for different platforms may result in +corrupted binaries. + +#. Clean the working directory + + :: + + make realclean + +#. Obtain SCP\_BL2 (Juno) and BL33 (all platforms) + + Use the fiptool to extract the SCP\_BL2 and BL33 images from the FIP + package included in the Linaro release: + + :: + + # Build the fiptool + make [DEBUG=1] [V=1] fiptool + + # Unpack firmware images from Linaro FIP + ./tools/fiptool/fiptool unpack \ + /fip.bin + + The unpack operation will result in a set of binary images extracted to the + working directory. The SCP\_BL2 image corresponds to ``scp-fw.bin`` and BL33 + corresponds to ``nt-fw.bin``. + + Note: the fiptool will complain if the images to be unpacked already + exist in the current directory. If that is the case, either delete those + files or use the ``--force`` option to overwrite. + + Note for AArch32, the instructions below assume that nt-fw.bin is a custom + Normal world boot loader that supports AArch32. + +#. Build TF images and create a new FIP for FVP + + :: + + # AArch64 + make PLAT=fvp BL33=nt-fw.bin all fip + + # AArch32 + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=nt-fw.bin all fip + +#. Build TF images and create a new FIP for Juno + + For AArch64: + + Building for AArch64 on Juno simply requires the addition of ``SCP_BL2`` + as a build parameter. + + :: + + make PLAT=juno all fip \ + BL33=/SOFTWARE/bl33-uboot.bin \ + SCP_BL2=/SOFTWARE/scp_bl2.bin + + For AArch32: + + Hardware restrictions on Juno prevent cold reset into AArch32 execution mode, + therefore BL1 and BL2 must be compiled for AArch64, and BL32 is compiled + separately for AArch32. + + - Before building BL32, the environment variable ``CROSS_COMPILE`` must point + to the AArch32 Linaro cross compiler. + + :: + + export CROSS_COMPILE=/bin/arm-linux-gnueabihf- + + - Build BL32 in AArch32. + + :: + + make ARCH=aarch32 PLAT=juno AARCH32_SP=sp_min \ + RESET_TO_SP_MIN=1 JUNO_AARCH32_EL3_RUNTIME=1 bl32 + + - Before building BL1 and BL2, the environment variable ``CROSS_COMPILE`` + must point to the AArch64 Linaro cross compiler. + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + + - The following parameters should be used to build BL1 and BL2 in AArch64 + and point to the BL32 file. + + :: + + make ARCH=aarch64 PLAT=juno LOAD_IMAGE_V2=1 JUNO_AARCH32_EL3_RUNTIME=1 \ + BL33=/SOFTWARE/bl33-uboot.bin \ + SCP_BL2=/SOFTWARE/scp_bl2.bin SPD=tspd \ + BL32=/bl32.bin all fip + +The resulting BL1 and FIP images may be found in: + +:: + + # Juno + ./build/juno/release/bl1.bin + ./build/juno/release/fip.bin + + # FVP + ./build/fvp/release/bl1.bin + ./build/fvp/release/fip.bin + +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 the Trusted Firmware 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. + +Booting an EL3 payload +~~~~~~~~~~~~~~~~~~~~~~ + +The EL3 payload image is a standalone image and is not part of the FIP. It is +not loaded by the Trusted Firmware. 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 the TF. + +- 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. + +Booting an EL3 payload on FVP +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The EL3 payloads boot flow requires the CPU's mailbox to be cleared at reset for +the secondary CPUs holding pen to work properly. Unfortunately, its reset value +is undefined on the FVP platform and the FVP platform code doesn't clear it. +Therefore, one must modify the way the model is normally invoked in order to +clear the mailbox at start-up. + +One way to do that is to create an 8-byte file containing all zero bytes using +the following command: + +:: + + dd if=/dev/zero of=mailbox.dat bs=1 count=8 + +and pre-load it into the FVP memory at the mailbox address (i.e. ``0x04000000``) +using the following model parameters: + +:: + + --data cluster0.cpu0=mailbox.dat@0x04000000 [Base FVPs] + --data=mailbox.dat@0x04000000 [Foundation FVP] + +To provide the model with the EL3 payload image, the following methods may be +used: + +#. If the EL3 payload is able to execute in place, it may be programmed into + flash memory. On Base Cortex and AEM FVPs, the following model parameter + loads it at the base address of the NOR FLASH1 (the NOR FLASH0 is already + used for the FIP): + + :: + + -C bp.flashloader1.fname="/path/to/el3-payload" + + On Foundation FVP, there is no flash loader component and the EL3 payload + may be programmed anywhere in flash using method 3 below. + +#. When using the ``SPIN_ON_BL1_EXIT=1`` loading method, the following DS-5 + command may be used to load the EL3 payload ELF image over JTAG: + + :: + + load /path/to/el3-payload.elf + +#. The EL3 payload may be pre-loaded in volatile memory using the following + model parameters: + + :: + + --data cluster0.cpu0="/path/to/el3-payload"@address [Base FVPs] + --data="/path/to/el3-payload"@address [Foundation FVP] + + The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address + used when building the Trusted Firmware. + +Booting an EL3 payload on Juno +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the EL3 payload is able to execute in place, it may be programmed in flash +memory by adding an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. + +Alternatively, the same DS-5 command mentioned in the FVP section above can +be used to load the EL3 payload's ELF file over JTAG on Juno. + +Preloaded BL33 alternative boot flow +------------------------------------ + +Some platforms have the ability to preload BL33 into memory instead of relying +on Trusted Firmware 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, Trusted Firmware 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 the Trusted Firmware. For example, the following command +will create a FIP without a BL33 and prepare to jump to a BL33 image loaded at +address 0x80000000: + +:: + + make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip + +Boot of a preloaded bootwrapped kernel image on Base FVP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following example uses the AArch64 boot wrapper. This simplifies normal +world booting while also making use of TF features. It can be obtained from its +repository with: + +:: + + git clone git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git + +After compiling it, an ELF file is generated. It can be loaded with the +following command: + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C bp.secureflashloader.fname=bl1.bin \ + -C bp.flashloader0.fname=fip.bin \ + -a cluster0.cpu0= \ + --start cluster0.cpu0=0x0 + +The ``-a cluster0.cpu0=`` option loads the ELF file. It +also sets the PC register to the ELF entry point address, which is not the +desired behaviour, so the ``--start cluster0.cpu0=0x0`` option forces the PC back +to 0x0 (the BL1 entry point address) on CPU #0. The ``PRELOADED_BL33_BASE`` define +used when compiling the FIP must match the ELF entry point. + +Boot of a preloaded bootwrapped kernel image on Juno +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The procedure to obtain and compile the boot wrapper is very similar to the case +of the FVP. The execution must be stopped at the end of bl2\_main(), and the +loading method explained above in the EL3 payload boot flow section may be used +to load the ELF file over JTAG on Juno. + +Running the software on FVP +--------------------------- + +The latest version of the AArch64 build of ARM Trusted Firmware has been tested +on the following ARM FVPs (64-bit host machine only). + +- ``Foundation_Platform`` (Version 10.2, Build 10.2.20) +- ``FVP_Base_AEMv8A-AEMv8A`` (Version 8.4, Build 0.8.8402) +- ``FVP_Base_Cortex-A57x4-A53x4`` (Version 8.4, Build 0.8.8402) + +The latest version of the AArch32 build of ARM Trusted Firmware has been tested +on the following ARM FVPs (64-bit host machine only). + +- ``FVP_Base_AEMv8A-AEMv8A`` (Version 8.4, Build 0.8.8402) +- ``FVP_Base_Cortex-A32x4`` (Version 10.1, Build 10.1.32) + +NOTE: The build numbers quoted above are those reported by launching the FVP +with the ``--version`` parameter. + +NOTE: The software will not work on Version 1.0 of the Foundation FVP. +The commands below would report an ``unhandled argument`` error in this case. + +NOTE: FVPs can be launched with ``--cadi-server`` option such that a +CADI-compliant debugger (for example, ARM DS-5) can connect to and control its +execution. + +The Foundation FVP is a cut down version of the AArch64 Base FVP. It can be +downloaded for free from `ARM's website`_. + +Please refer to the FVP documentation for a detailed description of the model +parameter options. A brief description of the important ones that affect the ARM +Trusted Firmware and normal world software behavior is provided below. + +Note the instructions in the following sections assume that Linaro Release 16.06 +is being used. + +Obtaining the Flattened Device Trees +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Depending on the FVP configuration and Linux configuration used, different +FDT files are required. FDTs for the Foundation and Base FVPs can be found in +the Trusted Firmware source directory under ``fdts/``. The Foundation FVP has a +subset of the Base FVP components. For example, the Foundation FVP lacks CLCD +and MMC support, and has only one CPU cluster. + +Note: It is not recommended to use the FDTs built along the kernel because not +all FDTs are available from there. + +- ``fvp-base-gicv2-psci.dtb`` + + For use with both AEMv8 and Cortex-A57-A53 Base FVPs with + Base memory map configuration. + +- ``fvp-base-gicv2-psci-aarch32.dtb`` + + For use with AEMv8 and Cortex-A32 Base FVPs running Linux in AArch32 state + with Base memory map configuration. + +- ``fvp-base-gicv3-psci.dtb`` + + (Default) For use with both AEMv8 and Cortex-A57-A53 Base FVPs with Base + memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-aarch32.dtb`` + + For use with AEMv8 and Cortex-A32 Base FVPs running Linux in AArch32 state + with Base memory map configuration and Linux GICv3 support. + +- ``fvp-foundation-gicv2-psci.dtb`` + + For use with Foundation FVP with Base memory map configuration. + +- ``fvp-foundation-gicv3-psci.dtb`` + + (Default) For use with Foundation FVP with Base memory map configuration + and Linux GICv3 support. + +Running on the Foundation FVP with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``Foundation_Platform`` parameters should be used to boot Linux with +4 CPUs using the AArch64 build of ARM Trusted Firmware. + +:: + + /Foundation_Platform \ + --cores=4 \ + --secure-memory \ + --visualization \ + --gicv3 \ + --data="/"@0x0 \ + --data="/"@0x08000000 \ + --data="/"@0x83000000 \ + --data="/"@0x80080000 \ + --block-device="/" + +Notes: + +- BL1 is loaded at the start of the Trusted ROM. +- The Firmware Image Package is loaded at the start of NOR FLASH0. +- The Linux kernel image and device tree are loaded in DRAM. +- The default use-case for the Foundation FVP is to use the ``--gicv3`` option + and enable the GICv3 device in the model. Note that without this option, + the Foundation FVP defaults to legacy (Versatile Express) memory map which + is not supported by ARM Trusted Firmware. + +Running on the AEMv8 Base FVP with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of ARM Trusted Firmware. + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Running on the AEMv8 Base FVP (AArch32) with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of ARM Trusted Firmware. + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Running on the Cortex-A57-A53 Base FVP with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of ARM Trusted Firmware. + +:: + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Running on the Cortex-A32 Base FVP (AArch32) with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of ARM Trusted Firmware. + +:: + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Running on the AEMv8 Base FVP with reset to BL31 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of ARM Trusted Firmware. + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04023000 \ + -C cluster0.cpu1.RVBAR=0x04023000 \ + -C cluster0.cpu2.RVBAR=0x04023000 \ + -C cluster0.cpu3.RVBAR=0x04023000 \ + -C cluster1.cpu0.RVBAR=0x04023000 \ + -C cluster1.cpu1.RVBAR=0x04023000 \ + -C cluster1.cpu2.RVBAR=0x04023000 \ + -C cluster1.cpu3.RVBAR=0x04023000 \ + --data cluster0.cpu0="/"@0x04023000 \ + --data cluster0.cpu0="/"@0x04001000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Notes: + +- Since a FIP is not loaded when using BL31 as reset entrypoint, the + ``--data=""@`` + parameter is needed to load the individual bootloader images in memory. + BL32 image is only needed if BL31 has been built to expect a Secure-EL1 + Payload. + +- The ``-C cluster.cpu.RVBAR=@`` parameter, where + X and Y are the cluster and CPU numbers respectively, is used to set the + reset vector for each core. + +- Changing the default value of ``ARM_TSP_RAM_LOCATION`` will also require + changing the value of + ``--data=""@`` to the new value of + ``BL32_BASE``. + +Running on the AEMv8 Base FVP (AArch32) with reset to SP\_MIN entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of ARM Trusted Firmware. + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C cluster0.cpu0.RVBAR=0x04001000 \ + -C cluster0.cpu1.RVBAR=0x04001000 \ + -C cluster0.cpu2.RVBAR=0x04001000 \ + -C cluster0.cpu3.RVBAR=0x04001000 \ + -C cluster1.cpu0.RVBAR=0x04001000 \ + -C cluster1.cpu1.RVBAR=0x04001000 \ + -C cluster1.cpu2.RVBAR=0x04001000 \ + -C cluster1.cpu3.RVBAR=0x04001000 \ + --data cluster0.cpu0="/"@0x04001000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Note: The load address of ```` depends on the value ``BL32_BASE``. +It should match the address programmed into the RVBAR register as well. + +Running on the Cortex-A57-A53 Base FVP with reset to BL31 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of ARM Trusted Firmware. + +:: + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04023000 \ + -C cluster0.cpu1.RVBARADDR=0x04023000 \ + -C cluster0.cpu2.RVBARADDR=0x04023000 \ + -C cluster0.cpu3.RVBARADDR=0x04023000 \ + -C cluster1.cpu0.RVBARADDR=0x04023000 \ + -C cluster1.cpu1.RVBARADDR=0x04023000 \ + -C cluster1.cpu2.RVBARADDR=0x04023000 \ + -C cluster1.cpu3.RVBARADDR=0x04023000 \ + --data cluster0.cpu0="/"@0x04023000 \ + --data cluster0.cpu0="/"@0x04001000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Running on the Cortex-A32 Base FVP (AArch32) with reset to SP\_MIN entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of ARM Trusted Firmware. + +:: + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04001000 \ + -C cluster0.cpu1.RVBARADDR=0x04001000 \ + -C cluster0.cpu2.RVBARADDR=0x04001000 \ + -C cluster0.cpu3.RVBARADDR=0x04001000 \ + --data cluster0.cpu0="/"@0x04001000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x83000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + -C bp.virtioblockdevice.image_path="/" + +Running the software on Juno +---------------------------- + +This version of the ARM Trusted Firmware has been tested on Juno r0 and Juno r1. + +To execute the software stack on Juno, the version of the Juno board recovery +image indicated in the `Linaro Release Notes`_ must be installed. If you have an +earlier version installed or are unsure which version is installed, please +re-install the recovery image by following the +`Instructions for using Linaro's deliverables on Juno`_. + +Preparing Trusted Firmware images +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After building Trusted Firmware, the files ``bl1.bin`` and ``fip.bin`` need copying +to the ``SOFTWARE/`` directory of the Juno SD card. + +Other Juno software information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Please visit the `ARM Platforms Portal`_ to get support and obtain any other Juno +software information. Please also refer to the `Juno Getting Started Guide`_ to +get more detailed information about the Juno ARM development platform and how to +configure it. + +Testing SYSTEM SUSPEND on Juno +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend +to RAM. For more details refer to section 5.16 of `PSCI`_. To test system suspend +on Juno, at the linux shell prompt, issue the following command: + +:: + + echo +10 > /sys/class/rtc/rtc0/wakealarm + echo -n mem > /sys/power/state + +The Juno board should suspend to RAM and then wakeup after 10 seconds due to +wakeup interrupt from RTC. + +-------------- + +*Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.* + +.. _Linaro: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated +.. _Instructions for using the Linaro software deliverables: https://community.arm.com/dev-platforms/b/documents/posts/instructions-for-using-the-linaro-software-deliverables +.. _Firmware Design: firmware-design.rst +.. _Linaro Release Notes: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated +.. _Linaro instructions: https://community.arm.com/dev-platforms/b/documents/posts/instructions-for-using-the-linaro-software-deliverables +.. _Development Studio 5 (DS-5): http://www.arm.com/products/tools/software-tools/ds-5/index.php +.. _Summary of build options: #user-content-summary-of-build-options +.. _here: ./psci-lib-integration-guide.rst +.. _Building the Test Secure Payload: #user-content-building-the-test-secure-payload +.. _Trusted Board Boot: trusted-board-boot.rst +.. _Secure-EL1 Payloads and Dispatchers: firmware-design.rst#user-content-secure-el1-payloads-and-dispatchers +.. _Firmware Update: ./firmware-update.rst +.. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git +.. _mbed TLS Security Center: https://tls.mbed.org/security +.. _Linaro Release: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated +.. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf +.. _ARM's website: https://developer.arm.com/products/system-design/fixed-virtual-platforms +.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/b/documents/posts/using-linaros-deliverables-on-juno +.. _ARM Platforms Portal: https://community.arm.com/groups/arm-development-platforms +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf diff --git a/license.rst b/license.rst new file mode 100644 index 0000000..c51e595 --- /dev/null +++ b/license.rst @@ -0,0 +1,38 @@ +Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +- Neither the name of ARM nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------- + +Note: +Individual files contain the following tag instead of the full license text. + +:: + + SPDX-License-Identifier: BSD-3-Clause + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ diff --git a/maintainers.rst b/maintainers.rst new file mode 100644 index 0000000..388073e --- /dev/null +++ b/maintainers.rst @@ -0,0 +1,102 @@ +ARM Trusted Firmware Maintainers +================================ + +ARM Trusted Firmware is an ARM maintained project. All contributions are +ultimately merged by the maintainers listed below. Technical ownership of some +parts of the codebase is delegated to the sub-maintainers listed below. An +acknowledgement from these sub-maintainers may be required before the +maintainers merge a contribution. + +Maintainers +----------- + +Dan Handley (dan.handley@arm.com, `danh-arm`_) + +David Cunado (david.cunado@arm.com, `davidcunado-arm`_) + +OPTEE and QEMU platform sub-maintainer +-------------------------------------- + +Jens Wiklander (jens.wiklander@linaro.org, `jenswi-linaro`_) + +Files: + +- docs/spd/optee-dispatcher.md +- docs/plat/qemu.md +- services/spd/opteed/\* +- plat/qemu/\* + +TLK/Trusty SPDs and NVidia platforms sub-maintainer +--------------------------------------------------- + +Varun Wadekar (vwadekar@nvidia.com, `vwadekar`_) + +Files: + +- docs/spd/tlk-dispatcher.md +- docs/spd/trusty-dispatcher.md +- include/bl32/payloads/tlk.h +- include/lib/cpus/aarch64/denver.h +- lib/cpus/aarch64/denver.S +- services/spd/tlkd/\* +- services/spd/trusty/\* +- plat/nvidia/\* + +eMMC/UFS drivers and HiSilicon platform sub-maintainer +------------------------------------------------------ + +Haojian Zhuang (haojian.zhuang@linaro.org, `hzhuang1`_) + +Files: + +- docs/plat/hikey.md +- docs/plat/hikey960.md +- drivers/emmc/\* +- drivers/partition/\* +- drivers/synopsys/emmc/\* +- drivers/synopsys/ufs/\* +- drivers/ufs/\* +- include/drivers/dw\_ufs.h +- include/drivers/emmc.h +- include/drivers/ufs.h +- include/drivers/synopsys/dw\_mmc.h +- plat/hisilicon/\* + +MediaTek platform sub-maintainer +-------------------------------- + +Yidi Lin (林以廸 yidi.lin@mediatek.com, `mtk09422`_) + +Files: + +- plat/mediatek/\* + +RockChip platform sub-maintainer +-------------------------------- + +Tony Xie (tony.xie@rock-chips.com, `TonyXie06`_ +or `rkchrome`_) + +Files: + +- plat/rockchip/\* + +Xilinx platform sub-maintainer +------------------------------ + +Sören Brinkmann (soren.brinkmann@xilinx.com, `sorenb-xlnx`_) + +Files: + +- docs/plat/xilinx-zynqmp.md +- plat/xilinx/\* + +.. _danh-arm: https://github.com/danh-arm +.. _davidcunado-arm: https://github.com/davidcunado-arm +.. _jenswi-linaro: https://github.com/jenswi-linaro +.. _vwadekar: https://github.com/vwadekar +.. _hzhuang1: https://github.com/hzhuang1 +.. _mtk09422: https://github.com/mtk09422 +.. _TonyXie06: https://github.com/TonyXie06 +.. _rkchrome: https://github.com/rkchrome +.. _sorenb-xlnx: https://github.com/sorenb-xlnx diff --git a/readme.rst b/readme.rst new file mode 100644 index 0000000..fdce8c0 --- /dev/null +++ b/readme.rst @@ -0,0 +1,196 @@ +ARM Trusted Firmware - version 1.3 +================================== + +ARM Trusted Firmware provides a reference implementation of secure world +software for `ARMv8-A`_, including a `Secure Monitor`_ executing at +Exception Level 3 (EL3). It implements various ARM interface standards, such as +the Power State Coordination Interface (`PSCI`_), Trusted Board Boot Requirements +(TBBR, ARM DEN0006C-1) and `SMC Calling Convention`_. As far as possible +the code is designed for reuse or porting to other ARMv8-A model and hardware +platforms. + +ARM will continue development in collaboration with interested parties to +provide a full reference implementation of PSCI, TBBR and Secure Monitor code +to the benefit of all developers working with ARMv8-A TrustZone technology. + +License +------- + +The software is provided under a BSD-3-Clause `license`_. Contributions to this +project are accepted under the same license with developer sign-off as +described in the `Contributing Guidelines`_. + +This project contains code from other projects as listed below. The original +license text is included in those source files. + +- The stdlib source code is derived from FreeBSD code. + +- The libfdt source code is dual licensed. It is used by this project under + the terms of the BSD-2-Clause license. + +This Release +------------ + +This release provides a suitable starting point for productization of secure +world boot and runtime firmware, executing in either the AArch32 or AArch64 +execution state. + +Users are encouraged to do their own security validation, including penetration +testing, on any secure world code derived from ARM Trusted Firmware. + +Functionality +~~~~~~~~~~~~~ + +- Initialization of the secure world (for example, exception vectors, control + registers, interrupt controller and interrupts for the platform), before + transitioning into the normal world at the Exception Level and Register + Width specified by the platform. + +- Library support for CPU specific reset and power down sequences. This + includes support for errata workarounds. + +- Drivers for both versions 2.0 and 3.0 of the ARM Generic Interrupt + Controller specifications (GICv2 and GICv3). The latter also enables GICv3 + hardware systems that do not contain legacy GICv2 support. + +- Drivers to enable standard initialization of ARM System IP, for example + Cache Coherent Interconnect (CCI), Cache Coherent Network (CCN), Network + Interconnect (NIC) and TrustZone Controller (TZC). + +- SMC (Secure Monitor Call) handling, conforming to the + `SMC Calling Convention`_ using an EL3 runtime services framework. + +- `PSCI`_ library support for the Secondary CPU Boot, CPU Hotplug, CPU Idle + and System Shutdown/Reset/Suspend use-cases. + This library is pre-integrated with the provided AArch64 EL3 Runtime + Software, and is also suitable for integration into other EL3 Runtime + Software. + +- A minimal AArch32 Secure Payload to demonstrate `PSCI`_ library integration + on platforms with AArch32 EL3 Runtime Software. + +- Secure Monitor library code such as world switching, EL1 context management + and interrupt routing. + When using the provided AArch64 EL3 Runtime Software, this must be + integrated with a Secure-EL1 Payload Dispatcher (SPD) component to + customize the interaction with a Secure-EL1 Payload (SP), for example a + Secure OS. + +- A Test Secure-EL1 Payload and Dispatcher to demonstrate AArch64 Secure + Monitor functionality and Secure-EL1 interaction with PSCI. + +- AArch64 SPDs for the `OP-TEE Secure OS`_ and `NVidia Trusted Little Kernel`_. + +- A Trusted Board Boot implementation, conforming to all mandatory TBBR + requirements. This includes image authentication using certificates, a + Firmware Update (or recovery mode) boot flow, and packaging of the various + firmware images into a Firmware Image Package (FIP) to be loaded from + non-volatile storage. + The TBBR implementation is currently only supported in the AArch64 build. + +- Support for alternative boot flows. Some platforms have their own boot + firmware and only require the AArch64 EL3 Runtime Software provided by this + project. Other platforms require minimal initialization before booting + into an arbitrary EL3 payload. + +For a full description of functionality and implementation details, please +see the `Firmware Design`_ and supporting documentation. The `Change Log`_ +provides details of changes made since the last release. + +Platforms +~~~~~~~~~ + +The AArch64 build of this release has been tested on variants r0, r1 and r2 +of the `Juno ARM Development Platform`_ with `Linaro Release 16.06`_. + +The AArch64 build of this release has been tested on the following ARM +`FVP`_\ s (64-bit host machine only, with `Linaro Release 16.06`_): + +- ``Foundation_Platform`` (Version 10.1, Build 10.1.32) +- ``FVP_Base_AEMv8A-AEMv8A`` (Version 7.7, Build 0.8.7701) +- ``FVP_Base_Cortex-A57x4-A53x4`` (Version 7.7, Build 0.8.7701) +- ``FVP_Base_Cortex-A57x1-A53x1`` (Version 7.7, Build 0.8.7701) +- ``FVP_Base_Cortex-A57x2-A53x4`` (Version 7.7, Build 0.8.7701) + +The AArch32 build of this release has been tested on the following ARM +`FVP`_\ s (64-bit host machine only, with `Linaro Release 16.06`_): + +- ``FVP_Base_AEMv8A-AEMv8A`` (Version 7.7, Build 0.8.7701) +- ``FVP_Base_Cortex-A32x4`` (Version 10.1, Build 10.1.32) + +The Foundation FVP can be downloaded free of charge. The Base FVPs can be +licensed from ARM: see `www.arm.com/fvp`_. + +This release also contains the following platform support: + +- MediaTek MT6795 and MT8173 SoCs +- NVidia T210 and T132 SoCs +- QEMU emulator +- RockChip RK3368 and RK3399 SoCs +- Xilinx Zynq UltraScale + MPSoC + +Still to Come +~~~~~~~~~~~~~ + +- AArch32 TBBR support and ongoing TBBR alignment. + +- More platform support. + +- Ongoing support for new architectural features, CPUs and System IP. + +- Ongoing `PSCI`_ alignment and feature support. + +- Ongoing security hardening, optimization and quality improvements. + +For a full list of detailed issues in the current code, please see the +`Change Log`_ and the `GitHub issue tracker`_. + +Getting Started +--------------- + +Get the Trusted Firmware source code from +`GitHub`_. + +See the `User Guide`_ for instructions on how to install, build and use +the Trusted Firmware with the ARM `FVP`_\ s. + +See the `Firmware Design`_ for information on how the ARM Trusted Firmware works. + +See the `Porting Guide`_ as well for information about how to use this +software on another ARMv8-A platform. + +See the `Contributing Guidelines`_ for information on how to contribute to this +project and the `Acknowledgments`_ file for a list of contributors to the +project. + +Feedback and support +~~~~~~~~~~~~~~~~~~~~ + +ARM welcomes any feedback on the Trusted Firmware. Please send feedback using +the `GitHub issue tracker`_. + +ARM licensees may contact ARM directly via their partner managers. + +-------------- + +*Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.* + +.. _ARMv8-A: http://www.arm.com/products/processors/armv8-architecture.php +.. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html +.. _license: ./license.rst +.. _Contributing Guidelines: ./contributing.rst +.. _OP-TEE Secure OS: https://github.com/OP-TEE/optee_os +.. _NVidia Trusted Little Kernel: http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/ote_partner/tlk.git;a=summary +.. _Firmware Design: ./docs/firmware-design.rst +.. _Change Log: ./docs/change-log.rst +.. _Juno ARM Development Platform: http://www.arm.com/products/tools/development-boards/versatile-express/juno-arm-development-platform.php +.. _Linaro Release 16.06: https://community.arm.com/docs/DOC-10952#jive_content_id_Linaro_Release_1606 +.. _FVP: http://www.arm.com/fvp +.. _www.arm.com/fvp: http://www.arm.com/fvp +.. _GitHub issue tracker: https://github.com/ARM-software/tf-issues/issues +.. _GitHub: https://www.github.com/ARM-software/arm-trusted-firmware +.. _User Guide: ./docs/user-guide.rst +.. _Porting Guide: ./docs/porting-guide.rst +.. _Acknowledgments: ./acknowledgements.rst