Merge "TF-A Aarch32: optimise memcpy4()" into integration
diff --git a/Makefile b/Makefile
index 65ebb93..fa711e2 100644
--- a/Makefile
+++ b/Makefile
@@ -1201,7 +1201,7 @@
.PHONY: ${CRTTOOL}
${CRTTOOL}:
- ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} --no-print-directory -C ${CRTTOOLPATH}
+ ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${CRTTOOLPATH}
@${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
@${ECHO_BLANK_LINE}
@@ -1267,7 +1267,7 @@
.PHONY: ${ENCTOOL}
${ENCTOOL}:
- ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 --no-print-directory -C ${ENCTOOLPATH}
+ ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${ENCTOOLPATH}
@${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
@${ECHO_BLANK_LINE}
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 802c174..203e1d4 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,6 +14,9 @@
#include <common/debug.h>
#include <drivers/auth/auth_mod.h>
#include <drivers/console.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
#include <lib/extensions/pauth.h>
#include <plat/common/platform.h>
@@ -88,14 +91,25 @@
#if TRUSTED_BOARD_BOOT
/* Initialize authentication module */
auth_mod_init();
+
+#if MEASURED_BOOT
+ /* Initialize measured boot module */
+ measured_boot_init();
+
+#endif /* MEASURED_BOOT */
#endif /* TRUSTED_BOARD_BOOT */
- /* initialize boot source */
+ /* Initialize boot source */
bl2_plat_preload_setup();
/* Load the subsequent bootloader images. */
next_bl_ep_info = bl2_load_images();
+#if MEASURED_BOOT
+ /* Finalize measured boot */
+ measured_boot_finish();
+#endif /* MEASURED_BOOT */
+
#if !BL2_AT_EL3
#ifndef __aarch64__
/*
diff --git a/docs/components/index.rst b/docs/components/index.rst
index 18b1e38..ffeef80 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -12,11 +12,13 @@
exception-handling
fconf/index
firmware-update
+ measured_boot/index
platform-interrupt-controller-API
ras
romlib-design
sdei
- secure-partition-manager-design
+ secure-partition-manager
+ secure-partition-manager-mm
psa-ffa-manifest-binding
xlat-tables-lib-v2-design
cot-binding
diff --git a/docs/components/measured_boot/event_log.rst b/docs/components/measured_boot/event_log.rst
new file mode 100644
index 0000000..5347dcc
--- /dev/null
+++ b/docs/components/measured_boot/event_log.rst
@@ -0,0 +1,35 @@
+DTB binding for Event Log properties
+====================================
+
+This document describes the device tree format of Event Log properties.
+These properties are not related to a specific platform and can be queried
+from common code.
+
+Dynamic configuration for Event Log
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Measured Boot driver expects a *tpm_event_log* node with the following field
+in 'nt_fw_config' and 'tsp_fw_config' DTS files:
+
+- compatible [mandatory]
+ - value type: <string>
+ - Must be the string "arm,tpm_event_log".
+
+Then a list of properties representing Event Log configuration, which
+can be used by Measured Boot driver. Each property is named according
+to the information it contains:
+
+- tpm_event_log_sm_addr [fvp_nt_fw_config.dts with OP-TEE]
+ - value type: <u64>
+ - Event Log base address in secure memory.
+
+Note. Currently OP-TEE does not support reading DTBs from Secure memory
+and this property should be removed when this feature is supported.
+
+- tpm_event_log_addr [mandatory]
+ - value type: <u64>
+ - Event Log base address in non-secure memory.
+
+- tpm_event_log_size [mandatory]
+ - value type: <u32>
+ - Event Log size.
diff --git a/docs/components/measured_boot/index.rst b/docs/components/measured_boot/index.rst
new file mode 100644
index 0000000..e7f2634
--- /dev/null
+++ b/docs/components/measured_boot/index.rst
@@ -0,0 +1,12 @@
+Measured Boot Driver (MBD)
+==========================
+
+.. _measured-boot-document:
+
+Properties binding information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. toctree::
+ :maxdepth: 1
+
+ event_log
diff --git a/docs/components/secure-partition-manager-design.rst b/docs/components/secure-partition-manager-mm.rst
similarity index 97%
rename from docs/components/secure-partition-manager-design.rst
rename to docs/components/secure-partition-manager-mm.rst
index 4f67185..87fc91d 100644
--- a/docs/components/secure-partition-manager-design.rst
+++ b/docs/components/secure-partition-manager-mm.rst
@@ -1,5 +1,22 @@
-Secure Partition Manager
-************************
+Secure Partition Manager (MM)
+*****************************
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+- SPM based on the PSA FF-A specification (`Secure Partition Manager`__).
+- SPM based on the MM interface.
+
+.. __: secure-partition-manager.html
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document describes the latter implementation where the Secure Partition Manager
+resides at EL3 and management services run from isolated Secure Partitions at S-EL0.
+The communication protocol is established through the Management Mode (MM) interface.
Background
==========
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
new file mode 100644
index 0000000..2169f30
--- /dev/null
+++ b/docs/components/secure-partition-manager.rst
@@ -0,0 +1,867 @@
+Secure Partition Manager
+************************
+
+.. contents::
+
+Acronyms
+========
+
++--------+-----------------------------------+
+| DTB | Device Tree Blob |
++--------+-----------------------------------+
+| DTS | Device Tree Source |
++--------+-----------------------------------+
+| EC | Execution Context |
++--------+-----------------------------------+
+| FIP | Firmware Image Package |
++--------+-----------------------------------+
+| FF-A | Firmware Framework for A-class |
++--------+-----------------------------------+
+| IPA | Intermediate Physical Address |
++--------+-----------------------------------+
+| NWd | Normal World |
++--------+-----------------------------------+
+| ODM | Original Design Manufacturer |
++--------+-----------------------------------+
+| OEM | Original Equipment Manufacturer |
++--------+-----------------------------------+
+| PA | Physical Address |
++--------+-----------------------------------+
+| PE | Processing Element |
++--------+-----------------------------------+
+| PVM | Primary VM |
++--------+-----------------------------------+
+| PSA | Platform Security Architecture |
++--------+-----------------------------------+
+| SP | Secure Partition |
++--------+-----------------------------------+
+| SPM | Secure Partition Manager |
++--------+-----------------------------------+
+| SPMC | SPM Core |
++--------+-----------------------------------+
+| SPMD | SPM Dispatcher |
++--------+-----------------------------------+
+| SiP | Silicon Provider |
++--------+-----------------------------------+
+| SWd | Secure World |
++--------+-----------------------------------+
+| TLV | Tag-Length-Value |
++--------+-----------------------------------+
+| TOS | Trusted Operating System |
++--------+-----------------------------------+
+| VM | Virtual Machine |
++--------+-----------------------------------+
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+- SPM based on the PSA FF-A specification `[1]`_.
+- SPM based on the MM interface to communicate with an S-EL0 partition `[2]`_.
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document:
+
+- describes the PSA FF-A implementation where the Secure Partition Manager
+ resides at EL3 and S-EL2 (or EL3 and S-EL1).
+- is not an architecture specification and it might provide assumptions
+ on sections mandated as implementation-defined in the specification.
+- covers the implications to TF-A used as a bootloader, and Hafnium
+ used as a reference code base for an S-EL2 secure firmware on
+ platforms implementing Armv8.4-SecEL2.
+
+Terminology
+-----------
+
+- Hypervisor refers to the NS-EL2 component managing Virtual Machines (or
+ partitions) in the Normal World.
+- SPMC refers to the S-EL2 component managing Virtual Machines (or Secure
+ Partitions) in the Secure World when Armv8.4-SecEL2 extension is implemented.
+- Alternatively, SPMC can refer to an S-EL1 component, itself being a Secure
+ Partition and implementing the FF-A ABI on pre-Armv8.4 platforms.
+- VM refers to a Normal World Virtual Machine managed by an Hypervisor.
+- SP refers to a Secure World "Virtual Machine" managed by the SPMC component.
+
+Support for legacy platforms
+----------------------------
+
+In the implementation, the SPM is split into SPMD and SPMC components
+(although not strictly mandated by the specification). SPMD is located
+at EL3 and principally relays FF-A messages from NWd (Hypervisor or OS
+kernel) to SPMC located either at S-EL1 or S-EL2.
+
+Hence TF-A must support both cases where SPMC is either located at:
+
+- S-EL1 supporting pre-Armv8.4 platforms. SPMD conveys FF-A protocol
+ from EL3 to S-EL1.
+- S-EL2 supporting platforms implementing Armv8.4-SecEL2 extension.
+ SPMD conveys FF-A protocol from EL3 to S-EL2.
+
+The same SPMD component is used to support both configurations. The SPMC
+execution level is a build time choice.
+
+Sample reference stack
+======================
+
+The following diagram illustrates a possible configuration with SPMD and SPMC,
+one or multiple Secure Partitions, with or without an optional Hypervisor:
+
+.. image:: ../resources/diagrams/ff-a-spm-sel2.png
+
+TF-A build options
+==================
+
+The following TF-A build options are provisioned:
+
+- **SPD=spmd**: this option selects the SPMD component to relay FF-A
+ protocol from NWd to SWd back and forth. It is not possible to
+ enable another Secure Payload Dispatcher when this option is chosen.
+- **SPMD_SPM_AT_SEL2**: this option adjusts the SPMC execution
+ level to being S-EL1 or S-EL2. It defaults to enabled (value 1) when
+ SPD=spmd is chosen.
+- **CTX_INCLUDE_EL2_REGS**: this option permits saving (resp.
+ restoring) the EL2 system register context before entering (resp.
+ after leaving) the SPMC. It is mandatory when ``SPMD_SPM_AT_SEL2`` is
+ enabled. The context save/restore routine and exhaustive list of
+ registers is visible at `[4] <#References>`__.
+- **SP_LAYOUT_FILE**: this option provides a text description file
+ providing paths to SP binary images and DTS format manifests
+ (see `Specifying partition binary image and DT`_). It
+ is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
+ secure partitions are to be loaded on behalf of SPMC.
+
++------------------------------+----------------------+------------------+
+| | CTX_INCLUDE_EL2_REGS | SPMD_SPM_AT_SEL2 |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL1 (e.g. OP-TEE) | 0 | 0 |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL2 (e.g. Hafnium) | 1 | 1 (default when |
+| | | SPD=spmd) |
++------------------------------+----------------------+------------------+
+
+Other combinations of such build options either break the build or are not
+supported.
+
+Note, the ``CTX_INCLUDE_EL2_REGS`` option provides the generic support for
+barely saving/restoring EL2 registers from an Arm arch perspective. As such
+it is decoupled from the ``SPD=spmd`` option.
+
+BL32 option is re-purposed to specify the SPMC image. It can specify either the
+Hafnium binary path (built for the secure world) or the path to a TEE binary
+implementing the FF-A protocol.
+
+BL33 option can specify either:
+
+- the TFTF binary or
+- the Hafnium binary path (built for the normal world) if VMs were loaded by
+ TF-A beforehand or
+- a minimal loader performing the loading of VMs and Hafnium.
+
+Sample TF-A build command line when SPMC is located at S-EL1
+(typically pre-Armv8.4):
+
+.. code:: shell
+
+ make \
+ CROSS_COMPILE=aarch64-none-elf- \
+ SPD=spmd \
+ SPMD_SPM_AT_SEL2=0 \
+ BL32=<path-to-tee-binary> \
+ BL33=<path-to-nwd-binary> \
+ PLAT=fvp \
+ all fip
+
+Sample TF-A build command line for an Armv8.4-SecEL2 enabled system
+where SPMC is located at S-EL2:
+
+.. code:: shell
+
+ make \
+ CROSS_COMPILE=aarch64-none-elf- \
+ SPD=spmd \
+ CTX_INCLUDE_EL2_REGS=1 \
+ ARM_ARCH_MINOR=4 \
+ BL32=<path-to-swd-hafnium-binary>
+ BL33=<path-to-nwd-binary> \
+ SP_LAYOUT_FILE=sp_layout.json \
+ PLAT=fvp \
+ all fip
+
+Build options to enable secure boot:
+
+.. code:: shell
+
+ make \
+ CROSS_COMPILE=aarch64-none-elf- \
+ SPD=spmd \
+ CTX_INCLUDE_EL2_REGS=1 \
+ ARM_ARCH_MINOR=4 \
+ BL32=<path-to-swd-hafnium-binary>
+ BL33=<path-to-nwd-binary> \
+ SP_LAYOUT_FILE=../tf-a-tests/build/fvp/debug/sp_layout.json \
+ MBEDTLS_DIR=<path-to-mbedtls-lib> \
+ TRUSTED_BOARD_BOOT=1 \
+ COT=dualroot \
+ ARM_ROTPK_LOCATION=devel_rsa \
+ ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
+ GENERATE_COT=1 \
+ PLAT=fvp \
+ all fip
+
+Boot process
+============
+
+Loading Hafnium and Secure Partitions in the secure world
+---------------------------------------------------------
+
+The Hafnium implementation in normal world requires VMs to be loaded in
+memory prior to booting. The mechanism upon which VMs are loaded and
+exposed to Hafnium are either:
+
+- by supplying a ramdisk image where VM images are concatenated (1)
+- or by providing VM load addresses within Hafnium manifest (2)
+
+TF-A is the bootlader for the Hafnium and SPs in the secure world. TF-A
+does not provide tooling or libraries manipulating ramdisks as required
+by (1). Thus BL2 loads SPs payloads independently.
+SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
+Thus they are supplied as distinct “self-contained” signed entities within
+the FIP flash image. The FIP image itself is not signed hence providing
+ability to upgrade SPs in the field.
+
+Booting through TF-A
+--------------------
+
+SP manifests
+~~~~~~~~~~~~
+
+An SP manifest describes SP attributes as defined in `[1]`_
+section 3.1 (partition manifest at virtual FF-A instance) in DTS text format. It
+is represented as a single file associated with the SP. A sample is
+provided by `[5]`_. A binding document is provided by `[6]`_.
+
+Secure Partition packages
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Secure Partitions are bundled as independent package files consisting
+of:
+
+- a header
+- a DTB
+- an image payload
+
+The header starts with a magic value and offset values to SP DTB and
+image payload. Each SP package is loaded independently by BL2 loader
+and verified for authenticity and integrity.
+
+The SP package identified by its UUID (matching FF-A uuid) is inserted
+as a single entry into the FIP at end of the TF-A build flow as shown:
+
+.. code:: shell
+
+ Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw"
+ EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw"
+ Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw"
+ Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw"
+ HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config"
+ TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config"
+ SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config"
+ TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config"
+ NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config"
+ B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob"
+ D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob"
+
+.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml
+
+Specifying partition binary image and DT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A description file (json format) is passed to the build flow specifying
+paths to the SP binary image and associated DTS partition manifest file.
+The latter is going through the dtc compiler to generate the dtb fed into
+the SP package.
+
+.. code:: shell
+
+ {
+ "tee1" : {
+ "image": "tee1.bin",
+ "pm": "tee1.dts"
+ },
+
+ "tee2" : {
+ "image": "tee2.bin",
+ "pm": "tee2.dts"
+ }
+ }
+
+SPMC manifest
+~~~~~~~~~~~~~
+
+This manifest contains an SPMC attributes node consumed by SPMD at boot time. It
+is implementing the description from `[1]`_ section 3.2 (SP manifest at physical
+FF-A instance). The SP manifest at physical FF-A instance is used by the SPMD to
+setup a SP that co-resides with the SPMC and executes at S-EL1 or Secure
+Supervisor mode.
+
+In this implementation its usage is extended to the secure physical FF-A
+instance where SPMC executes at S-EL2.
+
+.. code:: shell
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x0>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x6000000>;
+ entrypoint = <0x0 0x6000000>;
+ binary_size = <0x60000>;
+ };
+
+- *spmc_id* defines the endpoint ID value that SPMC can query through
+ ``FFA_ID_GET``.
+- *maj_ver/min_ver*. SPMD checks provided version versus its internal
+ version and aborts if not matching.
+- *exec_state* defines SPMC execution state (can be AArch64 for
+ Hafnium, or AArch64/AArch32 for OP-TEE at S-EL1).
+- *load_address* and *binary_size* are mostly used to verify secondary
+ entry points fit into the loaded binary image.
+- *entrypoint* defines the cold boot primary core entry point used by
+ SPMD (currently matches ``BL32_BASE``)
+
+Other nodes in the manifest are consumed by Hafnium in the secure world.
+A sample can be found at [7]:
+
+- The *chosen* node is currently unused in SWd. It is meant for NWd to
+ specify the init ramdisk image.
+- The *hypervisor* node describes SPs. *is_ffa_partition* boolean
+ attribute indicates an SP. Load-addr field specifies the load address
+ at which TF-A loaded the SP package.
+- *cpus* node provide the platform topology and allows MPIDR to VMPIDR
+ mapping. Notice with current implementation primary cpu is declared
+ first, then secondary cpus must be declared in reverse order.
+
+SPMC boot
+~~~~~~~~~
+
+The SPMC is loaded by BL2 as the BL32 image.
+
+The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image.
+
+BL2 passes the SPMC manifest address to BL31 through a register.
+
+BL31(SPMD) runs from primary core, initializes the core contexts and
+launches BL32 passing the SPMC manifest address through a register.
+
+Loading of SPs
+~~~~~~~~~~~~~~
+
+.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
+
+
+Notice this boot flow is an implementation sample on Arm's FVP platform. Platforms
+not using FW_CONFIG would adjust to a different implementation.
+
+Secure boot
+~~~~~~~~~~~
+
+The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
+SPMC manifest and Secure Partitions and verifies them for authenticity and integrity.
+Refer to TBBR specification `[3]`_.
+
+The multiple-signing domain feature (in current state dual signing domain) allows
+the use of two root keys namely S-ROTPK and NS-ROTPK (see `[8]`_):
+
+- SPMC(BL32), SPMC manifest, SPs may be signed by the SiP using the S-ROTPK.
+- BL33 may be signed by the OEM using NS-ROTPK.
+
+Longer term multiple signing domain will allow additional signing keys, e.g.
+if SPs originate from different parties.
+
+See `TF-A build options`_ for a sample build command line.
+
+Hafnium in the secure world
+===========================
+
+**NOTE: this section is work in progress. Descriptions and implementation choices
+are subject to evolve.**
+
+General considerations
+----------------------
+
+Build platform for the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The implementation might add specific code parts only relevant to the
+secure world. Such code parts might be isolated into different files
+and/or conditional code enclosed by a ``SECURE_WORLD`` macro.
+
+Secure Partitions CPU scheduling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the normal world, VMs are scheduled by the FFA_RUN ABI invoked from the
+primary scheduler (in the primary VM), or by a direct message request or
+response.
+
+With the FF-A EAC specification, Secure Partitions are scheduled by direct
+message invocations from a NWd VM or another SP.
+
+Platform topology
+~~~~~~~~~~~~~~~~~
+
+As stated in `[1]`_ section 4.4.1 the SPMC implementation assumes the
+following SP types:
+
+- Pinned MP SPs: an Execution Context id matches a physical PE id. MP
+ SPs must implement the same number of ECs as the number of PEs in the
+ platform. Hence the *execution-ctx-count* as defined by
+ `[1]`_ (or NWd-Hafnium *vcpu_count*) can only take the
+ value of one or the number of physical PEs.
+- Migratable UP SPs: a single execution context can run and be migrated
+ on any physical PE. It declares a single EC in its SP manifest. An UP
+ SP can receive a direct message request on any physical core.
+
+Usage of PSCI services in the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The normal world Hypervisor (optional) or OS kernel issues PSCI service
+ invocations e.g. to request PSCI version, wake-up a secondary core, or request
+ core suspend. This happens at the non-secure physical FF-A instance. In the
+ example case of Hafnium in the normal world, it boots on the primary core and
+ one of the first initialization step is to request the PSCI version. It then
+ launches the primary VM. The primary VM upon initializing performs PSCI service
+ calls (at non-secure virtual FF-A instance) which are trapped by the
+ Hypervisor. Invocation from OS Kernel ends straight at EL3. The PVM issues
+ ``PSCI_CPU_ON`` service calls to wake-up secondary cores by passing an
+ ``MPIDR``, entry point address and a CPU context address. The EL3 PSCI layer
+ then performs an exception return to the secondary core entry point on the
+ targeted core. Other PSCI calls can happen at run-time from the PVM e.g. to
+ request core suspend.
+- In the existing TF-A PSCI standard library, PSCI service calls are filtered at
+ EL3 to only originate from the NWd. Thus concerning the SPMC (at secure
+ physical FF-A instance) the PSCI service invocations cannot happen as in the
+ normal world. For example, a ``PSCI_CPU_ON`` service invocation from the SPMC
+ does not reach the PSCI layer.
+
+Parsing SP partition manifests
+------------------------------
+
+Hafnium must be able to consume SP manifests as defined in
+`[1]`_ section 3.1, at least for the mandatory fields.
+
+The SP manifest may contain memory and device regions nodes.
+
+- Memory regions shall be mapped in the SP Stage-2 translation regime at
+ load time. A memory region node can specify RX/TX buffer regions in which
+ case it is not necessary for an SP to explicitly call the ``FFA_RXTX_MAP``
+ service.
+- Device regions shall be mapped in SP Stage-2 translation regime as
+ peripherals and possibly allocate additional resources (e.g. interrupts)
+
+Base addresses for memory and device region nodes are IPAs provided SPMC
+identity maps IPAs to PAs within SP Stage-2 translation regime.
+
+Note: currently both VTTBR_EL2 and VSTTBR_EL2 resolve to the same set of page
+tables. It is still open whether two sets of page tables shall be provided per
+SP. The memory region node as defined in the spec (section 3.1 Table 10)
+provides a memory security attribute hinting to map either to the secure or
+non-secure stage-2 table.
+
+Passing boot data to the SP
+---------------------------
+
+`[1]`_ Section 3.4.2 “Protocol for passing data” defines a
+method to passing boot data to SPs (not currently implemented).
+
+Provided that the whole Secure Partition package image (see `Secure
+Partition packages`_) is mapped to the SP's secure Stage-2 translation
+regime, an SP can access its own manifest DTB blob and extract its partition
+manifest properties.
+
+SP Boot order
+-------------
+
+SP manifests provide an optional boot order attribute meant to resolve
+dependencies such as an SP providing a service required to properly boot
+another SP.
+
+Boot phases
+-----------
+
+Primary core boot-up
+~~~~~~~~~~~~~~~~~~~~
+
+The SPMC performs its platform initializations then loads and creates
+secure partitions based on SP packages and manifests. Then each secure
+partition is launched in sequence (see `SP Boot order`_) on their primary
+Execution Context.
+
+Notice the primary physical core may not be core 0. Hence if the primary
+core linear id is N, the 1:1 mapping requires MP SPs are launched using
+EC[N] on PE[N] (see `Platform topology`_).
+
+The SP's primary Execution Context (or the EC used when the partition is booted)
+exits through ``FFA_MSG_WAIT`` to indicate successful initialization.
+
+Secondary physical core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Upon boot-up, the SPMC running on the primary core performs
+implementation-defined SPMD service calls at secure physical FF-A instance
+to register the secondary physical cores entry points and context information:
+
+- This is done through a direct message request invocation to the SPMD
+ (``SET_ENTRY_POINT``). This service call does not wake-up the targeted
+ core immediately. The secondary core is woken up later by a NWd
+ ``PSCI_CPU_ON`` service invocation. A notification is passed from EL3
+ PSCI layer to the SPMD, and then to SPMC through an implementation-defined
+ interface.
+- The SPMC/SPMD interface can consist of FF-A direct message requests/responses
+ transporting PM events.
+
+If there is no Hypervisor in the normal world, the OS Kernel issues
+``PSCI_CPU_ON`` calls that are directly trapped to EL3.
+
+When a secondary physical core wakes-up the SPMD notifies the SPMC which updates
+its internal states reflecting current physical core is being turned on.
+It might then return straight to the SPMD and then to the NWd.
+
+*(under discussion)* There may be possibility that an SP registers "PM events"
+(during primary EC boot stage) through an ad-hoc interface. Such events would
+be relayed by SPMC to one or more registered SPs on need basis
+(see `Power management`_).
+
+Secondary virtual core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the example case where Hafnium exists in the normal world, secondary VMs
+issue a ``PSCI_CPU_ON`` service call which is trapped to the Hypervisor. The
+latter then enables the vCPU context for the targeted core, and switches to
+the PVM down to the kernel driver with an ``HF_WAKE_UP`` message. The NWd
+driver in PVM can then schedule the newly woken up vCPU context.
+
+In the secure world the primary EC of a given SP passes the secondary EC entry
+point and context. The SMC service call is trapped into the SPMC. This can be
+either *(under discussion)*:
+
+- a specific interface registering the secondary EC entry point,
+ similarly to above ``SET_ENTRY_POINT`` service.
+- Re-purposing the ``PSCI_CPU_ON`` function id. It is
+ assumed that even if the input arguments are the same as the ones defined in
+ the PSCI standard, the usage deviates by the fact the secondary EC is not
+ woken up immediately. At least for the PSA-FF-A EAC where only
+ direct messaging is allowed, it is only after the first direct
+ message invocation that the secondary EC is entered. This option
+ might be preferred when the same code base is re-used for a VM or
+ an SP. The ABI to wake-up a secondary EC can remain similar.
+
+SPs are always scheduled from the NWd, this paradigm did not change from legacy
+TEEs. There must always be some logic (or driver) in the NWd to relinquish CPU
+cycles to the SWd. If primary core is 0, an SP EC[x>0] entry point is supplied
+by the SP EC[0] when the system boots in SWd. But this EC[x] is not immediately
+entered at boot. Later in the boot process when NWd is up, a direct message
+request issued from physical core 1 ends up in SP EC[1], and only at this stage
+this context is effectively scheduled.
+
+It should be possible for an SP to call into another SP through direct message
+provided the latter SP has been booted already. The "boot-order" field in
+partition manifests (`SP Boot order`_) fulfills the dependency towards availability
+of a service within an SP offered to another SP.
+
+Mandatory interfaces
+--------------------
+
+The following interfaces must be exposed to any VM or SP:
+
+- ``FFA_STATUS``
+- ``FFA_ERROR``
+- ``FFA_INTERRUPT``
+- ``FFA_VERSION``
+- ``FFA_FEATURES``
+- ``FFA_RX_RELEASE``
+- ``FFA_RXTX_MAP``
+- ``FFA_RXTX_UNMAP``
+- ``FFA_PARTITION_INFO_GET``
+- ``FFA_ID_GET``
+
+FFA_VERSION
+~~~~~~~~~~~
+
+Per `[1]`_ section 8.1 ``FFA_VERSION`` requires a
+*requested_version* parameter from the caller.
+
+In the current implementation when ``FFA_VERSION`` is invoked from:
+
+- Hypervisor in NS-EL2: the SPMD returns the SPMC version specified
+ in the SPMC manifest.
+- OS kernel in NS-EL1 when NS-EL2 is not present: the SPMD returns the
+ SPMC version specified in the SPMC manifest.
+- VM in NWd: the Hypervisor returns its implemented version.
+- SP in SWd: the SPMC returns its implemented version.
+- SPMC at S-EL1/S-EL2: the SPMD returns its implemented version.
+
+FFA_FEATURES
+~~~~~~~~~~~~
+
+FF-A features may be discovered by Secure Partitions while booting
+through the SPMC. However, SPMC cannot get features from Hypervisor
+early at boot time as NS world is not setup yet.
+
+The Hypervisor may decide to gather FF-A features from SPMC through SPMD
+once at boot time and store the result. Later when a VM requests FF-A
+features, the Hypervisor can adjust its own set of features with what
+SPMC advertised, if necessary. Another approach is to always forward FF-A
+features to the SPMC when a VM requests it to the Hypervisor. Although
+the result is not supposed to change over time so there may not be added
+value doing the systematic forwarding.
+
+FFA_RXTX_MAP/FFA_RXTX_UNMAP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+VM mailboxes are re-purposed to serve as SP RX/TX buffers. The RX/TX
+map API maps the send and receive buffer IPAs to the SP Stage-2 translation regime.
+
+Hafnium in the normal world defines VMs and their attributes as logical structures,
+including a mailbox used for FF-A indirect messaging, memory sharing, or the
+`FFA_PARTITION_INFO_GET`_ ABI.
+This same mailbox structure is re-used in the SPMC. `[1]`_ states only direct
+messaging is allowed to SPs. Thus mailbox usage is restricted to implementing
+`FFA_PARTITION_INFO_GET`_ and memory sharing ABIs.
+
+FFA_PARTITION_INFO_GET
+~~~~~~~~~~~~~~~~~~~~~~
+
+Partition info get service call can originate:
+
+- from SP to SPM
+- from VM to Hypervisor
+- from Hypervisor to SPM
+
+For the latter case, the service call must be forwarded through the SPMD.
+
+FFA_ID_GET
+~~~~~~~~~~
+
+The SPMD returns:
+
+- a default zero value on invocation from the Hypervisor.
+- The ``spmc_id`` value specified in the SPMC manifest on invocation from
+ the SPMC (see `SPMC manifest`_)
+
+The FF-A id space is split into a non-secure space and secure space:
+
+- FF-A id with bit 15 clear refer to normal world VMs.
+- FF-A id with bit 15 set refer to secure world SPs
+
+Such convention helps the SPMC discriminating the origin and destination worlds
+in an FF-A service invocation. In particular the SPMC shall filter unauthorized
+transactions in its world switch routine. It must not be permitted for a VM to
+use a secure FF-A id as origin world through spoofing:
+
+- A VM-to-SP messaging passing shall have an origin world being non-secure
+ (FF-A id bit 15 clear) and destination world being secure (FF-A id bit 15
+ set).
+- Similarly, an SP-to-SP message shall have FF-A id bit 15 set for both origin
+ and destination ids.
+
+An incoming direct message request arriving at SPMD from NWd is forwarded to
+SPMC without a specific check. The SPMC is resumed through eret and "knows" the
+message is coming from normal world in this specific code path. Thus the origin
+endpoint id must be checked by SPMC for being a normal world id.
+
+An SP sending a direct message request must have bit 15 set in its origin
+endpoint id and this can be checked by the SPMC when the SP invokes the ABI.
+
+The SPMC shall reject the direct message if the claimed world in origin endpoint
+id is not consistent:
+
+- It is either forwarded by SPMD and thus origin endpoint id must be a "normal
+ world id",
+- or initiated by an SP and thus origin endpoint id must be a "secure world id".
+
+Direct messaging
+----------------
+
+This is a mandatory interface for Secure Partitions consisting in direct
+message request and responses.
+
+The ``ffa_handler`` Hafnium function may:
+
+- trigger a world change e.g. when an SP invokes the direct message
+ response ABI to a VM.
+- handle multiple requests from the NWd without resuming an SP.
+
+SP-to-SP
+~~~~~~~~
+
+- An SP can send a direct message request to another SP
+- An SP can receive a direct message response from another SP.
+
+VM-to-SP
+~~~~~~~~
+
+- A VM can send a direct message request to an SP
+- An SP can send a direct message response to a VM
+
+SPMC-SPMD messaging
+~~~~~~~~~~~~~~~~~~~
+
+Specific implementation-defined endpoint IDs are allocated to the SPMC and SPMD.
+Referring those IDs in source/destination fields of a direct message
+request/response permits SPMD to SPMC messaging back and forth.
+
+Per `[1]`_ Table 114 Config No. 1 (physical FF-A instance):
+
+- SPMC=>SPMD direct message request uses SMC conduit
+- SPMD=>SPMC direct message request uses ERET conduit
+
+Per `[1]`_ Table 118 Config No. 1 (physical FF-A instance):
+
+- SPMC=>SPMD direct message response uses SMC conduit
+- SPMD=>SPMC direct message response uses ERET conduit
+
+Memory management
+-----------------
+
+This section only deals with the PE MMU configuration.
+
+Hafnium in the normal world deals with NS buffers only and provisions
+a single root page table directory to VMs. In context of S-EL2 enabled
+firmware, two IPA spaces are output from Stage-1 translation (secure
+and non-secure). The Stage-2 translation handles:
+
+- A single secure IPA space when an SP Stage-1 MMU is disabled.
+- Two IPA spaces (secure and non-secure) when Stage-1 MMU is enabled.
+
+``VTCR_EL2`` and ``VSTCR_EL2`` provide additional bits for controlling the
+NS/S IPA translations (``VSTCR_EL2.SW``, ``VSTCR_EL2.SA``, ``VTCR_EL2.NSW``,
+``VTCR_EL2.NSA``). There may be two approaches:
+
+- secure and non-secure mappings are rooted as two separate root page
+ tables
+- secure and non-secure mappings use the same root page table. Access
+ from S-EL1 to an NS region translates to a secure physical address
+ space access.
+
+Interrupt management
+--------------------
+
+Road to a para-virtualized interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Current Hafnium implementation uses an ad-hoc mechanism for a VM to get
+a pending interrupt number through an hypercall. The PVM injects
+interrupts to VMs by delegation from the Hypervisor. The PVM probes a
+pending interrupt directly from the GIC distributor.
+
+The short-term plan is to have Hafnium/SPMC in the secure world owner
+of the GIC configuration.
+
+The SPMC fully owns the GIC configuration at S-EL2. The SPMC manages
+interrupt resources and allocates interrupt ID based on SP manifests.
+The SPMC acknowledges physical interrupts and injects virtual interrupts
+by setting the vIRQ bit when resuming an SP. A Secure Partition gathers
+the interrupt number through an hypercall.
+
+Notice the SPMC/SPMD has to handle Group0 secure interrupts in addition
+to Group1 S/NS interrupts.
+
+Power management
+----------------
+
+Assumption on the Nwd:
+
+- NWd is the best candidate to own the platform Power Management
+ policy. It is master to invoking PSCI service calls from physical
+ CPUs.
+- EL3 monitor is in charge of the PM control part (its PSCI layer
+ actually writing to platform registers).
+- It is fine for the Hypervisor to trap PSCI calls and relay to EL3, or
+ OS kernel driver to emit PSCI service calls.
+
+PSCI notification are relayed through the SPMD/SPD PM hooks to the SPMC.
+This can either be through re-use of PSCI FIDs or an FF-A direct message
+from SPMD to SPMC.
+
+The SPMD performs an exception return to the SPMC which is resumed to
+its ``eret_handler`` routine. It is then either consuming a PSCI FID or
+an FF-A FID. Depending on the servicing, the SPMC may return directly to
+the SPMD (and then NWd) without resuming an SP at this stage. An example
+of this is invocation of ``FFA_PARTITION_INFO_GET`` from NWd relayed by
+the SPMD to the SPMC. The SPMC returns the needed partition information
+to the SPMD (then NWd) without actually resuming a partition in secure world.
+
+*(under discussion)*
+About using PSCI FIDs from SPMD to SPMC to notify of PM events, it is still
+questioned what to use as the return code from the SPMC.
+If the function ID used by the SPMC is not an FF-A ID when doing SMC, then the
+EL3 std svc handler won't route the response to the SPMD. That's where comes the
+idea to embed the notification into an FF-A message. The SPMC can discriminate
+this message as being a PSCI event, process it, and reply with an FF-A return
+message that the SPMD receives as an acknowledgement.
+
+SP notification
+---------------
+
+Power management notifications are conveyed from PSCI library to the
+SPMD / SPD hooks. A range of events can be relayed to SPMC.
+
+SPs may need to be notified about specific PM events.
+
+- SPs might register PM events to the SPMC
+- On SPMD to SPMC notification, a limited range of SPs may be notified
+ through a direct message.
+- This assumes the mentioned SPs supports managed exit.
+
+The SPMC is the first to be notified about PM events from the SPMD. It is up
+to the SPMC to arbitrate to which SP it needs to send PM events.
+An SP explicitly registers to receive notifications to specific PM events.
+The register operation can either be an implementation-defined service call
+to the SPMC when the primary SP EC boots, or be supplied through the SP
+manifest.
+
+References
+==========
+
+.. _[1]:
+
+[1] `Platform Security Architecture Firmware Framework for Arm® v8-A 1.0 Platform Design Document <https://developer.arm.com/docs/den0077/latest>`__
+
+.. _[2]:
+
+[2] `Secure Partition Manager using MM interface`__
+
+.. __: secure-partition-manager-mm.html
+
+.. _[3]:
+
+[3] `Trusted Boot Board Requirements
+Client <https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a>`__
+
+.. _[4]:
+
+[4] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime/aarch64/context.S#n45
+
+.. _[5]:
+
+[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/cactus.dts
+
+.. _[6]:
+
+[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/psa-ffa-manifest-binding.html
+
+.. _[7]:
+
+[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+
+.. _[8]:
+
+[8] https://developer.trustedfirmware.org/w/tf_a/poc-multiple-signing-domains/
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 78a80f6..6b6c639 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -278,9 +278,6 @@
- ``ERRATA_N1_1542419``: This applies errata 1542419 workaround to Neoverse-N1
CPU. This needs to be enabled only for revisions r3p0 - r4p0 of the CPU.
-- ``ERRATA_N1_1800710``: This applies errata 1800710 workaround to Neoverse-N1
- CPU. This needs to be enabled only for revisions <= r4p0 of the CPU.
-
DSU Errata Workarounds
----------------------
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 891a9a2..ae6dd46 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -988,7 +988,7 @@
Exception Handling Framework
----------------------------
-Please refer to the `Exception Handling Framework`_ document.
+Please refer to the :ref:`Exception Handling Framework` document.
Power State Coordination Interface
----------------------------------
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index bfc50df..630d861 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -721,6 +721,10 @@
bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs.
This flag is disabled by default.
+- ``OPENSSL_DIR``: This flag is used to provide the installed openssl directory
+ path on the host machine which is used to build certificate generation and
+ firmware encryption tool.
+
GICv3 driver options
--------------------
diff --git a/docs/getting_started/docs-build.rst b/docs/getting_started/docs-build.rst
index 91b1b3a..87c677f 100644
--- a/docs/getting_started/docs-build.rst
+++ b/docs/getting_started/docs-build.rst
@@ -67,7 +67,7 @@
::
- docs/build/html/
+ docs/build/html
We also support building documentation in other formats. From the ``docs``
directory of the project, run the following command to see the supported
@@ -79,6 +79,31 @@
make help
+Building rendered documentation from a container
+------------------------------------------------
+
+There may be cases where you can not either install or upgrade required
+dependencies to generate the documents, so in this case, one way to
+create the documentation is through a docker container. The first step is
+to check if `docker`_ is installed in your host, otherwise check main docker
+page for installation instructions. Once installed, run the following script
+from project root directory
+
+.. code:: shell
+
+ docker run --rm -v $PWD:/TF sphinxdoc/sphinx \
+ bash -c 'cd /TF && \
+ pip3 install plantuml -r ./docs/requirements.txt && make doc'
+
+The above command fetches the ``sphinxdoc/sphinx`` container from `docker
+hub`_, launches the container, installs documentation requirements and finally
+creates the documentation. Once done, exit the container and output from the
+build process will be placed in:
+
+::
+
+ docs/build/html
+
--------------
*Copyright (c) 2019, Arm Limited. All rights reserved.*
@@ -86,3 +111,5 @@
.. _Sphinx: http://www.sphinx-doc.org/en/master/
.. _pip homepage: https://pip.pypa.io/en/stable/
.. _Dia: https://wiki.gnome.org/Apps/Dia
+.. _docker: https://www.docker.com/
+.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index c98f3cc..7aaeae2 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1130,6 +1130,7 @@
soc_version[30:24] = JEP-106 continuation code for the SiP
soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+ soc_version[15:0] = Implementation defined SoC ID
Function : plat_get_soc_revision()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1145,6 +1146,18 @@
soc_revision[0:30] = SOC revision of specific SOC
+Function : plat_is_smccc_feature_available()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : u_register_t
+ Return : int32_t
+
+This function returns SMC_ARCH_CALL_SUCCESS if the platform supports
+the SMCCC function specified in the argument; otherwise returns
+SMC_ARCH_CALL_NOT_SUPPORTED.
+
Modifications specific to a Boot Loader stage
---------------------------------------------
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index a6ff19a..fd658bb 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -42,10 +42,11 @@
- ``FVP_Base_Neoverse-E1x4``
- ``FVP_Base_Neoverse-N1x4``
- ``FVP_Base_Zeusx4``
-- ``FVP_CSS_SGI-575`` (Version 11.10 build 25)
+- ``FVP_CSS_SGI-575`` (Version 11.10 build 36)
- ``FVP_CSS_SGM-775``
-- ``FVP_RD_E1Edge``
-- ``FVP_RD_N1Edge`` (Version 11.10 build 25)
+- ``FVP_RD_E1_edge`` (Version 11.10 build 36)
+- ``FVP_RD_N1_edge`` (Version 11.10 build 36)
+- ``FVP_RD_N1_edge_dual`` (Version 11.10 build 36)
- ``Foundation_Platform``
The latest version of the AArch32 build of TF-A has been tested on the
diff --git a/docs/resources/diagrams/ff-a-spm-sel2.png b/docs/resources/diagrams/ff-a-spm-sel2.png
new file mode 100644
index 0000000..6479ff5
--- /dev/null
+++ b/docs/resources/diagrams/ff-a-spm-sel2.png
Binary files differ
diff --git a/docs/resources/diagrams/plantuml/bl2-loading-sp.puml b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
new file mode 100644
index 0000000..3cf7c36
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
@@ -0,0 +1,44 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+participant bl1
+participant FIP
+
+bl1 -> FIP : read(FW_CONFIG)
+create FW_CONFIG
+bl1 -> FW_CONFIG : load
+
+bl1 -> FIP : read(bl2)
+create bl2
+bl1 -> bl2 : load
+bl1 --> bl2 : hand off (FW_CONFIG)
+
+bl2 -> FW_CONFIG : read_node(SPKs)
+loop for each spkg subnode
+ bl2 -> FW_CONFIG : read(UUID)
+ bl2 -> FW_CONFIG : read(load_address)
+ bl2 -> FIP : read(spkg@UUID)
+ create SPKG
+ bl2 -> SPKG : load
+end loop
+
+bl2 -> FW_CONFIG : read_node(TOS_FW_CONFIG)
+create TOS_FW_CONFIG
+bl2 -> TOS_FW_CONFIG : load
+
+bl2 -> FIP : read(bl32/SPMC)
+create SPMC
+bl2 -> SPMC : load
+
+bl2 -> FIP : read(bl31)
+create bl31
+bl2 -> bl31 : load
+bl2 --> bl31 : hand off (TOS_FW_CONFIG)
+
+bl31 --> SPMC : hand off (TOS_FW_CONFIG)
+
+@enduml
diff --git a/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
new file mode 100644
index 0000000..40621db
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
@@ -0,0 +1,122 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+
+folder SP_vendor_1 {
+ artifact sp_binary_1
+ artifact sp_manifest_1 [
+ sp_manifest_1
+ ===
+ UUID = xxx
+ load_address = 0xaaa
+ ...
+ ]
+}
+
+folder SP_vendor_2 {
+ artifact sp_binary_2
+ artifact sp_manifest_2 [
+ sp_manifest_2
+ ===
+ UUID = yyy
+ load_address = 0xbbb
+ ]
+}
+
+artifact config.json [
+ SP_LAYOUT.json
+ ===
+ path to sp_binary_1
+ path to sp_manifest_1
+ ---
+ path to sp_binary_2
+ path to sp_manifest_2
+ ---
+ ...
+]
+
+control sp_mk_generator
+
+artifact fconf_node [
+ fconf_sp.dts
+ ===
+ spkg_1 UUID
+ spkg_1 load_address
+ ---
+ spkg_2 UUID
+ spkg_2 load_address
+]
+
+artifact sp_gen [
+ sp_gen.mk
+ ===
+ FDT_SOURCE = ...
+ SPTOOL_ARGS = ...
+ FIP_ARG = ...
+]
+
+control dtc
+control sptool
+
+artifact FW_CONFIG
+
+artifact spkg_1 [
+ spkg_1.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+artifact spkg_2 [
+ spkg_2.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+control fiptool
+
+artifact fip [
+ fip.bin
+ ===
+ FW_CONFIG.dtb
+ ---
+ ...
+ ---
+ SPKG1
+ ---
+ SPKG2
+ ---
+ ...
+]
+
+config.json .up.> SP_vendor_1
+config.json .up.> SP_vendor_2
+config.json --> sp_mk_generator
+sp_mk_generator --> fconf_node
+sp_mk_generator --> sp_gen
+
+sp_gen --> sptool
+sptool --> spkg_1
+sptool --> spkg_2
+
+fconf_node -down-> dtc
+dtc --> FW_CONFIG
+
+sp_gen --> fiptool
+FW_CONFIG --> fiptool
+spkg_1 -down-> fiptool
+spkg_2 -down-> fiptool
+fiptool -down-> fip
+
+@enduml
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
index c9e9cb9..6e106ba 100644
--- a/drivers/arm/gic/v3/gic-x00.c
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -21,10 +21,10 @@
#include "gicv3_private.h"
/* GIC-600 specific register offsets */
-#define GICR_PWRR 0x24
-#define IIDR_MODEL_ARM_GIC_600 (0x0200043b)
-#define IIDR_MODEL_ARM_GIC_600AE (0x0300043b)
-#define IIDR_MODEL_ARM_GIC_CLAYTON (0x0400043b)
+#define GICR_PWRR 0x24U
+#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b)
+#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b)
+#define IIDR_MODEL_ARM_GIC_CLAYTON U(0x0400043b)
/* GICR_PWRR fields */
#define PWRR_RDPD_SHIFT 0
@@ -32,17 +32,17 @@
#define PWRR_RDGPD_SHIFT 2
#define PWRR_RDGPO_SHIFT 3
-#define PWRR_RDPD (1 << PWRR_RDPD_SHIFT)
-#define PWRR_RDAG (1 << PWRR_RDAG_SHIFT)
-#define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT)
-#define PWRR_RDGPO (1 << PWRR_RDGPO_SHIFT)
+#define PWRR_RDPD (1U << PWRR_RDPD_SHIFT)
+#define PWRR_RDAG (1U << PWRR_RDAG_SHIFT)
+#define PWRR_RDGPD (1U << PWRR_RDGPD_SHIFT)
+#define PWRR_RDGPO (1U << PWRR_RDGPO_SHIFT)
/*
* Values to write to GICR_PWRR register to power redistributor
* for operating through the core (GICR_PWRR.RDAG = 0)
*/
-#define PWRR_ON (0 << PWRR_RDPD_SHIFT)
-#define PWRR_OFF (1 << PWRR_RDPD_SHIFT)
+#define PWRR_ON (0U << PWRR_RDPD_SHIFT)
+#define PWRR_OFF (1U << PWRR_RDPD_SHIFT)
#if GICV3_SUPPORT_GIC600
@@ -59,10 +59,14 @@
static void gicr_wait_group_not_in_transit(uintptr_t base)
{
+ uint32_t pwrr;
+
+ do {
+ pwrr = gicr_read_pwrr(base);
+
/* Check group not transitioning: RDGPD == RDGPO */
- while (((gicr_read_pwrr(base) & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
- ((gicr_read_pwrr(base) & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT))
- ;
+ } while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
+ ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT));
}
static void gic600_pwr_on(uintptr_t base)
@@ -94,7 +98,7 @@
* In that case, wait as long as it's in transition, or has aborted
* the transition altogether for any reason.
*/
- if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0) {
+ if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) {
/* Wait until group not transitioning */
gicr_wait_group_not_in_transit(base);
}
@@ -104,12 +108,12 @@
{
uintptr_t gicr_base;
- assert(gicv3_driver_data);
+ assert(gicv3_driver_data != NULL);
assert(proc_num < gicv3_driver_data->rdistif_num);
- assert(gicv3_driver_data->rdistif_base_addrs);
+ assert(gicv3_driver_data->rdistif_base_addrs != NULL);
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
- assert(gicr_base);
+ assert(gicr_base != 0UL);
return gicr_base;
}
@@ -127,7 +131,7 @@
((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
}
-#endif
+#endif /* GICV3_SUPPORT_GIC600 */
void gicv3_distif_pre_save(unsigned int proc_num)
{
@@ -139,7 +143,6 @@
arm_gicv3_distif_post_restore(proc_num);
}
-
/*
* Power off GIC-600 redistributor (if configured and detected)
*/
diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c
index 64ec5ab..7e307ee 100644
--- a/drivers/arm/tzc/tzc_dmc620.c
+++ b/drivers/arm/tzc/tzc_dmc620.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,7 +17,7 @@
/* Helper macro for getting dmc_base addr of a dmc_inst */
#define DMC_BASE(plat_data, dmc_inst) \
- ((uintptr_t)(plat_data->dmc_base[dmc_inst]))
+ ((uintptr_t)((plat_data)->dmc_base[(dmc_inst)]))
/* Pointer to the tzc_dmc620_config_data structure populated by the platform */
static const tzc_dmc620_config_data_t *g_plat_config_data;
@@ -31,8 +31,7 @@
static void tzc_dmc620_validate_plat_driver_data(
const tzc_dmc620_driver_data_t *plat_driver_data)
{
- uint8_t dmc_inst, dmc_count;
- unsigned int dmc_id;
+ unsigned int dmc_inst, dmc_count, dmc_id;
uintptr_t base;
assert(plat_driver_data != NULL);
@@ -59,7 +58,7 @@
{
uint32_t min_31_00, min_47_32;
uint32_t max_31_00, max_47_32;
- uint8_t dmc_inst, dmc_count;
+ unsigned int dmc_inst, dmc_count;
uintptr_t base;
const tzc_dmc620_driver_data_t *plat_driver_data;
@@ -67,19 +66,19 @@
assert(plat_driver_data != NULL);
/* Do range checks on regions. */
- assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT));
+ assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT));
/* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
dmc_count = plat_driver_data->dmc_count;
for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
- min_31_00 = (region_base & MASK_31_16) | sec_attr;
- min_47_32 = (region_base & MASK_47_32)
- >> DMC620_ACC_ADDR_WIDTH;
- max_31_00 = (region_top & MASK_31_16);
- max_47_32 = (region_top & MASK_47_32)
- >> DMC620_ACC_ADDR_WIDTH;
+ min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr);
+ min_47_32 = (uint32_t)((region_base & MASK_47_32)
+ >> DMC620_ACC_ADDR_WIDTH);
+ max_31_00 = (uint32_t)(region_top & MASK_31_16);
+ max_47_32 = (uint32_t)((region_top & MASK_47_32)
+ >> DMC620_ACC_ADDR_WIDTH);
/* Extract the base address of the DMC-620 instance */
base = DMC_BASE(plat_driver_data, dmc_inst);
@@ -100,7 +99,7 @@
*/
static void tzc_dmc620_set_action(void)
{
- uint8_t dmc_inst, dmc_count;
+ unsigned int dmc_inst, dmc_count;
uintptr_t base;
const tzc_dmc620_driver_data_t *plat_driver_data;
@@ -123,7 +122,7 @@
*/
static void tzc_dmc620_verify_complete(void)
{
- uint8_t dmc_inst, dmc_count;
+ unsigned int dmc_inst, dmc_count;
uintptr_t base;
const tzc_dmc620_driver_data_t *plat_driver_data;
@@ -133,8 +132,9 @@
/* Extract the base address of the DMC-620 instance */
base = DMC_BASE(plat_driver_data, dmc_inst);
while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
- DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO)
+ DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) {
continue;
+ }
}
}
@@ -145,7 +145,7 @@
*/
void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
{
- int i;
+ uint8_t i;
/* Check if valid pointer is passed */
assert(plat_config_data != NULL);
@@ -164,11 +164,12 @@
g_plat_config_data = plat_config_data;
INFO("Configuring DMC-620 TZC settings\n");
- for (i = 0U; i < g_plat_config_data->acc_addr_count; i++)
+ for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) {
tzc_dmc620_configure_region(i,
g_plat_config_data->plat_acc_addr_data[i].region_base,
g_plat_config_data->plat_acc_addr_data[i].region_top,
g_plat_config_data->plat_acc_addr_data[i].sec_attr);
+ }
tzc_dmc620_set_action();
tzc_dmc620_verify_complete();
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
index 31e5d65..68f3d46 100644
--- a/drivers/auth/dualroot/cot.c
+++ b/drivers/auth/dualroot/cot.c
@@ -693,8 +693,8 @@
* Secure Partitions
*/
#if defined(SPD_spmd)
-static const auth_img_desc_t sp_content_cert = {
- .img_id = SP_CONTENT_CERT_ID,
+static const auth_img_desc_t sip_sp_content_cert = {
+ .img_id = SIP_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
@@ -775,14 +775,14 @@
}
};
-DEFINE_SP_PKG(1);
-DEFINE_SP_PKG(2);
-DEFINE_SP_PKG(3);
-DEFINE_SP_PKG(4);
-DEFINE_SP_PKG(5);
-DEFINE_SP_PKG(6);
-DEFINE_SP_PKG(7);
-DEFINE_SP_PKG(8);
+DEFINE_SIP_SP_PKG(1);
+DEFINE_SIP_SP_PKG(2);
+DEFINE_SIP_SP_PKG(3);
+DEFINE_SIP_SP_PKG(4);
+DEFINE_SIP_SP_PKG(5);
+DEFINE_SIP_SP_PKG(6);
+DEFINE_SIP_SP_PKG(7);
+DEFINE_SIP_SP_PKG(8);
#endif /* SPD_spmd */
#else /* IMAGE_BL2 */
@@ -914,15 +914,15 @@
[BL33_IMAGE_ID] = &bl33_image,
[NT_FW_CONFIG_ID] = &nt_fw_config,
#if defined(SPD_spmd)
- [SP_CONTENT_CERT_ID] = &sp_content_cert,
- [SP_CONTENT_CERT_ID + 1] = &sp_pkg1,
- [SP_CONTENT_CERT_ID + 2] = &sp_pkg2,
- [SP_CONTENT_CERT_ID + 3] = &sp_pkg3,
- [SP_CONTENT_CERT_ID + 4] = &sp_pkg4,
- [SP_CONTENT_CERT_ID + 5] = &sp_pkg5,
- [SP_CONTENT_CERT_ID + 6] = &sp_pkg6,
- [SP_CONTENT_CERT_ID + 7] = &sp_pkg7,
- [SP_CONTENT_CERT_ID + 8] = &sp_pkg8,
+ [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
+ [SP_PKG1_ID] = &sp_pkg1,
+ [SP_PKG2_ID] = &sp_pkg2,
+ [SP_PKG3_ID] = &sp_pkg3,
+ [SP_PKG4_ID] = &sp_pkg4,
+ [SP_PKG5_ID] = &sp_pkg5,
+ [SP_PKG6_ID] = &sp_pkg6,
+ [SP_PKG7_ID] = &sp_pkg7,
+ [SP_PKG8_ID] = &sp_pkg8,
#endif
};
#endif
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 564a4c9..94f2f59 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -75,19 +75,10 @@
ifeq (${HASH_ALG}, sha384)
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA384
- MBEDTLS_MD_ID := MBEDTLS_MD_SHA384
- TPM_ALG_ID := TPM_ALG_SHA384
- TCG_DIGEST_SIZE := 48
else ifeq (${HASH_ALG}, sha512)
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA512
- MBEDTLS_MD_ID := MBEDTLS_MD_SHA512
- TPM_ALG_ID := TPM_ALG_SHA512
- TCG_DIGEST_SIZE := 64
else
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA256
- MBEDTLS_MD_ID := MBEDTLS_MD_SHA256
- TPM_ALG_ID := TPM_ALG_SHA256
- TCG_DIGEST_SIZE := 32
endif
ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa)
@@ -112,11 +103,6 @@
$(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
$(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM))
-# Set definitions for measured boot driver
-$(eval $(call add_define,MBEDTLS_MD_ID))
-$(eval $(call add_define,TPM_ALG_ID))
-$(eval $(call add_define,TCG_DIGEST_SIZE))
-
$(eval $(call MAKE_LIB,mbedtls))
endif
diff --git a/drivers/auth/tbbr/tbbr_cot_bl2.c b/drivers/auth/tbbr/tbbr_cot_bl2.c
index 63c18fa..65a0478 100644
--- a/drivers/auth/tbbr/tbbr_cot_bl2.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl2.c
@@ -558,8 +558,8 @@
};
/* Secure Partitions */
#if defined(SPD_spmd)
-static const auth_img_desc_t sp_content_cert = {
- .img_id = SP_CONTENT_CERT_ID,
+static const auth_img_desc_t sip_sp_content_cert = {
+ .img_id = SIP_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
@@ -640,14 +640,14 @@
}
};
-DEFINE_SP_PKG(1);
-DEFINE_SP_PKG(2);
-DEFINE_SP_PKG(3);
-DEFINE_SP_PKG(4);
-DEFINE_SP_PKG(5);
-DEFINE_SP_PKG(6);
-DEFINE_SP_PKG(7);
-DEFINE_SP_PKG(8);
+DEFINE_SIP_SP_PKG(1);
+DEFINE_SIP_SP_PKG(2);
+DEFINE_SIP_SP_PKG(3);
+DEFINE_SIP_SP_PKG(4);
+DEFINE_SIP_SP_PKG(5);
+DEFINE_SIP_SP_PKG(6);
+DEFINE_SIP_SP_PKG(7);
+DEFINE_SIP_SP_PKG(8);
#endif /* SPD_spmd */
static const auth_img_desc_t * const cot_desc[] = {
@@ -672,15 +672,15 @@
[BL33_IMAGE_ID] = &bl33_image,
[NT_FW_CONFIG_ID] = &nt_fw_config,
#if defined(SPD_spmd)
- [SP_CONTENT_CERT_ID] = &sp_content_cert,
- [SP_CONTENT_CERT_ID + 1] = &sp_pkg1,
- [SP_CONTENT_CERT_ID + 2] = &sp_pkg2,
- [SP_CONTENT_CERT_ID + 3] = &sp_pkg3,
- [SP_CONTENT_CERT_ID + 4] = &sp_pkg4,
- [SP_CONTENT_CERT_ID + 5] = &sp_pkg5,
- [SP_CONTENT_CERT_ID + 6] = &sp_pkg6,
- [SP_CONTENT_CERT_ID + 7] = &sp_pkg7,
- [SP_CONTENT_CERT_ID + 8] = &sp_pkg8,
+ [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
+ [SP_PKG1_ID] = &sp_pkg1,
+ [SP_PKG2_ID] = &sp_pkg2,
+ [SP_PKG3_ID] = &sp_pkg3,
+ [SP_PKG4_ID] = &sp_pkg4,
+ [SP_PKG5_ID] = &sp_pkg5,
+ [SP_PKG6_ID] = &sp_pkg6,
+ [SP_PKG7_ID] = &sp_pkg7,
+ [SP_PKG8_ID] = &sp_pkg8,
#endif
};
diff --git a/drivers/measured_boot/event_log.c b/drivers/measured_boot/event_log.c
new file mode 100644
index 0000000..0042c96
--- /dev/null
+++ b/drivers/measured_boot/event_log.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <arch_helpers.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/event_log.h>
+#include <mbedtls/md.h>
+
+#include <plat/common/platform.h>
+
+/* Event Log data */
+static uint8_t event_log[EVENT_LOG_SIZE];
+
+/* End of Event Log */
+#define EVENT_LOG_END ((uintptr_t)event_log + sizeof(event_log) - 1U)
+
+CASSERT(sizeof(event_log) >= LOG_MIN_SIZE, assert_event_log_size);
+
+/* Pointer in event_log[] */
+static uint8_t *log_ptr = event_log;
+
+/* Pointer to measured_boot_data_t */
+const static measured_boot_data_t *plat_data_ptr;
+
+static uintptr_t tos_fw_config_base;
+static uintptr_t nt_fw_config_base;
+
+/* TCG_EfiSpecIdEvent */
+static const id_event_headers_t id_event_header = {
+ .header = {
+ .pcr_index = PCR_0,
+ .event_type = EV_NO_ACTION,
+ .digest = {0},
+ .event_size = (uint32_t)(sizeof(id_event_struct_t) +
+ (sizeof(id_event_algorithm_size_t) *
+ HASH_ALG_COUNT))
+ },
+
+ .struct_header = {
+ .signature = TCG_ID_EVENT_SIGNATURE_03,
+ .platform_class = PLATFORM_CLASS_CLIENT,
+ .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
+ .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
+ .spec_errata = TCG_SPEC_ERRATA_TPM2,
+ .uintn_size = (uint8_t)(sizeof(unsigned int) /
+ sizeof(uint32_t)),
+ .number_of_algorithms = HASH_ALG_COUNT
+ }
+};
+
+static const event2_header_t locality_event_header = {
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
+ */
+ .pcr_index = PCR_0,
+
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.eventType = 03h
+ */
+ .event_type = EV_NO_ACTION,
+
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.digests to all
+ * 0x00's for each allocated Hash algorithm
+ */
+ .digests = {
+ .count = HASH_ALG_COUNT
+ }
+};
+
+/* Platform's table with platform specific image IDs, names and PCRs */
+static const image_data_t plat_images_data[] = {
+ { BL2_IMAGE_ID, BL2_STRING, PCR_0 }, /* Reserved for BL2 */
+ { INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+static const measured_boot_data_t plat_measured_boot_data = {
+ plat_images_data,
+ NULL, /* platform_set_nt_fw_info */
+ NULL /* platform_set_tos_fw_info */
+};
+
+/*
+ * Function retuns pointer to platform's measured_boot_data_t structure
+ *
+ * Must be overridden in the platform code
+ */
+#pragma weak plat_get_measured_boot_data
+
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+ return &plat_measured_boot_data;
+}
+
+/*
+ * Add TCG_PCR_EVENT2 event
+ *
+ * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes
+ * @param[in] image_ptr Pointer to image_data_t structure
+ * @return:
+ * 0 = success
+ * < 0 = error code
+ */
+static int add_event2(const uint8_t *hash, const image_data_t *image_ptr)
+{
+ void *ptr = log_ptr;
+ uint32_t name_len;
+ uint32_t size_of_event;
+
+ assert(image_ptr != NULL);
+ assert(image_ptr->name != NULL);
+
+ name_len = (uint32_t)strlen(image_ptr->name) + 1U;
+ size_of_event = name_len + (uint32_t)EVENT2_HDR_SIZE;
+
+ /* Check for space in Event Log buffer */
+ if (((uintptr_t)ptr + size_of_event) > EVENT_LOG_END) {
+ ERROR("%s(): Event Log is short of memory", __func__);
+ return -ENOMEM;
+ }
+
+ /*
+ * As per TCG specifications, firmware components that are measured
+ * into PCR[0] must be logged in the event log using the event type
+ * EV_POST_CODE.
+ */
+ /* TCG_PCR_EVENT2.PCRIndex */
+ ((event2_header_t *)ptr)->pcr_index = image_ptr->pcr;
+
+ /* TCG_PCR_EVENT2.EventType */
+ ((event2_header_t *)ptr)->event_type = EV_POST_CODE;
+
+ /* TCG_PCR_EVENT2.Digests.Count */
+ ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
+ ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
+
+ /* TCG_PCR_EVENT2.Digests[] */
+ ptr = (uint8_t *)ptr + offsetof(tpml_digest_values, digests);
+
+ /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+ ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+ /* TCG_PCR_EVENT2.Digests[].Digest[] */
+ ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest);
+
+ /* Check for space in Event Log buffer */
+ if (((uintptr_t)ptr + TCG_DIGEST_SIZE) > EVENT_LOG_END) {
+ ERROR("%s(): Event Log is short of memory", __func__);
+ return -ENOMEM;
+ }
+
+ if (hash == NULL) {
+ /* Get BL2 hash from DTB */
+ bl2_plat_get_hash(ptr);
+ } else {
+ /* Copy digest */
+ (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
+ }
+
+ /* TCG_PCR_EVENT2.EventSize */
+ ptr = (uint8_t *)ptr + TCG_DIGEST_SIZE;
+ ((event2_data_t *)ptr)->event_size = name_len;
+
+ /* Copy event data to TCG_PCR_EVENT2.Event */
+ (void)memcpy((void *)(((event2_data_t *)ptr)->event),
+ (const void *)image_ptr->name, name_len);
+
+ /* End of event data */
+ log_ptr = (uint8_t *)ptr + offsetof(event2_data_t, event) + name_len;
+
+ return 0;
+}
+
+/*
+ * Init Event Log
+ *
+ * Initialises Event Log by writing Specification ID and
+ * Startup Locality events.
+ */
+void event_log_init(void)
+{
+ const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
+ const uint8_t *start_ptr;
+ void *ptr = event_log;
+
+ /* Get pointer to platform's measured_boot_data_t structure */
+ plat_data_ptr = plat_get_measured_boot_data();
+
+ /*
+ * Add Specification ID Event first
+ *
+ * Copy TCG_EfiSpecIDEventStruct structure header
+ */
+ (void)memcpy(ptr, (const void *)&id_event_header,
+ sizeof(id_event_header));
+ ptr = (uint8_t *)ptr + sizeof(id_event_header);
+
+ /* TCG_EfiSpecIdEventAlgorithmSize structure */
+ ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
+ ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
+ ptr = (uint8_t *)ptr + sizeof(id_event_algorithm_size_t);
+
+ /*
+ * TCG_EfiSpecIDEventStruct.vendorInfoSize
+ * No vendor data
+ */
+ ((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
+ ptr = (uint8_t *)ptr + offsetof(id_event_struct_data_t, vendor_info);
+ if ((uintptr_t)ptr != ((uintptr_t)event_log + ID_EVENT_SIZE)) {
+ panic();
+ }
+
+ start_ptr = (uint8_t *)ptr;
+
+ /*
+ * The Startup Locality event should be placed in the log before
+ * any event which extends PCR[0].
+ *
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+
+ /* Copy Startup Locality Event Header */
+ (void)memcpy(ptr, (const void *)&locality_event_header,
+ sizeof(locality_event_header));
+ ptr = (uint8_t *)ptr + sizeof(locality_event_header);
+
+ /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+ ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+ /* TCG_PCR_EVENT2.Digests[].Digest[] */
+ (void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID);
+ ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE;
+
+ /* TCG_PCR_EVENT2.EventSize */
+ ((event2_data_t *)ptr)->event_size =
+ (uint32_t)sizeof(startup_locality_event_t);
+ ptr = (uint8_t *)ptr + offsetof(event2_data_t, event);
+
+ /* TCG_EfiStartupLocalityEvent.Signature */
+ (void)memcpy(ptr, (const void *)locality_signature,
+ sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
+
+ /*
+ * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
+ * the platform's boot firmware
+ */
+ ((startup_locality_event_t *)ptr)->startup_locality = 0U;
+ ptr = (uint8_t *)ptr + sizeof(startup_locality_event_t);
+ if ((uintptr_t)ptr != ((uintptr_t)start_ptr + LOC_EVENT_SIZE)) {
+ panic();
+ }
+
+ log_ptr = (uint8_t *)ptr;
+
+ /* Add BL2 event */
+ if (add_event2(NULL, plat_data_ptr->images_data) != 0) {
+ panic();
+ }
+}
+
+/*
+ * Calculate and write hash of image, configuration data, etc.
+ * to Event Log.
+ *
+ * @param[in] data_base Address of data
+ * @param[in] data_size Size of data
+ * @param[in] data_id Data ID
+ * @return:
+ * 0 = success
+ * < 0 = error
+ */
+int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id)
+{
+ const image_data_t *data_ptr = plat_data_ptr->images_data;
+ unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
+ int rc;
+
+ /* Check if image_id is supported */
+ while (data_ptr->id != data_id) {
+ if ((data_ptr++)->id == INVALID_ID) {
+ ERROR("%s(): image_id %u not supported\n",
+ __func__, data_id);
+ return -EINVAL;
+ }
+ }
+
+ if (data_id == TOS_FW_CONFIG_ID) {
+ tos_fw_config_base = data_base;
+ } else if (data_id == NT_FW_CONFIG_ID) {
+ nt_fw_config_base = data_base;
+ } else {
+ /* No action */
+ }
+
+ /* Calculate hash */
+ rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
+ (void *)data_base, data_size, hash_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return add_event2(hash_data, data_ptr);
+}
+
+/*
+ * Finalise Event Log
+ *
+ * @param[out] log_addr Pointer to return Event Log address
+ * @param[out] log_size Pointer to return Event Log size
+ * @return:
+ * 0 = success
+ * < 0 = error code
+ */
+int event_log_finalise(uint8_t **log_addr, size_t *log_size)
+{
+ /* Event Log size */
+ size_t num_bytes = (uintptr_t)log_ptr - (uintptr_t)event_log;
+ int rc;
+
+ assert(log_addr != NULL);
+ assert(log_size != NULL);
+
+ if (nt_fw_config_base == 0UL) {
+ ERROR("%s(): %s_FW_CONFIG not loaded\n", __func__, "NT");
+ return -ENOENT;
+ }
+
+ /*
+ * Set Event Log data in NT_FW_CONFIG and
+ * get Event Log address in Non-Secure memory
+ */
+ if (plat_data_ptr->set_nt_fw_info != NULL) {
+
+ /* Event Log address in Non-Secure memory */
+ uintptr_t ns_log_addr;
+
+ rc = plat_data_ptr->set_nt_fw_info(
+ nt_fw_config_base,
+#ifdef SPD_opteed
+ (uintptr_t)event_log,
+#endif
+ num_bytes, &ns_log_addr);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "NT");
+ return rc;
+ }
+
+ /* Copy Event Log to Non-secure memory */
+ (void)memcpy((void *)ns_log_addr, (const void *)event_log,
+ num_bytes);
+
+ /* Ensure that the Event Log is visible in Non-secure memory */
+ flush_dcache_range(ns_log_addr, num_bytes);
+
+ /* Return Event Log address in Non-Secure memory */
+ *log_addr = (uint8_t *)ns_log_addr;
+
+ } else {
+ INFO("%s(): set_%s_fw_info not set\n", __func__, "nt");
+
+ /* Return Event Log address in Secure memory */
+ *log_addr = event_log;
+ }
+
+ if (tos_fw_config_base != 0UL) {
+ if (plat_data_ptr->set_tos_fw_info != NULL) {
+
+ /* Set Event Log data in TOS_FW_CONFIG */
+ rc = plat_data_ptr->set_tos_fw_info(
+ tos_fw_config_base,
+ (uintptr_t)event_log,
+ num_bytes);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "TOS");
+ return rc;
+ }
+ } else {
+ INFO("%s(): set_%s_fw_info not set\n", __func__, "tos");
+ }
+ } else {
+ INFO("%s(): %s_FW_CONFIG not loaded\n", __func__, "TOS");
+ }
+
+ /* Ensure that the Event Log is visible in Secure memory */
+ flush_dcache_range((uintptr_t)event_log, num_bytes);
+
+ /* Return Event Log size */
+ *log_size = num_bytes;
+
+ return 0;
+}
diff --git a/drivers/measured_boot/event_print.c b/drivers/measured_boot/event_print.c
new file mode 100644
index 0000000..ed970b8
--- /dev/null
+++ b/drivers/measured_boot/event_print.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/event_log.h>
+
+#if LOG_LEVEL >= EVENT_LOG_LEVEL
+
+/*
+ * Print TCG_EfiSpecIDEventStruct
+ *
+ * @param[in/out] log_addr Pointer to Event Log
+ * @param[in/out] log_size Pointer to Event Log size
+ */
+static void id_event_print(uint8_t **log_addr, size_t *log_size)
+{
+ unsigned int i;
+ uint8_t info_size, *info_size_ptr;
+ void *ptr = *log_addr;
+ id_event_headers_t *event = (id_event_headers_t *)ptr;
+ id_event_algorithm_size_t *alg_ptr;
+ uint32_t event_size, number_of_algorithms;
+ size_t digest_len;
+#if ENABLE_ASSERTIONS
+ const uint8_t *end_ptr = *log_addr + *log_size;
+ bool valid = true;
+#endif
+
+ assert(*log_size >= sizeof(id_event_headers_t));
+
+ /* The fields of the event log header are defined to be PCRIndex of 0,
+ * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
+ * Event content defined as TCG_EfiSpecIDEventStruct.
+ */
+ LOG_EVENT("TCG_EfiSpecIDEvent:\n");
+ LOG_EVENT(" PCRIndex : %u\n", event->header.pcr_index);
+ assert(event->header.pcr_index == (uint32_t)PCR_0);
+
+ LOG_EVENT(" EventType : %u\n", event->header.event_type);
+ assert(event->header.event_type == EV_NO_ACTION);
+
+ LOG_EVENT(" Digest :");
+ for (i = 0U; i < sizeof(event->header.digest); ++i) {
+ uint8_t val = event->header.digest[i];
+
+ (void)printf(" %02x", val);
+ if ((i & U(0xF)) == 0U) {
+ (void)printf("\n");
+ LOG_EVENT("\t\t :");
+ }
+#if ENABLE_ASSERTIONS
+ if (val != 0U) {
+ valid = false;
+ }
+#endif
+ }
+ if ((i & U(0xF)) != 0U) {
+ (void)printf("\n");
+ }
+
+ assert(valid);
+
+ /* EventSize */
+ event_size = event->header.event_size;
+ LOG_EVENT(" EventSize : %u\n", event_size);
+
+ LOG_EVENT(" Signature : %s\n",
+ event->struct_header.signature);
+ LOG_EVENT(" PlatformClass : %u\n",
+ event->struct_header.platform_class);
+ LOG_EVENT(" SpecVersion : %u.%u.%u\n",
+ event->struct_header.spec_version_major,
+ event->struct_header.spec_version_minor,
+ event->struct_header.spec_errata);
+ LOG_EVENT(" UintnSize : %u\n",
+ event->struct_header.uintn_size);
+
+ /* NumberOfAlgorithms */
+ number_of_algorithms = event->struct_header.number_of_algorithms;
+ LOG_EVENT(" NumberOfAlgorithms : %u\n", number_of_algorithms);
+
+ /* Address of DigestSizes[] */
+ alg_ptr = event->struct_header.digest_size;
+
+ /* Size of DigestSizes[] */
+ digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
+ assert(((uint8_t *)alg_ptr + digest_len) <= end_ptr);
+
+ LOG_EVENT(" DigestSizes :\n");
+ for (i = 0U; i < number_of_algorithms; ++i) {
+ LOG_EVENT(" #%u AlgorithmId : SHA", i);
+ uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+
+ switch (algorithm_id) {
+ case TPM_ALG_SHA256:
+ (void)printf("256\n");
+ break;
+ case TPM_ALG_SHA384:
+ (void)printf("384\n");
+ break;
+ case TPM_ALG_SHA512:
+ (void)printf("512\n");
+ break;
+ default:
+ (void)printf("?\n");
+ ERROR("Algorithm 0x%x not found\n", algorithm_id);
+ assert(false);
+ }
+
+ LOG_EVENT(" DigestSize : %u\n",
+ alg_ptr[i].digest_size);
+ }
+
+ /* Address of VendorInfoSize */
+ info_size_ptr = (uint8_t *)alg_ptr + digest_len;
+ assert(info_size_ptr <= end_ptr);
+
+ info_size = *info_size_ptr++;
+ LOG_EVENT(" VendorInfoSize : %u\n", info_size);
+
+ /* Check VendorInfo end address */
+ assert((info_size_ptr + info_size) <= end_ptr);
+
+ /* Check EventSize */
+ assert(event_size == (sizeof(id_event_struct_t) +
+ digest_len + info_size));
+ if (info_size != 0U) {
+ LOG_EVENT(" VendorInfo :");
+ for (i = 0U; i < info_size; ++i) {
+ (void)printf(" %02x", *info_size_ptr++);
+ }
+ (void)printf("\n");
+ }
+
+ *log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
+ *log_addr = info_size_ptr;
+}
+
+/*
+ * Print TCG_PCR_EVENT2
+ *
+ * @param[in/out] log_addr Pointer to Event Log
+ * @param[in/out] log_size Pointer to Event Log size
+ */
+static void event2_print(uint8_t **log_addr, size_t *log_size)
+{
+ uint32_t event_size, count;
+ size_t sha_size, digests_size = 0U;
+ void *ptr = *log_addr;
+#if ENABLE_ASSERTIONS
+ const uint8_t *end_ptr = *log_addr + *log_size;
+#endif
+
+ assert(*log_size >= sizeof(event2_header_t));
+
+ LOG_EVENT("PCR_Event2:\n");
+ LOG_EVENT(" PCRIndex : %u\n",
+ ((event2_header_t *)ptr)->pcr_index);
+ LOG_EVENT(" EventType : %u\n",
+ ((event2_header_t *)ptr)->event_type);
+
+ count = ((event2_header_t *)ptr)->digests.count;
+ LOG_EVENT(" Digests Count : %u\n", count);
+
+ /* Address of TCG_PCR_EVENT2.Digests[] */
+ ptr = (uint8_t *)ptr + sizeof(event2_header_t);
+ assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U));
+
+ for (unsigned int i = 0U; i < count; ++i) {
+ /* Check AlgorithmId address */
+ assert(((uint8_t *)ptr + offsetof(tpmt_ha, digest)) <= end_ptr);
+
+ LOG_EVENT(" #%u AlgorithmId : SHA", i);
+ switch (((tpmt_ha *)ptr)->algorithm_id) {
+ case TPM_ALG_SHA256:
+ sha_size = SHA256_DIGEST_SIZE;
+ (void)printf("256\n");
+ break;
+ case TPM_ALG_SHA384:
+ sha_size = SHA384_DIGEST_SIZE;
+ (void)printf("384\n");
+ break;
+ case TPM_ALG_SHA512:
+ sha_size = SHA512_DIGEST_SIZE;
+ (void)printf("512\n");
+ break;
+ default:
+ (void)printf("?\n");
+ ERROR("Algorithm 0x%x not found\n",
+ ((tpmt_ha *)ptr)->algorithm_id);
+ panic();
+ }
+
+ /* End of Digest[] */
+ ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest);
+ assert(((uint8_t *)ptr + sha_size) <= end_ptr);
+
+ /* Total size of all digests */
+ digests_size += sha_size;
+
+ LOG_EVENT(" Digest :");
+ for (unsigned int j = 0U; j < sha_size; ++j) {
+ (void)printf(" %02x", *(uint8_t *)ptr++);
+ if ((j & U(0xF)) == U(0xF)) {
+ (void)printf("\n");
+ if (j < (sha_size - 1U)) {
+ LOG_EVENT("\t\t :");
+ }
+ }
+ }
+ }
+
+ /* TCG_PCR_EVENT2.EventSize */
+ assert(((uint8_t *)ptr + offsetof(event2_data_t, event)) <= end_ptr);
+
+ event_size = ((event2_data_t *)ptr)->event_size;
+ LOG_EVENT(" EventSize : %u\n", event_size);
+
+ /* Address of TCG_PCR_EVENT2.Event[EventSize] */
+ ptr = (uint8_t *)ptr + offsetof(event2_data_t, event);
+
+ /* End of TCG_PCR_EVENT2.Event[EventSize] */
+ assert(((uint8_t *)ptr + event_size) <= end_ptr);
+
+ if ((event_size == sizeof(startup_locality_event_t)) &&
+ (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
+ LOG_EVENT(" Signature : %s\n",
+ ((startup_locality_event_t *)ptr)->signature);
+ LOG_EVENT(" StartupLocality : %u\n",
+ ((startup_locality_event_t *)ptr)->startup_locality);
+ } else {
+ LOG_EVENT(" Event : %s\n", (uint8_t *)ptr);
+ }
+
+ *log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
+ *log_addr = (uint8_t *)ptr + event_size;
+}
+#endif /* LOG_LEVEL >= EVENT_LOG_LEVEL */
+
+/*
+ * Print Event Log
+ *
+ * @param[in] log_addr Pointer to Event Log
+ * @param[in] log_size Event Log size
+ */
+void dump_event_log(uint8_t *log_addr, size_t log_size)
+{
+#if LOG_LEVEL >= EVENT_LOG_LEVEL
+ assert(log_addr != NULL);
+
+ /* Print TCG_EfiSpecIDEvent */
+ id_event_print(&log_addr, &log_size);
+
+ while (log_size != 0U) {
+ event2_print(&log_addr, &log_size);
+ }
+#endif
+}
diff --git a/drivers/measured_boot/measured_boot.c b/drivers/measured_boot/measured_boot.c
new file mode 100644
index 0000000..37fddfb
--- /dev/null
+++ b/drivers/measured_boot/measured_boot.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/measured_boot.h>
+
+/*
+ * Init Measured Boot driver
+ *
+ * Initialises Event Log.
+ */
+void measured_boot_init(void)
+{
+ event_log_init();
+}
+
+/*
+ * Finish Measured Boot driver
+ *
+ * Finalises Event Log and dumps the records to the debug console.
+ */
+void measured_boot_finish(void)
+{
+ uint8_t *log_addr;
+ size_t log_size;
+ int rc;
+
+ rc = event_log_finalise(&log_addr, &log_size);
+ if (rc != 0) {
+ panic();
+ }
+
+ dump_event_log(log_addr, log_size);
+}
diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/measured_boot.mk
new file mode 100644
index 0000000..fc005d5
--- /dev/null
+++ b/drivers/measured_boot/measured_boot.mk
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TPM hash algorithm
+TPM_HASH_ALG := sha256
+
+ifeq (${TPM_HASH_ALG}, sha512)
+ MBEDTLS_MD_ID := MBEDTLS_MD_SHA512
+ TPM_ALG_ID := TPM_ALG_SHA512
+ TCG_DIGEST_SIZE := 64U
+else ifeq (${TPM_HASH_ALG}, sha384)
+ MBEDTLS_MD_ID := MBEDTLS_MD_SHA384
+ TPM_ALG_ID := TPM_ALG_SHA384
+ TCG_DIGEST_SIZE := 48U
+else
+ MBEDTLS_MD_ID := MBEDTLS_MD_SHA256
+ TPM_ALG_ID := TPM_ALG_SHA256
+ TCG_DIGEST_SIZE := 32U
+endif
+
+# Event Log length in bytes
+EVENT_LOG_SIZE := 1024
+
+# Set definitions for mbed TLS library and Measured Boot driver
+$(eval $(call add_define,MBEDTLS_MD_ID))
+$(eval $(call add_define,TPM_ALG_ID))
+$(eval $(call add_define,TCG_DIGEST_SIZE))
+$(eval $(call add_define,EVENT_LOG_SIZE))
+
+ifeq (${HASH_ALG}, sha256)
+ifneq (${TPM_HASH_ALG}, sha256)
+$(eval $(call add_define,MBEDTLS_SHA512_C))
+endif
+endif
+
+MEASURED_BOOT_SRC_DIR := drivers/measured_boot/
+
+MEASURED_BOOT_SOURCES := ${MEASURED_BOOT_SRC_DIR}measured_boot.c \
+ ${MEASURED_BOOT_SRC_DIR}event_log.c \
+ ${MEASURED_BOOT_SRC_DIR}event_print.c
+
+BL2_SOURCES += ${MEASURED_BOOT_SOURCES}
diff --git a/fdts/cot_descriptors.dtsi b/fdts/cot_descriptors.dtsi
index 753d56a..9308e17 100644
--- a/fdts/cot_descriptors.dtsi
+++ b/fdts/cot_descriptors.dtsi
@@ -146,8 +146,8 @@
};
#if defined(SPD_spmd)
- sp_content_cert: sp_content_cert {
- image-id = <SP_CONTENT_CERT_ID>;
+ sip_sp_content_cert: sip_sp_content_cert {
+ image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
antirollback-counter = <&trusted_nv_counter>;
@@ -251,50 +251,50 @@
#if defined(SPD_spmd)
sp_pkg1 {
- image-id = <SP_CONTENT_CERT_ID + 1>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG1_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg1_hash>;
};
sp_pkg2 {
- image-id = <SP_CONTENT_CERT_ID + 2>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG2_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg2_hash>;
};
sp_pkg3 {
- image-id = <SP_CONTENT_CERT_ID + 3>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG3_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg3_hash>;
};
sp_pkg4 {
- image-id = <SP_CONTENT_CERT_ID + 4>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG4_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg4_hash>;
};
sp_pkg5 {
- image-id = <SP_CONTENT_CERT_ID + 5>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG5_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg5_hash>;
};
sp_pkg6 {
- image-id = <SP_CONTENT_CERT_ID + 6>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG6_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg6_hash>;
};
sp_pkg7 {
- image-id = <SP_CONTENT_CERT_ID + 7>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG7_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg7_hash>;
};
sp_pkg8 {
- image-id = <SP_CONTENT_CERT_ID + 8>;
- parent = <&sp_content_cert>;
+ image-id = <SP_PKG8_ID>;
+ parent = <&sip_sp_content_cert>;
hash = <&sp_pkg8_hash>;
};
#endif
diff --git a/fdts/n1sdp-multi-chip.dts b/fdts/n1sdp-multi-chip.dts
new file mode 100644
index 0000000..b58d9d8
--- /dev/null
+++ b/fdts/n1sdp-multi-chip.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+#include "n1sdp-single-chip.dts"
+
+/ {
+ cpus {
+ cpu4@100000000 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x1 0x0>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <1>;
+ };
+ cpu5@100000100 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x1 0x00000100>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <1>;
+ };
+ cpu6@100010000 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x1 0x00010000>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <1>;
+ };
+ cpu7@100010100 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x1 0x00010100>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <1>;
+ };
+ };
+
+ /* Remote N1SDP board address is mapped at offset 4TB.
+ * First DRAM Bank of remote N1SDP board is mapped at 4TB + 2GB.
+ */
+ memory@40080000000 {
+ device_type = "memory";
+ reg = <0x00000400 0x80000000 0x0 0x80000000>,
+ <0x00000480 0x80000000 0x3 0x80000000>;
+ numa-node-id = <1>;
+ };
+
+ distance-map {
+ compatible = "numa-distance-map-v1";
+ distance-matrix = <0 0 10>,
+ <0 1 20>,
+ <1 1 10>;
+ };
+};
+
+&gic {
+ #redistributor-regions = <2>;
+ reg = <0x0 0x30000000 0 0x10000>, /* GICD */
+ <0x0 0x300c0000 0 0x80000>, /* GICR */
+ <0x400 0x300c0000 0 0x80000>; /* GICR */
+};
diff --git a/fdts/n1sdp-single-chip.dts b/fdts/n1sdp-single-chip.dts
new file mode 100644
index 0000000..bd48273
--- /dev/null
+++ b/fdts/n1sdp-single-chip.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+/dts-v1/;
+
+#include "n1sdp.dtsi"
+
+/ {
+ model = "Arm Neoverse N1 System Development Platform";
+ compatible = "arm,neoverse-n1-sdp", "arm,neoverse-n1-soc";
+
+ aliases {
+ serial0 = &soc_uart0;
+ };
+
+ chosen {
+ stdout-path = "soc_uart0:115200n8";
+ };
+
+ /* This configuration assumes that standard setup with two DIMM modules.
+ * In the first 2GB of DRAM bank the top 16MB are reserved by firmware as secure memory.
+ * This configuration assumes 16GB of total DRAM being populated.
+ */
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000 0x0 0x7f000000>,
+ <0x00000080 0x80000000 0x3 0x80000000>;
+ numa-node-id = <0>;
+ };
+
+ soc_refclk60mhz: refclk60mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <60000000>;
+ clock-output-names = "iofpga_clk";
+ };
+
+ soc_hdlcdclk: hdlcdclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <23750000>;
+ clock-output-names = "hdlcdclk";
+ };
+
+ hdlcd: hdlcd@1c050000 {
+ compatible = "arm,hdlcd";
+ reg = <0 0x1c050000 0 0x1000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&soc_hdlcdclk>;
+ clock-names = "pxlclk";
+
+ port {
+ hdlcd0_output: endpoint {
+ remote-endpoint = <&tda998x_0_input>;
+ };
+ };
+ };
+
+ i2c@1c0f0000 {
+ compatible = "arm,versatile-i2c";
+ reg = <0x0 0x1c0f0000 0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <400000>;
+ i2c-sda-hold-time-ns = <500>;
+ clocks = <&soc_refclk60mhz>;
+
+ hdmi-transmitter@70 {
+ compatible = "nxp,tda998x";
+ reg = <0x70>;
+ port {
+ tda998x_0_input: endpoint {
+ remote-endpoint = <&hdlcd0_output>;
+ };
+ };
+ };
+ };
+};
+
+&pcie_ctlr {
+ status = "okay";
+};
+
+&ccix_pcie_ctlr {
+ status = "okay";
+};
+
+&soc_uart0 {
+ status = "okay";
+};
diff --git a/fdts/n1sdp.dtsi b/fdts/n1sdp.dtsi
new file mode 100644
index 0000000..88f8734
--- /dev/null
+++ b/fdts/n1sdp.dtsi
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0@0 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x0 0x0>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <0>;
+ };
+ cpu1@100 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x0 0x100>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <0>;
+ };
+ cpu2@10000 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x0 0x10000>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <0>;
+ };
+ cpu3@10100 {
+ compatible = "arm,neoverse-n1";
+ reg = <0x0 0x10100>;
+ device_type = "cpu";
+ enable-method = "psci";
+ numa-node-id = <0>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ spe-pmu {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ soc_refclk100mhz: refclk100mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "apb_pclk";
+ };
+
+ soc_uartclk: uartclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ clock-output-names = "uartclk";
+ };
+
+ soc {
+ compatible = "arm,neoverse-n1-soc", "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gic: interrupt-controller@30000000 {
+ compatible = "arm,gic-v3";
+ #address-cells = <2>;
+ #interrupt-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ interrupt-controller;
+ reg = <0x0 0x30000000 0 0x10000>, /* GICD */
+ <0x0 0x300c0000 0 0x80000>; /* GICR */
+
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+ its1: its@30040000 {
+ compatible = "arm,gic-v3-its";
+ msi-controller;
+ #msi-cells = <1>;
+ reg = <0x0 0x30040000 0x0 0x20000>;
+ };
+
+ its2: its@30060000 {
+ compatible = "arm,gic-v3-its";
+ msi-controller;
+ #msi-cells = <1>;
+ reg = <0x0 0x30060000 0x0 0x20000>;
+ };
+
+ its_ccix: its@30080000 {
+ compatible = "arm,gic-v3-its";
+ msi-controller;
+ #msi-cells = <1>;
+ reg = <0x0 0x30080000 0x0 0x20000>;
+ };
+
+ its_pcie: its@300a0000 {
+ compatible = "arm,gic-v3-its";
+ msi-controller;
+ #msi-cells = <1>;
+ reg = <0x0 0x300a0000 0x0 0x20000>;
+ };
+ };
+
+ smmu_ccix: iommu@4f000000 {
+ compatible = "arm,smmu-v3";
+ reg = <0 0x4f000000 0 0x40000>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "cmdq-sync", "gerror";
+ msi-parent = <&its1 0>;
+ #iommu-cells = <1>;
+ dma-coherent;
+ };
+
+ smmu_pcie: iommu@4f400000 {
+ compatible = "arm,smmu-v3";
+ reg = <0 0x4f400000 0 0x40000>;
+ interrupts = <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 237 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "cmdq-sync", "gerror";
+ msi-parent = <&its2 0>;
+ #iommu-cells = <1>;
+ dma-coherent;
+ };
+
+ pcie_ctlr: pcie@70000000 {
+ compatible = "arm,n1sdp-pcie";
+ device_type = "pci";
+ reg = <0 0x70000000 0 0x1200000>;
+ bus-range = <0 17>;
+ linux,pci-domain = <0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ dma-coherent;
+ ranges = <0x01000000 0x00 0x00000000 0x00 0x75200000 0x00 0x00010000>,
+ <0x02000000 0x00 0x71200000 0x00 0x71200000 0x00 0x04000000>,
+ <0x42000000 0x09 0x00000000 0x09 0x00000000 0x20 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>;
+ msi-map = <0 &its_pcie 0 0x10000>;
+ iommu-map = <0 &smmu_pcie 0 0x10000>;
+ status = "disabled";
+ };
+
+ ccix_pcie_ctlr: pcie@68000000 {
+ compatible = "arm,n1sdp-pcie";
+ device_type = "pci";
+ reg = <0 0x68000000 0 0x1200000>;
+ bus-range = <0 17>;
+ linux,pci-domain = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ dma-coherent;
+ ranges = <0x01000000 0x00 0x00000000 0x00 0x6d200000 0x00 0x00010000>,
+ <0x02000000 0x00 0x69200000 0x00 0x69200000 0x00 0x04000000>,
+ <0x42000000 0x29 0x00000000 0x29 0x00000000 0x20 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>;
+ msi-map = <0 &its_ccix 0 0x10000>;
+ iommu-map = <0 &smmu_ccix 0 0x10000>;
+ status = "disabled";
+ };
+
+ soc_uart0: serial@2a400000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0 0x2a400000 0x0 0x1000>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "disabled";
+ };
+ };
+};
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index e057891..b29b135 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -10,7 +10,7 @@
#include <export/common/tbbr/tbbr_img_def_exp.h>
#if defined(SPD_spmd)
-#define SP_CONTENT_CERT_ID MAX_IMAGE_IDS
+#define SIP_SP_CONTENT_CERT_ID MAX_IMAGE_IDS
#define SP_PKG1_ID (MAX_IMAGE_IDS + 1)
#define SP_PKG2_ID (MAX_IMAGE_IDS + 2)
#define SP_PKG3_ID (MAX_IMAGE_IDS + 3)
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 97b75b0..18d5b73 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -223,10 +223,10 @@
#define TYPER_PPI_NUM_MASK U(0x1f)
/* GICR_IIDR bit definitions */
-#define IIDR_PRODUCT_ID_MASK 0xff000000
-#define IIDR_VARIANT_MASK 0x000f0000
-#define IIDR_REVISION_MASK 0x0000f000
-#define IIDR_IMPLEMENTER_MASK 0x00000fff
+#define IIDR_PRODUCT_ID_MASK U(0xff000000)
+#define IIDR_VARIANT_MASK U(0x000f0000)
+#define IIDR_REVISION_MASK U(0x0000f000)
+#define IIDR_IMPLEMENTER_MASK U(0x00000fff)
#define IIDR_MODEL_MASK (IIDR_PRODUCT_ID_MASK | \
IIDR_IMPLEMENTER_MASK)
diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h
index e0e6760..26c444d 100644
--- a/include/drivers/arm/tzc_dmc620.h
+++ b/include/drivers/arm/tzc_dmc620.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,16 +32,16 @@
/* Address offsets of access address next registers */
#define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no) \
(DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE + \
- (region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+ ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
#define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no) \
(DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE + \
- (region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+ ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
#define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no) \
(DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE + \
- (region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+ ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
#define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no) \
(DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE + \
- (region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+ ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
/* Number of TZC address regions in DMC-620 */
#define DMC620_ACC_ADDR_COUNT U(8)
diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h
index 01d144d..504e539 100644
--- a/include/drivers/auth/auth_mod.h
+++ b/include/drivers/auth/auth_mod.h
@@ -51,11 +51,11 @@
extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
#if defined(SPD_spmd)
-#define DEFINE_SP_PKG(n) \
+#define DEFINE_SIP_SP_PKG(n) \
static const auth_img_desc_t sp_pkg##n = { \
- .img_id = SP_CONTENT_CERT_ID + (n), \
+ .img_id = SP_PKG##n##_ID, \
.img_type = IMG_RAW, \
- .parent = &sp_content_cert, \
+ .parent = &sip_sp_content_cert, \
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { \
[0] = { \
.type = AUTH_METHOD_HASH, \
diff --git a/include/drivers/measured_boot/event_log.h b/include/drivers/measured_boot/event_log.h
new file mode 100644
index 0000000..10dfbb3
--- /dev/null
+++ b/include/drivers/measured_boot/event_log.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_H
+#define EVENT_LOG_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/tcg.h>
+
+/*
+ * Set Event Log debug level to one of:
+ *
+ * LOG_LEVEL_ERROR
+ * LOG_LEVEL_INFO
+ * LOG_LEVEL_WARNING
+ * LOG_LEVEL_VERBOSE
+ */
+#define EVENT_LOG_LEVEL LOG_LEVEL_INFO
+
+#if EVENT_LOG_LEVEL == LOG_LEVEL_ERROR
+#define LOG_EVENT ERROR
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
+#define LOG_EVENT NOTICE
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
+#define LOG_EVENT WARN
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
+#define LOG_EVENT INFO
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
+#define LOG_EVENT VERBOSE
+#else
+#error "Not supported EVENT_LOG_LEVEL"
+#endif
+
+/* Number of hashing algorithms supported */
+#define HASH_ALG_COUNT 1U
+
+#define INVALID_ID MAX_NUMBER_IDS
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+#define BL2_STRING "BL_2"
+#define BL31_STRING "BL_31"
+#define BL32_STRING "BL_32"
+#define BL32_EXTRA1_IMAGE_STRING "BL32_EXTRA1_IMAGE"
+#define BL32_EXTRA2_IMAGE_STRING "BL32_EXTRA2_IMAGE"
+#define BL33_STRING "BL_33"
+#define GPT_IMAGE_STRING "GPT"
+#define HW_CONFIG_STRING "HW_CONFIG"
+#define NT_FW_CONFIG_STRING "NT_FW_CONFIG"
+#define SCP_BL2_IMAGE_STRING "SCP_BL2_IMAGE"
+#define SOC_FW_CONFIG_STRING "SOC_FW_CONFIG"
+#define STM32_IMAGE_STRING "STM32"
+#define TOS_FW_CONFIG_STRING "TOS_FW_CONFIG"
+
+typedef struct {
+ unsigned int id;
+ const char *name;
+ unsigned int pcr;
+} image_data_t;
+
+typedef struct {
+ const image_data_t *images_data;
+ int (*set_nt_fw_info)(uintptr_t config_base,
+#ifdef SPD_opteed
+ uintptr_t log_addr,
+#endif
+ size_t log_size, uintptr_t *ns_log_addr);
+ int (*set_tos_fw_info)(uintptr_t config_base, uintptr_t log_addr,
+ size_t log_size);
+} measured_boot_data_t;
+
+#define ID_EVENT_SIZE (sizeof(id_event_headers_t) + \
+ (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
+ sizeof(id_event_struct_data_t))
+
+#define LOC_EVENT_SIZE (sizeof(event2_header_t) + \
+ sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+ sizeof(event2_data_t) + \
+ sizeof(startup_locality_event_t))
+
+#define LOG_MIN_SIZE (ID_EVENT_SIZE + LOC_EVENT_SIZE)
+
+#define EVENT2_HDR_SIZE (sizeof(event2_header_t) + \
+ sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+ sizeof(event2_data_t))
+
+/* Functions' declarations */
+void event_log_init(void);
+int event_log_finalise(uint8_t **log_addr, size_t *log_size);
+void dump_event_log(uint8_t *log_addr, size_t log_size);
+const measured_boot_data_t *plat_get_measured_boot_data(void);
+int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id);
+#endif /* EVENT_LOG_H */
diff --git a/include/drivers/measured_boot/measured_boot.h b/include/drivers/measured_boot/measured_boot.h
new file mode 100644
index 0000000..f8769ab
--- /dev/null
+++ b/include/drivers/measured_boot/measured_boot.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEASURED_BOOT_H
+#define MEASURED_BOOT_H
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log.h>
+
+/* Platform specific table of image IDs, names and PCRs */
+extern const image_data_t images_data[];
+
+/* Functions' declarations */
+void measured_boot_init(void);
+void measured_boot_finish(void);
+
+#endif /* MEASURED_BOOT_H */
diff --git a/include/drivers/measured_boot/tcg.h b/include/drivers/measured_boot/tcg.h
new file mode 100644
index 0000000..ab27a08
--- /dev/null
+++ b/include/drivers/measured_boot/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE "StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_SPEC_ERRATA_TPM2 2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT U(0x00000000)
+#define EV_POST_CODE U(0x00000001)
+#define EV_UNUSED U(0x00000002)
+#define EV_NO_ACTION U(0x00000003)
+#define EV_SEPARATOR U(0x00000004)
+#define EV_ACTION U(0x00000005)
+#define EV_EVENT_TAG U(0x00000006)
+#define EV_S_CRTM_CONTENTS U(0x00000007)
+#define EV_S_CRTM_VERSION U(0x00000008)
+#define EV_CPU_MICROCODE U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS U(0x0000000A)
+#define EV_TABLE_OF_DEVICES U(0x0000000B)
+#define EV_COMPACT_HASH U(0x0000000C)
+#define EV_IPL U(0x0000000D)
+#define EV_IPL_PARTITION_DATA U(0x0000000E)
+#define EV_NONHOST_CODE U(0x0000000F)
+#define EV_NONHOST_CONFIG U(0x00000010)
+#define EV_NONHOST_INFO U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS U(0x00000012)
+#define EV_EFI_EVENT_BASE U(0x80000000)
+#define EV_EFI_VARIABLE_DRIVER_CONFIG U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT U(0x80000002)
+#define EV_EFI_BOOT_SERVICES_APPLICATION U(0x80000003)
+#define EV_EFI_BOOT_SERVICES_DRIVER U(0x80000004)
+#define EV_EFI_RUNTIME_SERVICES_DRIVER U(0x80000005)
+#define EV_EFI_GPT_EVENT U(0x80000006)
+#define EV_EFI_ACTION U(0x80000007)
+#define EV_EFI_PLATFORM_FIRMWARE_BLOB U(0x80000008)
+#define EV_EFI_HANDOFF_TABLES U(0x80000009)
+#define EV_EFI_HCRTM_EVENT U(0x80000010)
+#define EV_EFI_VARIABLE_AUTHORITY U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256 0x000B
+#define TPM_ALG_SHA384 0x000C
+#define TPM_ALG_SHA512 0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT 0
+#define PLATFORM_CLASS_SERVER 1
+
+/* SHA digest sizes in bytes */
+#define SHA1_DIGEST_SIZE 20
+#define SHA256_DIGEST_SIZE 32
+#define SHA384_DIGEST_SIZE 48
+#define SHA512_DIGEST_SIZE 64
+
+enum {
+ /*
+ * SRTM, BIOS, Host Platform Extensions, Embedded
+ * Option ROMs and PI Drivers
+ */
+ PCR_0 = 0,
+ /* Host Platform Configuration */
+ PCR_1,
+ /* UEFI driver and application Code */
+ PCR_2,
+ /* UEFI driver and application Configuration and Data */
+ PCR_3,
+ /* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+ PCR_4,
+ /*
+ * Boot Manager Code Configuration and Data (for use
+ * by the Boot Manager Code) and GPT/Partition Table
+ */
+ PCR_5,
+ /* Host Platform Manufacturer Specific */
+ PCR_6,
+ /* Secure Boot Policy */
+ PCR_7,
+ /* 8-15: Defined for use by the Static OS */
+ PCR_8,
+ /* Debug */
+ PCR_16 = 16
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+ /* PCRIndex:
+ * The PCR Index to which this event is extended
+ */
+ uint32_t pcr_index;
+
+ /* EventType:
+ * SHALL be an EV_NO_ACTION event
+ */
+ uint32_t event_type;
+
+ /* SHALL be 20 Bytes of 0x00 */
+ uint8_t digest[SHA1_DIGEST_SIZE];
+
+ /* The size of the event */
+ uint32_t event_size;
+
+ /* SHALL be a TCG_EfiSpecIdEvent */
+ uint8_t event[]; /* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+ /* Algorithm ID (hashAlg) of the Hash used by BIOS */
+ uint16_t algorithm_id;
+
+ /* The size of the digest produced by the implemented Hash algorithm */
+ uint16_t digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+ /*
+ * The NUL-terminated ASCII string "Spec ID Event03".
+ * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+ * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+ */
+ uint8_t signature[16];
+
+ /*
+ * The value for the Platform Class.
+ * The enumeration is defined in the TCG ACPI Specification Client
+ * Common Header.
+ */
+ uint32_t platform_class;
+
+ /*
+ * The PC Client Platform Profile Specification minor version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+ */
+ uint8_t spec_version_minor;
+
+ /*
+ * The PC Client Platform Profile Specification major version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+ */
+ uint8_t spec_version_major;
+
+ /*
+ * The PC Client Platform Profile Specification errata version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+ */
+ uint8_t spec_errata;
+
+ /*
+ * Specifies the size of the UINTN fields used in various data
+ * structures used in this specification.
+ * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+ */
+ uint8_t uintn_size;
+
+ /*
+ * The number of Hash algorithms in the digestSizes field.
+ * This field MUST be set to a value of 0x01 or greater.
+ */
+ uint32_t number_of_algorithms;
+
+ /*
+ * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+ * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+ * structure, the first of which is a Hash algorithmID and the second
+ * is the size of the respective digest.
+ */
+ id_event_algorithm_size_t digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+ /*
+ * Size in bytes of the VendorInfo field.
+ * Maximum value MUST be FFh bytes.
+ */
+ uint8_t vendor_info_size;
+
+ /*
+ * Provided for use by Platform Firmware implementer. The value might
+ * be used, for example, to provide more detailed information about the
+ * specific BIOS such as BIOS revision numbers, etc. The values within
+ * this field are not standardized and are implementer-specific.
+ * Platform-specific or -unique information MUST NOT be provided in
+ * this field.
+ *
+ */
+ uint8_t vendor_info[]; /* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+ id_event_struct_header_t struct_header;
+ id_event_struct_data_t struct_data;
+} id_event_struct_t;
+
+typedef struct {
+ tcg_pcr_event_t header;
+ id_event_struct_header_t struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+ /* Selector of the hash contained in the digest that implies
+ * the size of the digest
+ */
+ uint16_t algorithm_id; /* AlgorithmId */
+
+ /* Digest, depends on AlgorithmId */
+ uint8_t digest[]; /* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+ /* The number of digests in the list */
+ uint32_t count; /* Count */
+
+ /* The list of tagged digests, as sent to the TPM as part of a
+ * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+ */
+ tpmt_ha digests[]; /* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+ /* The PCR Index to which this event was extended */
+ uint32_t pcr_index; /* PCRIndex */
+
+ /* Type of event */
+ uint32_t event_type; /* EventType */
+
+ /* Digests:
+ * A counted list of tagged digests, which contain the digest of
+ * the event data (or external data) for all active PCR banks
+ */
+ tpml_digest_values digests; /* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+ /* The size of the event data */
+ uint32_t event_size; /* EventSize */
+
+ /* The data of the event */
+ uint8_t event[]; /* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+ /*
+ * The NUL-terminated ASCII string "StartupLocality" SHALL be
+ * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+ * 0x61 0x6C 0x69 0x74 0x79 0x00}
+ */
+ uint8_t signature[16];
+
+ /* The Locality Indicator which sent the TPM2_Startup command */
+ uint8_t startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
index 18bdb57..67e66b2 100644
--- a/include/dt-bindings/clock/stm32mp1-clks.h
+++ b/include/dt-bindings/clock/stm32mp1-clks.h
@@ -248,4 +248,31 @@
#define STM32MP1_LAST_CLK 232
+/* SCMI clock identifiers */
+#define CK_SCMI0_HSE 0
+#define CK_SCMI0_HSI 1
+#define CK_SCMI0_CSI 2
+#define CK_SCMI0_LSE 3
+#define CK_SCMI0_LSI 4
+#define CK_SCMI0_PLL2_Q 5
+#define CK_SCMI0_PLL2_R 6
+#define CK_SCMI0_MPU 7
+#define CK_SCMI0_AXI 8
+#define CK_SCMI0_BSEC 9
+#define CK_SCMI0_CRYP1 10
+#define CK_SCMI0_GPIOZ 11
+#define CK_SCMI0_HASH1 12
+#define CK_SCMI0_I2C4 13
+#define CK_SCMI0_I2C6 14
+#define CK_SCMI0_IWDG1 15
+#define CK_SCMI0_RNG1 16
+#define CK_SCMI0_RTC 17
+#define CK_SCMI0_RTCAPB 18
+#define CK_SCMI0_SPI6 19
+#define CK_SCMI0_USART1 20
+
+#define CK_SCMI1_PLL3_Q 0
+#define CK_SCMI1_PLL3_R 1
+#define CK_SCMI1_MCU 2
+
#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
index f0c3aae..bc71924 100644
--- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -105,4 +105,17 @@
#define GPIOJ_R 19785
#define GPIOK_R 19786
+/* SCMI reset domain identifiers */
+#define RST_SCMI0_SPI6 0
+#define RST_SCMI0_I2C4 1
+#define RST_SCMI0_I2C6 2
+#define RST_SCMI0_USART1 3
+#define RST_SCMI0_STGEN 4
+#define RST_SCMI0_GPIOZ 5
+#define RST_SCMI0_CRYP1 6
+#define RST_SCMI0_HASH1 7
+#define RST_SCMI0_RNG1 8
+#define RST_SCMI0_MDMA 9
+#define RST_SCMI0_MCU 10
+
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/include/lib/cpus/aarch64/neoverse_n1.h b/include/lib/cpus/aarch64/neoverse_n1.h
index 155a90e..b50befa 100644
--- a/include/lib/cpus/aarch64/neoverse_n1.h
+++ b/include/lib/cpus/aarch64/neoverse_n1.h
@@ -35,7 +35,6 @@
#define NEOVERSE_N1_WS_THR_L2_MASK (ULL(3) << 24)
#define NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT (ULL(1) << 51)
-#define NEOVERSE_N1_CPUECTLR_EL1_BIT_53 (ULL(1) << 53)
#define NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT (ULL(1) << 0)
/*******************************************************************************
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
index 9816d6f..6f8da0d 100644
--- a/include/lib/fconf/fconf_dyn_cfg_getter.h
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -14,14 +14,15 @@
struct dyn_cfg_dtb_info_t {
uintptr_t config_addr;
- size_t config_max_size;
+ uint32_t config_max_size;
unsigned int config_id;
};
struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id);
int fconf_populate_dtb_registry(uintptr_t config);
-/* Set fw_config information in global DTB array */
-void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size);
+/* Set config information in global DTB array */
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+ unsigned int config_id);
#endif /* FCONF_DYN_CFG_GETTER_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
index db98b68..6066af6 100644
--- a/include/lib/fconf/fconf_tbbr_getter.h
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -23,6 +23,9 @@
uint32_t disable_auth;
void *mbedtls_heap_addr;
size_t mbedtls_heap_size;
+#if MEASURED_BOOT
+ uint8_t bl2_hash_data[TCG_DIGEST_SIZE];
+#endif
};
extern struct tbbr_dyn_config_t tbbr_dyn_config;
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 680d354..293e7ce 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -81,7 +81,7 @@
ARM_SCP_TZC_DRAM1_SIZE)
#define ARM_SCP_TZC_DRAM1_SIZE PLAT_ARM_SCP_TZC_DRAM1_SIZE
#define ARM_SCP_TZC_DRAM1_END (ARM_SCP_TZC_DRAM1_BASE + \
- ARM_SCP_TZC_DRAM1_SIZE - 1)
+ ARM_SCP_TZC_DRAM1_SIZE - 1U)
/*
* Define a 2MB region within the TZC secured DRAM for use by EL3 runtime
@@ -92,7 +92,7 @@
#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2 MB */
#define ARM_EL3_TZC_DRAM1_END (ARM_EL3_TZC_DRAM1_BASE + \
- ARM_EL3_TZC_DRAM1_SIZE - 1)
+ ARM_EL3_TZC_DRAM1_SIZE - 1U)
#define ARM_AP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \
ARM_DRAM1_SIZE - \
@@ -101,7 +101,7 @@
(ARM_SCP_TZC_DRAM1_SIZE + \
ARM_EL3_TZC_DRAM1_SIZE))
#define ARM_AP_TZC_DRAM1_END (ARM_AP_TZC_DRAM1_BASE + \
- ARM_AP_TZC_DRAM1_SIZE - 1)
+ ARM_AP_TZC_DRAM1_SIZE - 1U)
/* Define the Access permissions for Secure peripherals to NS_DRAM */
#if ARM_CRYPTOCELL_INTEG
@@ -148,17 +148,17 @@
#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
ARM_TZC_DRAM1_SIZE)
#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \
- ARM_NS_DRAM1_SIZE - 1)
+ ARM_NS_DRAM1_SIZE - 1U)
#define ARM_DRAM1_BASE ULL(0x80000000)
#define ARM_DRAM1_SIZE ULL(0x80000000)
#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
- ARM_DRAM1_SIZE - 1)
+ ARM_DRAM1_SIZE - 1U)
#define ARM_DRAM2_BASE PLAT_ARM_DRAM2_BASE
#define ARM_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE
#define ARM_DRAM2_END (ARM_DRAM2_BASE + \
- ARM_DRAM2_SIZE - 1)
+ ARM_DRAM2_SIZE - 1U)
#define ARM_IRQ_SEC_PHY_TIMER 29
@@ -294,12 +294,19 @@
#define ARM_V2M_MAP_MEM_PROTECT MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR, \
V2M_FLASH_BLOCK_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
/*
* The max number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
*/
-#define ARM_BL_REGIONS 5
+#define ARM_BL_REGIONS 6
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
ARM_BL_REGIONS)
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 3625530..95fc18e 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -235,8 +235,20 @@
#if MEASURED_BOOT
/* Measured boot related functions */
-void arm_bl1_set_bl2_hash(image_desc_t *image_desc);
+void arm_bl1_set_bl2_hash(const image_desc_t *image_desc);
+void arm_bl2_get_hash(void *data);
+int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+ size_t log_size);
+int arm_set_nt_fw_info(uintptr_t config_base,
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this option should be removed when feature is supported.
+ */
+#ifdef SPD_opteed
+ uintptr_t log_addr,
#endif
+ size_t log_size, uintptr_t *ns_log_addr);
+#endif /* MEASURED_BOOT */
/*
* Free the memory storing initialization code only used during an images boot
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 720c259..2c1a180 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -175,6 +175,14 @@
int bl1_plat_handle_pre_image_load(unsigned int image_id);
int bl1_plat_handle_post_image_load(unsigned int image_id);
+#if MEASURED_BOOT
+/*
+ * Calculates and writes BL2 hash data to the platform's defined location.
+ * For ARM platforms the data are written to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc);
+#endif
+
/*******************************************************************************
* Mandatory BL2 functions
******************************************************************************/
@@ -190,11 +198,13 @@
int bl2_plat_handle_pre_image_load(unsigned int image_id);
int bl2_plat_handle_post_image_load(unsigned int image_id);
-
/*******************************************************************************
* Optional BL2 functions (may be overridden)
******************************************************************************/
-
+#if MEASURED_BOOT
+/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
+void bl2_plat_get_hash(void *data);
+#endif
/*******************************************************************************
* Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is
@@ -204,7 +214,6 @@
u_register_t arg2, u_register_t arg3);
void bl2_el3_plat_arch_setup(void);
-
/*******************************************************************************
* Optional BL2 at EL3 functions (may be overridden)
******************************************************************************/
@@ -332,4 +341,9 @@
*/
int32_t plat_get_soc_revision(void);
+/*
+ * Optional function to check for SMCCC function availability for platform
+ */
+int32_t plat_is_smccc_feature_available(u_register_t fid);
+
#endif /* PLATFORM_H */
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 0f80de1..d537ed6 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -375,35 +375,6 @@
b cpu_rev_var_range
endfunc check_errata_1542419
-/* --------------------------------------------------
- * Errata Workaround for Neoverse N1 Erratum 1800710.
- * This applies to revisions <= r4p0 of Neoverse N1
- * Inputs:
- * x0: variant[4:7] and revision[0:3] of current cpu.
- * Shall clobber: x0-x17
- * --------------------------------------------------
- */
-func errata_n1_1800710_wa
- /* Compare x0 against revision <= r4p0 */
- mov x17, x30
- bl check_errata_1800710
- cbz x0, 1f
-
- /* Disable allocation of splintered pages in the L2 TLB */
- mrs x1, NEOVERSE_N1_CPUECTLR_EL1
- orr x1, x1, NEOVERSE_N1_CPUECTLR_EL1_BIT_53
- msr NEOVERSE_N1_CPUECTLR_EL1, x1
- isb
-1:
- ret x17
-endfunc errata_n1_1800710_wa
-
-func check_errata_1800710
- /* Applies to everything <= r4p0 */
- mov x1, #0x40
- b cpu_rev_var_ls
-endfunc check_errata_1800710
-
func neoverse_n1_reset_func
mov x19, x30
@@ -478,11 +449,6 @@
bl errata_n1_1542419_wa
#endif
-#if ERRATA_N1_1800710
- mov x0, x18
- bl errata_n1_1800710_wa
-#endif
-
#if ENABLE_AMU
/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
mrs x0, actlr_el3
@@ -556,7 +522,6 @@
report_errata ERRATA_N1_1275112, neoverse_n1, 1275112
report_errata ERRATA_N1_1315703, neoverse_n1, 1315703
report_errata ERRATA_N1_1542419, neoverse_n1, 1542419
- report_errata ERRATA_N1_1800710, neoverse_n1, 1800710
report_errata ERRATA_DSU_936184, neoverse_n1, dsu_936184
ldp x8, x30, [sp], #16
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 3c895f5..e494375 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -314,10 +314,6 @@
# to revisions r3p0 - r4p0 of the Neoverse N1 cpu.
ERRATA_N1_1542419 ?=0
-# Flag to apply erratum 1800710 workaround during reset. This erratum applies
-# to revisions <= r4p0 of the Neoverse N1 cpu.
-ERRATA_N1_1800710 ?=0
-
# Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
# Applying the workaround results in higher DSU power consumption on idle.
ERRATA_DSU_798953 ?=0
@@ -567,10 +563,6 @@
$(eval $(call assert_boolean,ERRATA_N1_1542419))
$(eval $(call add_define,ERRATA_N1_1542419))
-# Process ERRATA_N1_1800710 flag
-$(eval $(call assert_boolean,ERRATA_N1_1800710))
-$(eval $(call add_define,ERRATA_N1_1800710))
-
# Process ERRATA_DSU_798953 flag
$(eval $(call assert_boolean,ERRATA_DSU_798953))
$(eval $(call add_define,ERRATA_DSU_798953))
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
index bc4fa8e..24b6bcc 100644
--- a/lib/fconf/fconf.c
+++ b/lib/fconf/fconf.c
@@ -32,8 +32,7 @@
assert(config_info != NULL);
config_image_info.image_base = config_info->config_addr;
- config_image_info.image_max_size =
- (uint32_t)config_info->config_max_size;
+ config_image_info.image_max_size = config_info->config_max_size;
VERBOSE("FCONF: Loading config with image ID: %d\n", image_id);
err = load_auth_image(image_id, &config_image_info);
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 902c07d..25dd7f9 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -12,66 +12,59 @@
#include <lib/object_pool.h>
#include <libfdt.h>
-/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs */
+/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs */
#define MAX_DTB_INFO U(6)
+/*
+ * Compile time assert if FW_CONFIG_ID is 0 which is more
+ * unlikely as 0 is a valid image ID for FIP as per the current
+ * code but still to avoid code breakage in case of unlikely
+ * event when image IDs get changed.
+ */
+CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id);
static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
/*
- * This function is used to alloc memory for fw config information from
- * global pool and set fw configuration information.
- * Specifically used by BL1 to set fw_config information in global array
+ * This function is used to alloc memory for config information from
+ * global pool and set the configuration information.
*/
-void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size)
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+ unsigned int config_id)
{
struct dyn_cfg_dtb_info_t *dtb_info;
dtb_info = pool_alloc(&dtb_info_pool);
dtb_info->config_addr = config_addr;
dtb_info->config_max_size = config_max_size;
- dtb_info->config_id = FW_CONFIG_ID;
+ dtb_info->config_id = config_id;
}
struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
{
unsigned int index;
- struct dyn_cfg_dtb_info_t *info;
/* Positions index to the proper config-id */
- for (index = 0; index < MAX_DTB_INFO; index++) {
+ for (index = 0U; index < MAX_DTB_INFO; index++) {
if (dtb_infos[index].config_id == config_id) {
- info = &dtb_infos[index];
- break;
+ return &dtb_infos[index];
}
}
- if (index == MAX_DTB_INFO) {
- WARN("FCONF: Invalid config id %u\n", config_id);
- info = NULL;
- }
+ WARN("FCONF: Invalid config id %u\n", config_id);
- return info;
+ return NULL;
}
int fconf_populate_dtb_registry(uintptr_t config)
{
int rc;
int node, child;
- struct dyn_cfg_dtb_info_t *dtb_info;
/* As libfdt use void *, we can't avoid this cast */
const void *dtb = (void *)config;
/*
- * Compile time assert if FW_CONFIG_ID is 0 which is more
- * unlikely as 0 is a valid image id for FIP as per the current
- * code but still to avoid code breakage in case of unlikely
- * event when image ids gets changed.
- */
- CASSERT(FW_CONFIG_ID != 0, assert_invalid_fw_config_id);
-
- /*
* In case of BL1, fw_config dtb information is already
* populated in global dtb_infos array by 'set_fw_config_info'
* function, Below check is present to avoid re-population of
@@ -80,11 +73,9 @@
* Other BLs, satisfy below check and populate fw_config information
* in global dtb_infos array.
*/
- if (dtb_infos[0].config_id == 0) {
- dtb_info = pool_alloc(&dtb_info_pool);
- dtb_info->config_addr = config;
- dtb_info->config_max_size = fdt_totalsize(dtb);
- dtb_info->config_id = FW_CONFIG_ID;
+ if (dtb_infos[0].config_id == 0U) {
+ uint32_t config_max_size = fdt_totalsize(dtb);
+ set_config_info(config, config_max_size, FW_CONFIG_ID);
}
/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
@@ -96,37 +87,36 @@
}
fdt_for_each_subnode(child, dtb, node) {
- uint32_t val32;
+ uint32_t config_max_size, config_id;
+ uintptr_t config_addr;
uint64_t val64;
- dtb_info = pool_alloc(&dtb_info_pool);
-
/* Read configuration dtb information */
rc = fdt_read_uint64(dtb, child, "load-address", &val64);
if (rc < 0) {
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
return rc;
}
- dtb_info->config_addr = (uintptr_t)val64;
+ config_addr = (uintptr_t)val64;
- rc = fdt_read_uint32(dtb, child, "max-size", &val32);
+ rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size);
if (rc < 0) {
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
return rc;
}
- dtb_info->config_max_size = val32;
- rc = fdt_read_uint32(dtb, child, "id", &val32);
+ rc = fdt_read_uint32(dtb, child, "id", &config_id);
if (rc < 0) {
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
return rc;
}
- dtb_info->config_id = val32;
VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
- VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
- VERBOSE("\tmax-size = 0x%zx\n", dtb_info->config_max_size);
- VERBOSE("\tconfig-id = %u\n", dtb_info->config_id);
+ VERBOSE("\tload-address = %lx\n", config_addr);
+ VERBOSE("\tmax-size = 0x%x\n", config_max_size);
+ VERBOSE("\tconfig-id = %u\n", config_id);
+
+ set_config_info(config_addr, config_max_size, config_id);
}
if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index 2127801..9a20ced 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -27,20 +27,25 @@
const char *compatible_str = "arm,tb_fw";
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
if (node < 0) {
- ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+ ERROR("FCONF: Can't find `%s` compatible in dtb\n",
+ compatible_str);
return node;
}
/* Locate the disable_auth cell and read the value */
- err = fdt_read_uint32(dtb, node, "disable_auth", &tbbr_dyn_config.disable_auth);
+ err = fdt_read_uint32(dtb, node, "disable_auth",
+ &tbbr_dyn_config.disable_auth);
if (err < 0) {
- WARN("FCONF: Read cell failed for `disable_auth`\n");
+ WARN("FCONF: Read %s failed for `%s`\n",
+ "cell", "disable_auth");
return err;
}
/* Check if the value is boolean */
- if ((tbbr_dyn_config.disable_auth != 0U) && (tbbr_dyn_config.disable_auth != 1U)) {
- WARN("Invalid value for `disable_auth` cell %d\n", tbbr_dyn_config.disable_auth);
+ if ((tbbr_dyn_config.disable_auth != 0U) &&
+ (tbbr_dyn_config.disable_auth != 1U)) {
+ WARN("Invalid value for `%s` cell %d\n",
+ "disable_auth", tbbr_dyn_config.disable_auth);
return -1;
}
@@ -52,25 +57,40 @@
/* Retrieve the Mbed TLS heap details from the DTB */
err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64);
if (err < 0) {
- ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+ ERROR("FCONF: Read %s failed for `%s`\n",
+ "cell", "mbedtls_heap_addr");
return err;
}
tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64;
err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32);
if (err < 0) {
- ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+ ERROR("FCONF: Read %s failed for `%s`\n",
+ "cell", "mbedtls_heap_size");
return err;
}
tbbr_dyn_config.mbedtls_heap_size = val32;
- VERBOSE("FCONF:tbbr.disable_auth cell found with value = %d\n",
- tbbr_dyn_config.disable_auth);
- VERBOSE("FCONF:tbbr.mbedtls_heap_addr cell found with value = %p\n",
- tbbr_dyn_config.mbedtls_heap_addr);
- VERBOSE("FCONF:tbbr.mbedtls_heap_size cell found with value = %zu\n",
- tbbr_dyn_config.mbedtls_heap_size);
-
+#if MEASURED_BOOT
+ /* Retrieve BL2 hash data details from the DTB */
+ err = fdtw_read_bytes(dtb, node, "bl2_hash_data", TCG_DIGEST_SIZE,
+ &tbbr_dyn_config.bl2_hash_data);
+ if (err < 0) {
+ ERROR("FCONF: Read %s failed for '%s'\n",
+ "bytes", "bl2_hash_data");
+ return err;
+ }
+#endif
+ VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth",
+ "` cell found with value =", tbbr_dyn_config.disable_auth);
+ VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
+ "` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
+ VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size",
+ "` cell found with value =", tbbr_dyn_config.mbedtls_heap_size);
+#if MEASURED_BOOT
+ VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "bl2_hash_data",
+ "` array found at address =", tbbr_dyn_config.bl2_hash_data);
+#endif
return 0;
}
diff --git a/lib/xlat_tables/aarch32/nonlpae_tables.c b/lib/xlat_tables/aarch32/nonlpae_tables.c
index b8c2686..7cd509d 100644
--- a/lib/xlat_tables/aarch32/nonlpae_tables.c
+++ b/lib/xlat_tables/aarch32/nonlpae_tables.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016-2017, Linaro Limited. All rights reserved.
- * Copyright (c) 2014-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2014-2020, Arm Limited. All rights reserved.
* Copyright (c) 2014, STMicroelectronics International N.V.
* All rights reserved.
*
@@ -30,8 +30,8 @@
CASSERT(PLAT_VIRT_ADDR_SPACE_SIZE == (1ULL << 32), invalid_vaddr_space_size);
CASSERT(PLAT_PHY_ADDR_SPACE_SIZE == (1ULL << 32), invalid_paddr_space_size);
-#define MMU32B_UNSET_DESC ~0ul
-#define MMU32B_INVALID_DESC 0ul
+#define MMU32B_UNSET_DESC ~0UL
+#define MMU32B_INVALID_DESC 0UL
#define MT_UNKNOWN ~0U
@@ -40,38 +40,38 @@
*/
/* Sharable */
-#define MMU32B_TTB_S (1 << 1)
+#define MMU32B_TTB_S (1U << 1)
/* Not Outer Sharable */
-#define MMU32B_TTB_NOS (1 << 5)
+#define MMU32B_TTB_NOS (1U << 5)
/* Normal memory, Inner Non-cacheable */
-#define MMU32B_TTB_IRGN_NC 0
+#define MMU32B_TTB_IRGN_NC 0U
/* Normal memory, Inner Write-Back Write-Allocate Cacheable */
-#define MMU32B_TTB_IRGN_WBWA (1 << 6)
+#define MMU32B_TTB_IRGN_WBWA (1U << 6)
/* Normal memory, Inner Write-Through Cacheable */
-#define MMU32B_TTB_IRGN_WT 1
+#define MMU32B_TTB_IRGN_WT 1U
/* Normal memory, Inner Write-Back no Write-Allocate Cacheable */
-#define MMU32B_TTB_IRGN_WB (1 | (1 << 6))
+#define MMU32B_TTB_IRGN_WB (1U | (1U << 6))
/* Normal memory, Outer Write-Back Write-Allocate Cacheable */
-#define MMU32B_TTB_RNG_WBWA (1 << 3)
+#define MMU32B_TTB_RNG_WBWA (1U << 3)
#define MMU32B_DEFAULT_ATTRS \
(MMU32B_TTB_S | MMU32B_TTB_NOS | \
MMU32B_TTB_IRGN_WBWA | MMU32B_TTB_RNG_WBWA)
/* armv7 memory mapping attributes: section mapping */
-#define SECTION_SECURE (0 << 19)
-#define SECTION_NOTSECURE (1 << 19)
-#define SECTION_SHARED (1 << 16)
-#define SECTION_NOTGLOBAL (1 << 17)
-#define SECTION_ACCESS_FLAG (1 << 10)
-#define SECTION_UNPRIV (1 << 11)
-#define SECTION_RO (1 << 15)
+#define SECTION_SECURE (0U << 19)
+#define SECTION_NOTSECURE (1U << 19)
+#define SECTION_SHARED (1U << 16)
+#define SECTION_NOTGLOBAL (1U << 17)
+#define SECTION_ACCESS_FLAG (1U << 10)
+#define SECTION_UNPRIV (1U << 11)
+#define SECTION_RO (1U << 15)
#define SECTION_TEX(tex) ((((tex) >> 2) << 12) | \
((((tex) >> 1) & 0x1) << 3) | \
(((tex) & 0x1) << 2))
@@ -80,16 +80,16 @@
#define SECTION_NORMAL_CACHED \
SECTION_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX)
-#define SECTION_XN (1 << 4)
-#define SECTION_PXN (1 << 0)
-#define SECTION_SECTION (2 << 0)
+#define SECTION_XN (1U << 4)
+#define SECTION_PXN (1U << 0)
+#define SECTION_SECTION (2U << 0)
-#define SECTION_PT_NOTSECURE (1 << 3)
-#define SECTION_PT_PT (1 << 0)
+#define SECTION_PT_NOTSECURE (1U << 3)
+#define SECTION_PT_PT (1U << 0)
-#define SMALL_PAGE_SMALL_PAGE (1 << 1)
-#define SMALL_PAGE_SHARED (1 << 10)
-#define SMALL_PAGE_NOTGLOBAL (1 << 11)
+#define SMALL_PAGE_SMALL_PAGE (1U << 1)
+#define SMALL_PAGE_SHARED (1U << 10)
+#define SMALL_PAGE_NOTGLOBAL (1U << 11)
#define SMALL_PAGE_TEX(tex) ((((tex) >> 2) << 6) | \
((((tex) >> 1) & 0x1) << 3) | \
(((tex) & 0x1) << 2))
@@ -99,39 +99,39 @@
SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX)
#define SMALL_PAGE_NORMAL_CACHED \
SMALL_PAGE_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX)
-#define SMALL_PAGE_ACCESS_FLAG (1 << 4)
-#define SMALL_PAGE_UNPRIV (1 << 5)
-#define SMALL_PAGE_RO (1 << 9)
-#define SMALL_PAGE_XN (1 << 0)
+#define SMALL_PAGE_ACCESS_FLAG (1U << 4)
+#define SMALL_PAGE_UNPRIV (1U << 5)
+#define SMALL_PAGE_RO (1U << 9)
+#define SMALL_PAGE_XN (1U << 0)
/* The TEX, C and B bits concatenated */
-#define MMU32B_ATTR_DEVICE_INDEX 0x0
-#define MMU32B_ATTR_IWBWA_OWBWA_INDEX 0x1
+#define MMU32B_ATTR_DEVICE_INDEX 0U
+#define MMU32B_ATTR_IWBWA_OWBWA_INDEX 1U
#define MMU32B_PRRR_IDX(idx, tr, nos) (((tr) << (2 * (idx))) | \
((uint32_t)(nos) << ((idx) + 24)))
#define MMU32B_NMRR_IDX(idx, ir, or) (((ir) << (2 * (idx))) | \
((uint32_t)(or) << (2 * (idx) + 16)))
-#define MMU32B_PRRR_DS0 (1 << 16)
-#define MMU32B_PRRR_DS1 (1 << 17)
-#define MMU32B_PRRR_NS0 (1 << 18)
-#define MMU32B_PRRR_NS1 (1 << 19)
+#define MMU32B_PRRR_DS0 (1U << 16)
+#define MMU32B_PRRR_DS1 (1U << 17)
+#define MMU32B_PRRR_NS0 (1U << 18)
+#define MMU32B_PRRR_NS1 (1U << 19)
#define DACR_DOMAIN(num, perm) ((perm) << ((num) * 2))
-#define DACR_DOMAIN_PERM_NO_ACCESS 0x0
-#define DACR_DOMAIN_PERM_CLIENT 0x1
-#define DACR_DOMAIN_PERM_MANAGER 0x3
+#define DACR_DOMAIN_PERM_NO_ACCESS 0U
+#define DACR_DOMAIN_PERM_CLIENT 1U
+#define DACR_DOMAIN_PERM_MANAGER 3U
-#define NUM_1MB_IN_4GB (1U << 12)
-#define NUM_4K_IN_1MB (1U << 8)
+#define NUM_1MB_IN_4GB (1UL << 12)
+#define NUM_4K_IN_1MB (1UL << 8)
#define ONE_MB_SHIFT 20
/* mmu 32b integration */
#define MMU32B_L1_TABLE_SIZE (NUM_1MB_IN_4GB * 4)
#define MMU32B_L2_TABLE_SIZE (NUM_4K_IN_1MB * 4)
-#define MMU32B_L1_TABLE_ALIGN (1 << 14)
-#define MMU32B_L2_TABLE_ALIGN (1 << 10)
+#define MMU32B_L1_TABLE_ALIGN (1U << 14)
+#define MMU32B_L2_TABLE_ALIGN (1U << 10)
static unsigned int next_xlat;
static unsigned long long xlat_max_pa;
@@ -190,8 +190,9 @@
assert(IS_PAGE_ALIGNED(base_va));
assert(IS_PAGE_ALIGNED(size));
- if (size == 0U)
+ if (size == 0U) {
return;
+ }
assert(base_pa < end_pa); /* Check for overflows */
assert(base_va < end_va);
@@ -249,8 +250,9 @@
#endif /* ENABLE_ASSERTIONS */
/* Find correct place in mmap to insert new region */
- while ((mm->base_va < base_va) && (mm->size != 0U))
+ while ((mm->base_va < base_va) && (mm->size != 0U)) {
++mm;
+ }
/*
* If a section is contained inside another one with the same base
@@ -263,8 +265,9 @@
* This is required for mmap_region_attr() to get the attributes of the
* small region correctly.
*/
- while ((mm->base_va == base_va) && (mm->size > size))
+ while ((mm->base_va == base_va) && (mm->size > size)) {
++mm;
+ }
/* Make room for new region by moving other regions up by one place */
(void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm);
@@ -277,10 +280,12 @@
mm->size = size;
mm->attr = attr;
- if (end_pa > xlat_max_pa)
+ if (end_pa > xlat_max_pa) {
xlat_max_pa = end_pa;
- if (end_va > xlat_max_va)
+ }
+ if (end_va > xlat_max_va) {
xlat_max_va = end_va;
+ }
}
/* map all memory as shared/global/domain0/no-usr access */
@@ -290,42 +295,44 @@
uint32_t desc;
switch (level) {
- case 1:
- assert(!(addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)));
+ case 1U:
+ assert((addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U);
desc = SECTION_SECTION | SECTION_SHARED;
- desc |= attr & MT_NS ? SECTION_NOTSECURE : 0;
+ desc |= (attr & MT_NS) != 0U ? SECTION_NOTSECURE : 0U;
desc |= SECTION_ACCESS_FLAG;
- desc |= attr & MT_RW ? 0 : SECTION_RO;
+ desc |= (attr & MT_RW) != 0U ? 0U : SECTION_RO;
- desc |= attr & MT_MEMORY ?
+ desc |= (attr & MT_MEMORY) != 0U ?
SECTION_NORMAL_CACHED : SECTION_DEVICE;
- if ((attr & MT_RW) || !(attr & MT_MEMORY))
+ if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) {
desc |= SECTION_XN;
+ }
break;
- case 2:
- assert(!(addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)));
+ case 2U:
+ assert((addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U);
desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED;
desc |= SMALL_PAGE_ACCESS_FLAG;
- desc |= attr & MT_RW ? 0 : SMALL_PAGE_RO;
+ desc |= (attr & MT_RW) != 0U ? 0U : SMALL_PAGE_RO;
- desc |= attr & MT_MEMORY ?
+ desc |= (attr & MT_MEMORY) != 0U ?
SMALL_PAGE_NORMAL_CACHED : SMALL_PAGE_DEVICE;
- if ((attr & MT_RW) || !(attr & MT_MEMORY))
+ if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) {
desc |= SMALL_PAGE_XN;
+ }
break;
default:
panic();
}
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
/* dump only the non-lpae level 2 tables */
- if (level == 2) {
+ if (level == 2U) {
printf(attr & MT_MEMORY ? "MEM" : "dev");
printf(attr & MT_RW ? "-rw" : "-RO");
printf(attr & MT_NS ? "-NS" : "-S");
@@ -357,26 +364,31 @@
*/
for ( ; ; ++mm) {
- if (mm->size == 0U)
+ if (mm->size == 0U) {
return ret; /* Reached end of list */
+ }
- if (mm->base_va > (base_va + size - 1U))
+ if (mm->base_va > (base_va + size - 1U)) {
return ret; /* Next region is after area so end */
+ }
- if ((mm->base_va + mm->size - 1U) < base_va)
+ if ((mm->base_va + mm->size - 1U) < base_va) {
continue; /* Next region has already been overtaken */
+ }
- if ((ret == 0U) && (mm->attr == *attr))
+ if ((ret == 0U) && (mm->attr == *attr)) {
continue; /* Region doesn't override attribs so skip */
+ }
if ((mm->base_va > base_va) ||
- ((mm->base_va + mm->size - 1U) < (base_va + size - 1U)))
+ ((mm->base_va + mm->size - 1U) <
+ (base_va + size - 1U))) {
return MT_UNKNOWN; /* Region doesn't fully cover area */
+ }
*attr = mm->attr;
ret = 0U;
}
- return ret;
}
static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm,
@@ -384,16 +396,16 @@
uint32_t *table,
unsigned int level)
{
- unsigned int level_size_shift = (level == 1) ?
+ unsigned int level_size_shift = (level == 1U) ?
ONE_MB_SHIFT : FOUR_KB_SHIFT;
- unsigned int level_size = 1 << level_size_shift;
- unsigned int level_index_mask = (level == 1) ?
+ unsigned int level_size = 1U << level_size_shift;
+ unsigned int level_index_mask = (level == 1U) ?
(NUM_1MB_IN_4GB - 1) << ONE_MB_SHIFT :
(NUM_4K_IN_1MB - 1) << FOUR_KB_SHIFT;
- assert(level == 1 || level == 2);
+ assert((level == 1U) || (level == 2U));
- VERBOSE("init xlat table at %p (level%1d)\n", (void *)table, level);
+ VERBOSE("init xlat table at %p (level%1u)\n", (void *)table, level);
do {
uint32_t desc = MMU32B_UNSET_DESC;
@@ -405,15 +417,17 @@
}
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
/* dump only non-lpae level 2 tables content */
- if (level == 2)
+ if (level == 2U) {
printf(" 0x%lx %x " + 6 - 2 * level,
base_va, level_size);
+ }
#endif
if (mm->base_va >= base_va + level_size) {
/* Next region is after area so nothing to map yet */
desc = MMU32B_INVALID_DESC;
- } else if (mm->base_va <= base_va && mm->base_va + mm->size >=
- base_va + level_size) {
+ } else if ((mm->base_va <= base_va) &&
+ (mm->base_va + mm->size) >=
+ (base_va + level_size)) {
/* Next region covers all of area */
unsigned int attr = mm->attr;
unsigned int r = mmap_region_attr(mm, base_va,
@@ -436,8 +450,8 @@
*/
if (*table) {
assert((*table & 3) == SECTION_PT_PT);
- assert(!(*table & SECTION_PT_NOTSECURE) ==
- !(mm->attr & MT_NS));
+ assert(((*table & SECTION_PT_NOTSECURE) == 0U)
+ == ((mm->attr & MT_NS) == 0U));
xlat_table = (*table) &
~(MMU32B_L1_TABLE_ALIGN - 1);
@@ -447,11 +461,11 @@
next_xlat * MMU32B_L2_TABLE_SIZE;
next_xlat++;
assert(next_xlat <= MAX_XLAT_TABLES);
- memset((char *)xlat_table, 0,
+ (void)memset((char *)xlat_table, 0,
MMU32B_L2_TABLE_SIZE);
desc = xlat_table | SECTION_PT_PT;
- desc |= mm->attr & MT_NS ?
+ desc |= (mm->attr & MT_NS) != 0U ?
SECTION_PT_NOTSECURE : 0;
}
/* Recurse to fill in new table */
@@ -461,12 +475,13 @@
}
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
/* dump only non-lpae level 2 tables content */
- if (level == 2)
+ if (level == 2U) {
printf("\n");
+ }
#endif
*table++ = desc;
base_va += level_size;
- } while (mm->size && (base_va & level_index_mask));
+ } while ((mm->size != 0U) && ((base_va & level_index_mask) != 0U));
return mm;
}
@@ -475,17 +490,16 @@
{
print_mmap();
- assert(!((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)));
- assert(!((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)));
+ assert(((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U);
+ assert(((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U);
- memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE);
+ (void)memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE);
init_xlation_table_inner(mmap, 0, (uint32_t *)mmu_l1_base, 1);
VERBOSE("init xlat - max_va=%p, max_pa=%llx\n",
(void *)xlat_max_va, xlat_max_pa);
- assert(xlat_max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
- assert(xlat_max_pa <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
+ assert(xlat_max_pa <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1));
}
/*******************************************************************************
@@ -499,7 +513,7 @@
unsigned int sctlr;
assert(IS_IN_SECURE());
- assert((read_sctlr() & SCTLR_M_BIT) == 0);
+ assert((read_sctlr() & SCTLR_M_BIT) == 0U);
/* Enable Access flag (simplified access permissions) and TEX remap */
write_sctlr(read_sctlr() | SCTLR_AFE_BIT | SCTLR_TRE_BIT);
@@ -522,7 +536,7 @@
/* set MMU base xlat table entry (use only TTBR0) */
write_ttbr0((uint32_t)mmu_l1_base | MMU32B_DEFAULT_ATTRS);
- write_ttbr1(0);
+ write_ttbr1(0U);
/*
* Ensure all translation table writes have drained
@@ -535,14 +549,15 @@
sctlr = read_sctlr();
sctlr |= SCTLR_M_BIT;
-#if ARMV7_SUPPORTS_VIRTUALIZATION
+#ifdef ARMV7_SUPPORTS_VIRTUALIZATION
sctlr |= SCTLR_WXN_BIT;
#endif
- if (flags & DISABLE_DCACHE)
+ if ((flags & DISABLE_DCACHE) != 0U) {
sctlr &= ~SCTLR_C_BIT;
- else
+ } else {
sctlr |= SCTLR_C_BIT;
+ }
write_sctlr(sctlr);
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 9a6fd58..caf5990 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -308,3 +308,6 @@
# Build option to create cot descriptors using fconf
COT_DESC_IN_DTB := 0
+
+# Build option to provide openssl directory path
+OPENSSL_DIR := /usr
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index 0745316..792a754 100644
--- a/plat/arm/board/a5ds/include/platform_def.h
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -152,10 +152,18 @@
#endif
/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
* The max number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
*/
-#define ARM_BL_REGIONS 5
+#define ARM_BL_REGIONS 6
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
ARM_BL_REGIONS)
@@ -194,6 +202,12 @@
#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
/*******************************************************************************
* BL1 specific defines.
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
@@ -221,6 +235,8 @@
/* Put BL32 below BL2 in NS DRAM.*/
#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
+ + (PAGE_SIZE / 2U))
#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
index aeed310..20120c9 100644
--- a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
+++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
@@ -7,6 +7,8 @@
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
+#include "../fpga_private.h"
+
#include <platform_def.h>
.globl plat_get_my_entrypoint
@@ -14,10 +16,10 @@
.globl plat_is_my_cpu_primary
.globl platform_mem_init
.globl plat_my_core_pos
- .globl plat_fpga_calc_core_pos
.globl plat_crash_console_init
.globl plat_crash_console_putc
.globl plat_crash_console_flush
+ .globl plat_fpga_calc_core_pos
/* -----------------------------------------------------------------------
* Indicate a cold boot for every CPU - warm boot is unsupported for the
@@ -34,23 +36,59 @@
* -----------------------------------------------------------------------
*/
func plat_secondary_cold_boot_setup
+
+ /*
+ * Wait for the primary processor to initialise the .BSS segment
+ * to avoid a race condition that would erase fpga_valid_mpids
+ * if it is populated before the C runtime is ready.
+ *
+ * We cannot use the current spin-lock implementation until the
+ * runtime is up and we should not rely on sevl/wfe instructions as
+ * it is optional whether they are implemented or not, so we use
+ * a global variable as lock and wait for the primary processor to
+ * finish the C runtime bring-up.
+ */
+
+ ldr w0, =C_RUNTIME_READY_KEY
+ adrp x1, secondary_core_spinlock
+ add x1, x1, :lo12:secondary_core_spinlock
+1:
+ wfe
+ ldr w2, [x1]
+ cmp w2, w0
+ b.ne 1b
+ /* Prevent reordering of the store into fpga_valid_mpids below */
+ dmb ish
+
+ mov x10, x30
+ bl plat_my_core_pos
+ mov x30, x10
+
+ adrp x4, fpga_valid_mpids
+ add x4, x4, :lo12:fpga_valid_mpids
+ mov x5, #VALID_MPID
+ strb w5, [x4, x0]
+
/*
* Poll the CPU's hold entry until it indicates to jump
* to the entrypoint address.
*/
- bl plat_my_core_pos
- lsl x0, x0, #PLAT_FPGA_HOLD_ENTRY_SHIFT
- ldr x1, =hold_base
- ldr x2, =fpga_sec_entrypoint
+
+ adrp x1, hold_base
+ add x1, x1, :lo12:hold_base
poll_hold_entry:
- ldr x3, [x1, x0]
+ ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
cmp x3, #PLAT_FPGA_HOLD_STATE_GO
b.ne 1f
+
+ adrp x2, fpga_sec_entrypoint
+ add x2, x2, :lo12:fpga_sec_entrypoint
ldr x3, [x2]
br x3
1:
wfe
b poll_hold_entry
+
endfunc plat_secondary_cold_boot_setup
/* -----------------------------------------------------------------------
@@ -73,12 +111,16 @@
endfunc platform_mem_init
func plat_my_core_pos
+ ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
mrs x0, mpidr_el1
+ and x0, x0, x1
b plat_fpga_calc_core_pos
+
endfunc plat_my_core_pos
/* -----------------------------------------------------------------------
- * unsigned int plat_fpga_calc_core_pos(u_register_t mpidr)
+ * unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
+ * Clobber registers: x0 to x5
* -----------------------------------------------------------------------
*/
func plat_fpga_calc_core_pos
@@ -88,6 +130,7 @@
*
* If not set, shift MPIDR to left to make it look as if in a
* multi-threaded implementation.
+ *
*/
tst x0, #MPIDR_MT_MASK
lsl x3, x0, #MPIDR_AFFINITY_BITS
@@ -98,11 +141,13 @@
ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
- /* Compute linear position */
mov x4, #FPGA_MAX_CPUS_PER_CLUSTER
- madd x1, x2, x4, x1
mov x5, #FPGA_MAX_PE_PER_CPU
+
+ /* Compute linear position */
+ madd x1, x2, x4, x1
madd x0, x1, x5, x0
+
ret
endfunc plat_fpga_calc_core_pos
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index e4b9767..9db107c 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -7,23 +7,23 @@
#include <assert.h>
#include <common/fdt_wrappers.h>
+#include <drivers/delay_timer.h>
#include <drivers/generic_delay_timer.h>
-#include <lib/mmio.h>
#include <libfdt.h>
+#include "fpga_private.h"
#include <plat/common/platform.h>
#include <platform_def.h>
-#include "fpga_private.h"
-
static entry_point_info_t bl33_image_ep_info;
+volatile uint32_t secondary_core_spinlock;
uintptr_t plat_get_ns_image_entrypoint(void)
{
#ifdef PRELOADED_BL33_BASE
return PRELOADED_BL33_BASE;
#else
- return 0;
+ return 0ULL;
#endif
}
@@ -35,6 +35,17 @@
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
+ /* Add this core to the VALID mpids list */
+ fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
+
+ /*
+ * Notify the secondary CPUs that the C runtime is ready
+ * so they can announce themselves.
+ */
+ secondary_core_spinlock = C_RUNTIME_READY_KEY;
+ dsbish();
+ sev();
+
fpga_console_init();
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
@@ -54,11 +65,37 @@
void bl31_platform_setup(void)
{
- /* Initialize the GIC driver, cpu and distributor interfaces */
- plat_fpga_gic_init();
-
/* Write frequency to CNTCRL and initialize timer */
generic_delay_timer_init();
+
+ /*
+ * Before doing anything else, wait for some time to ensure that
+ * the secondary CPUs have populated the fpga_valid_mpids array.
+ * As the number of secondary cores is unknown and can even be 0,
+ * it is not possible to rely on any signal from them, so use a
+ * delay instead.
+ */
+ mdelay(5);
+
+ /*
+ * On the event of a cold reset issued by, for instance, a reset pin
+ * assertion, we cannot guarantee memory to be initialized to zero.
+ * In such scenario, if the secondary cores reached
+ * plat_secondary_cold_boot_setup before the primary one initialized
+ * .BSS, we could end up having a race condition if the spinlock
+ * was not cleared before.
+ *
+ * Similarly, if there were a reset before the spinlock had been
+ * cleared, the secondary cores would find the lock opened before
+ * .BSS is cleared, causing another race condition.
+ *
+ * So clean the spinlock as soon as we think it is safe to reduce the
+ * chances of any race condition on a reset.
+ */
+ secondary_core_spinlock = 0UL;
+
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_fpga_gic_init();
}
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
@@ -91,6 +128,84 @@
FPGA_DEFAULT_TIMER_FREQUENCY);
}
+static void fpga_prepare_dtb(void)
+{
+ void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+ const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE;
+ int err;
+
+ err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE);
+ if (err < 0) {
+ ERROR("cannot open devicetree at %p: %d\n", fdt, err);
+ panic();
+ }
+
+ /* Check for the command line signature. */
+ if (!strncmp(cmdline, "CMD:", 4)) {
+ int chosen;
+
+ INFO("using command line at 0x%x\n", FPGA_PRELOADED_CMD_LINE);
+
+ chosen = fdt_add_subnode(fdt, 0, "chosen");
+ if (chosen == -FDT_ERR_EXISTS) {
+ chosen = fdt_path_offset(fdt, "/chosen");
+ }
+ if (chosen < 0) {
+ ERROR("cannot find /chosen node: %d\n", chosen);
+ } else {
+ const char *eol;
+ char nul = 0;
+ int slen;
+
+ /*
+ * There is most likely an EOL at the end of the
+ * command line, make sure we terminate the line there.
+ * We can't replace the EOL with a NUL byte in the
+ * source, as this is in read-only memory. So we first
+ * create the property without any termination, then
+ * append a single NUL byte.
+ */
+ eol = strchr(cmdline, '\n');
+ if (!eol) {
+ eol = strchr(cmdline, 0);
+ }
+ /* Skip the signature and omit the EOL/NUL byte. */
+ slen = eol - (cmdline + 4);
+
+ /*
+ * Let's limit the size of the property, just in case
+ * we find the signature by accident. The Linux kernel
+ * limits to 4096 characters at most (in fact 2048 for
+ * arm64), so that sounds like a reasonable number.
+ */
+ if (slen > 4095) {
+ slen = 4095;
+ }
+ err = fdt_setprop(fdt, chosen, "bootargs",
+ cmdline + 4, slen);
+ if (!err) {
+ err = fdt_appendprop(fdt, chosen, "bootargs",
+ &nul, 1);
+ }
+ if (err) {
+ ERROR("Could not set command line: %d\n", err);
+ }
+ }
+ }
+
+ err = fdt_pack(fdt);
+ if (err < 0) {
+ ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err);
+ }
+
+ clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ fpga_prepare_dtb();
+}
+
void bl31_plat_enable_mmu(uint32_t flags)
{
/* TODO: determine if MMU needs to be enabled */
diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h
index 5f1951f..2884ea6 100644
--- a/plat/arm/board/arm_fpga/fpga_def.h
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -18,6 +18,7 @@
* that are present will still be indexed appropriately regardless of any empty
* entries in the array used to represent the topology.
*/
+
#define FPGA_MAX_CLUSTER_COUNT 4
#define FPGA_MAX_CPUS_PER_CLUSTER 8
#define FPGA_MAX_PE_PER_CPU 4
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 7545bd1..47059d6 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -7,12 +7,24 @@
#ifndef FPGA_PRIVATE_H
#define FPGA_PRIVATE_H
-unsigned int plat_fpga_calc_core_pos(u_register_t mpidr);
+#include "../fpga_def.h"
+#include <platform_def.h>
+
+#define C_RUNTIME_READY_KEY (0xaa55aa55)
+#define VALID_MPID (1U)
+#define FPGA_MAX_DTB_SIZE 0x10000
+
+#ifndef __ASSEMBLER__
+
+extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
void fpga_console_init(void);
void plat_fpga_gic_init(void);
void fpga_pwr_gic_on_finish(void);
void fpga_pwr_gic_off(void);
+unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
-#endif
+#endif /* __ASSEMBLER__ */
+
+#endif /* FPGA_PRIVATE_H */
diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c
index a2908d7..7fead86 100644
--- a/plat/arm/board/arm_fpga/fpga_topology.c
+++ b/plat/arm/board/arm_fpga/fpga_topology.c
@@ -5,15 +5,20 @@
*/
#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/spinlock.h>
#include "fpga_private.h"
+#include <plat/common/platform.h>
#include <platform_def.h>
-static unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
const unsigned char *plat_get_power_domain_tree_desc(void)
{
- int i;
+ unsigned int i;
+
/*
* The highest level is the system level. The next level is constituted
* by clusters and then cores in clusters.
@@ -21,12 +26,26 @@
* This description of the power domain topology is aligned with the CPU
* indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
* APIs.
+ *
+ * A description of the topology tree can be found at
+ * https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
*/
- fpga_power_domain_tree_desc[0] = 1;
- fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
- for (i = 0; i < FPGA_MAX_CLUSTER_COUNT; i++) {
- fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU;
+ if (fpga_power_domain_tree_desc[0] == 0U) {
+ /*
+ * As fpga_power_domain_tree_desc[0] == 0, assume that the
+ * Power Domain Topology Tree has not been initialized, so
+ * perform the initialization here.
+ */
+
+ fpga_power_domain_tree_desc[0] = 1U;
+ fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
+
+ for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
+ fpga_power_domain_tree_desc[2 + i] =
+ (FPGA_MAX_CPUS_PER_CLUSTER *
+ FPGA_MAX_PE_PER_CPU);
+ }
}
return fpga_power_domain_tree_desc;
@@ -34,40 +53,25 @@
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
- unsigned int cluster_id, cpu_id, thread_id;
+ unsigned int core_pos;
- /*
- * The image running on the FPGA may or may not implement
- * multithreading, and it shouldn't be assumed this is consistent
- * across all CPUs.
- * This ensures that any passed mpidr values reflect the status of the
- * primary CPU's MT bit.
- */
+ mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
- mpidr &= MPID_MASK;
- if (mpidr & MPIDR_MT_MASK) {
- thread_id = MPIDR_AFFLVL0_VAL(mpidr);
- cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
- cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
- } else {
- thread_id = 0;
- cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
+ (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
+ (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
+ ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
+ panic();
}
- if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) {
+ /* Calculate the core position, based on the maximum topology. */
+ core_pos = plat_fpga_calc_core_pos(mpidr);
+
+ /* Check whether this core is actually present. */
+ if (fpga_valid_mpids[core_pos] != VALID_MPID) {
return -1;
}
- if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
- return -1;
- }
-
- if (thread_id >= FPGA_MAX_PE_PER_CPU) {
- return -1;
- }
-
- /* Calculate the correct core, catering for multi-threaded images */
- return (int) plat_fpga_calc_core_pos(mpidr);
+ return core_pos;
}
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index 31fc987..411b936 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -21,11 +21,12 @@
#define CACHE_WRITEBACK_SHIFT U(6)
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
-#define PLATFORM_CORE_COUNT \
- (FPGA_MAX_CLUSTER_COUNT * FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU)
+#define PLATFORM_CORE_COUNT \
+ (FPGA_MAX_CLUSTER_COUNT * \
+ FPGA_MAX_CPUS_PER_CLUSTER * \
+ FPGA_MAX_PE_PER_CPU)
-#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + \
- PLATFORM_CORE_COUNT) + 1
+#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1)
#if !ENABLE_PIE
#define BL31_BASE UL(0x80000000)
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index e57912c..1e7badf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -29,6 +29,9 @@
FPGA_PRELOADED_DTB_BASE := 0x80070000
$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
+FPGA_PRELOADED_CMD_LINE := 0x1000
+$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
+
# Treating this as a memory-constrained port for now
USE_COHERENT_MEM := 0
diff --git a/plat/arm/board/corstone700/common/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h
index c92086c..57b0551 100644
--- a/plat/arm/board/corstone700/common/include/platform_def.h
+++ b/plat/arm/board/corstone700/common/include/platform_def.h
@@ -93,10 +93,23 @@
#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
/*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE (ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
+ + (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
+/*
* The max number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
*/
-#define ARM_BL_REGIONS 2
+#define ARM_BL_REGIONS 3
#define PLAT_ARM_MMAP_ENTRIES 8
#define MAX_XLAT_TABLES 5
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
@@ -201,6 +214,14 @@
MT_DEVICE | MT_RW | MT_SECURE)
#endif
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
#define CORSTONE700_DEVICE_BASE (0x1A000000)
#define CORSTONE700_DEVICE_SIZE (0x26000000)
#define CORSTONE700_MAP_DEVICE MAP_REGION_FLAT( \
diff --git a/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
new file mode 100644
index 0000000..e258015
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+
+#include <libfdt.h>
+#include <fconf_nt_config_getter.h>
+
+#include <plat/common/platform.h>
+
+struct event_log_config_t event_log_config;
+
+int fconf_populate_event_log_config(uintptr_t config)
+{
+ int err;
+ int node;
+
+ /* Necessary to work with libfdt APIs */
+ const void *dtb = (const void *)config;
+
+ /*
+ * Find the offset of the node containing "arm,tpm_event_log"
+ * compatible property
+ */
+ const char *compatible_str = "arm,tpm_event_log";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find '%s' compatible in dtb\n",
+ compatible_str);
+ return node;
+ }
+
+ /* Retrieve Event Log details from the DTB */
+#ifdef SPD_opteed
+ err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2,
+ &event_log_config.tpm_event_log_sm_addr);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n");
+ return err;
+ }
+#endif
+ err = fdtw_read_cells(dtb, node,
+ "tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n");
+ return err;
+ }
+
+ err = fdtw_read_cells(dtb, node,
+ "tpm_event_log_size", 1, &event_log_config.tpm_event_log_size);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n");
+ }
+
+ return err;
+}
+
+FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config,
+ fconf_populate_event_log_config);
diff --git a/plat/arm/board/fvp/fdts/event_log.dtsi b/plat/arm/board/fvp/fdts/event_log.dtsi
new file mode 100644
index 0000000..47af672
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/event_log.dtsi
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* TPM Event Log Config */
+event_log: tpm_event_log {
+ compatible = "arm,tpm_event_log";
+ tpm_event_log_addr = <0x0 0x0>;
+ tpm_event_log_size = <0x0>;
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
index 7ab980b..8f32b98 100644
--- a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,5 +7,13 @@
/dts-v1/;
/ {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
};
+
+#if MEASURED_BOOT && defined(SPD_opteed)
+&event_log {
+ tpm_event_log_sm_addr = <0x0 0x0>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
index 7ab980b..7bed6cb 100644
--- a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,5 +7,7 @@
/dts-v1/;
/ {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
};
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index d13cc81..0e77c4d 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -70,6 +70,14 @@
#if MEASURED_BOOT
/*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+ arm_bl1_set_bl2_hash(image_desc);
+}
+
+/*
* Implementation for bl1_plat_handle_post_image_load(). This function
* populates the default arguments to BL2. The BL2 memory layout structure
* is allocated and the calculated layout is populated in arg1 to BL2.
@@ -90,7 +98,7 @@
assert(image_desc != NULL);
/* Calculate BL2 hash and set it in TB_FW_CONFIG */
- arm_bl1_set_bl2_hash(image_desc);
+ bl1_plat_set_bl2_hash(image_desc);
/* Get the entry point info */
ep_info = &image_desc->ep_info;
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index d5618d9..f2f2143 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -6,8 +6,12 @@
#include <assert.h>
+#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/arm/sp804_delay_timer.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
@@ -69,3 +73,45 @@
return arm_bl_params;
}
+#if MEASURED_BOOT
+static int fvp_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ const bl_mem_params_node_t *bl_mem_params =
+ get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params != NULL);
+
+ image_info_t info = bl_mem_params->image_info;
+ int err;
+
+ if ((info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U) {
+ /* Calculate image hash and record data in Event Log */
+ err = tpm_record_measurement(info.image_base,
+ info.image_size, image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "BL2: Failed to ", "record", image_id, err);
+ return err;
+ }
+ }
+
+ err = arm_bl2_handle_post_image_load(image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "BL2: Failed to ", "handle", image_id, err);
+ }
+
+ return err;
+}
+
+int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = fvp_bl2_plat_handle_post_image_load(image_id);
+
+ if (err != 0) {
+ ERROR("%s() returns %i\n", __func__, err);
+ }
+
+ return err;
+}
+#endif /* MEASURED_BOOT */
diff --git a/plat/arm/board/fvp/fvp_measured_boot.c b/plat/arm/board/fvp/fvp_measured_boot.c
new file mode 100644
index 0000000..b145aae
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_measured_boot.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/measured_boot/event_log.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* FVP table with platform specific image IDs, names and PCRs */
+static const image_data_t fvp_images_data[] = {
+ { BL2_IMAGE_ID, BL2_STRING, PCR_0 }, /* Reserved for BL2 */
+ { BL31_IMAGE_ID, BL31_STRING, PCR_0 },
+ { BL32_IMAGE_ID, BL32_STRING, PCR_0 },
+ { BL32_EXTRA1_IMAGE_ID, BL32_EXTRA1_IMAGE_STRING, PCR_0 },
+ { BL32_EXTRA2_IMAGE_ID, BL32_EXTRA2_IMAGE_STRING, PCR_0 },
+ { BL33_IMAGE_ID, BL33_STRING, PCR_0 },
+ { GPT_IMAGE_ID, GPT_IMAGE_STRING, PCR_0 },
+ { HW_CONFIG_ID, HW_CONFIG_STRING, PCR_0 },
+ { NT_FW_CONFIG_ID, NT_FW_CONFIG_STRING, PCR_0 },
+ { SCP_BL2_IMAGE_ID, SCP_BL2_IMAGE_STRING, PCR_0 },
+ { SOC_FW_CONFIG_ID, SOC_FW_CONFIG_STRING, PCR_0 },
+ { STM32_IMAGE_ID, STM32_IMAGE_STRING, PCR_0 },
+ { TOS_FW_CONFIG_ID, TOS_FW_CONFIG_STRING, PCR_0 },
+ { INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+static const measured_boot_data_t fvp_measured_boot_data = {
+ fvp_images_data,
+ arm_set_nt_fw_info,
+ arm_set_tos_fw_info
+};
+
+/*
+ * Function retuns pointer to FVP plat_measured_boot_data_t structure
+ */
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+ return &fvp_measured_boot_data;
+}
diff --git a/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
new file mode 100644
index 0000000..0824c35
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_NT_CONFIG_GETTER_H
+#define FCONF_NT_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* NT Firmware Config related getter */
+#define nt_config__event_log_config_getter(prop) event_log.prop
+
+struct event_log_config_t {
+#ifdef SPD_opteed
+ void *tpm_event_log_sm_addr;
+#endif
+ void *tpm_event_log_addr;
+ size_t tpm_event_log_size;
+};
+
+int fconf_populate_event_log_config(uintptr_t config);
+
+extern struct event_log_config_t event_log_config;
+
+#endif /* FCONF_NT_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index f8fb821..a986017 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -243,8 +243,8 @@
/*
* GIC related constants to cater for both GICv2 and GICv3 instances of an
- * FVP. They could be overriden at runtime in case the FVP implements the legacy
- * VE memory map.
+ * FVP. They could be overridden at runtime in case the FVP implements the
+ * legacy VE memory map.
*/
#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
#define PLAT_ARM_GICR_BASE BASE_GICR_BASE
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 9b8fccc..98c70c9 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -354,6 +354,11 @@
ifeq (${TRUSTED_BOARD_BOOT}, 1)
BL1_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c
BL2_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c
+
+ifeq (${MEASURED_BOOT},1)
+BL2_SOURCES += plat/arm/board/fvp/fvp_measured_boot.c
+endif
+
# FVP being a development platform, enable capability to disable Authentication
# dynamically if TRUSTED_BOARD_BOOT is set.
DYN_DISABLE_AUTH := 1
diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h
index 3591b4d..3f2fcee 100644
--- a/plat/arm/board/fvp_ve/include/platform_def.h
+++ b/plat/arm/board/fvp_ve/include/platform_def.h
@@ -121,10 +121,19 @@
#endif
/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+
+/*
* The max number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
*/
-#define ARM_BL_REGIONS 5
+#define ARM_BL_REGIONS 6
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
ARM_BL_REGIONS)
@@ -173,7 +182,14 @@
* and limit. Leave enough space of BL2 meminfo.
*/
#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_LIMIT ((ARM_BL_RAM_BASE + PAGE_SIZE) \
+ + (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
/*******************************************************************************
* BL1 specific defines.
@@ -205,6 +221,8 @@
/* Put BL32 below BL2 in NS DRAM.*/
#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
+ + (PAGE_SIZE / 2U))
#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 0bd3a21..4b621e3 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -38,6 +38,8 @@
${N1SDP_BASE}/n1sdp_security.c \
drivers/arm/css/sds/sds.c
+FDT_SOURCES += fdts/${PLAT}-single-chip.dts \
+ fdts/${PLAT}-multi-chip.dts
# TF-A not required to load the SCP Images
override CSS_LOAD_SCP_IMAGES := 0
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 6b630b9..4b2a062 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -54,6 +54,9 @@
/* Data structure which holds the extents of the trusted SRAM for BL1*/
static meminfo_t bl1_tzram_layout;
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
struct meminfo *bl1_plat_sec_mem_layout(void)
{
return &bl1_tzram_layout;
@@ -152,15 +155,15 @@
plat_arm_io_setup();
/* Check if we need FWU before further processing */
- err = plat_arm_bl1_fwu_needed();
- if (err) {
+ is_fwu_needed = plat_arm_bl1_fwu_needed();
+ if (is_fwu_needed) {
ERROR("Skip platform setup as FWU detected\n");
return;
}
/* Set global DTB info for fixed fw_config information */
fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
- set_fw_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size);
+ set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID);
/* Fill the device tree information struct with the info from the config dtb */
err = fconf_load_config(FW_CONFIG_ID);
@@ -247,5 +250,5 @@
******************************************************************************/
unsigned int bl1_plat_get_next_image_id(void)
{
- return plat_arm_bl1_fwu_needed() ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
+ return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
}
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index fd60c2b..60d8f6e 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -26,6 +26,9 @@
/* Data structure which holds the extents of the trusted SRAM for BL2 */
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+/* Base address of fw_config received from BL1 */
+static uintptr_t fw_config_base;
+
/*
* Check that BL2_BASE is above ARM_FW_CONFIG_LIMIT. This reserved page is
* for `meminfo_t` data structure and fw_configs passed from BL1.
@@ -37,6 +40,9 @@
#pragma weak bl2_platform_setup
#pragma weak bl2_plat_arch_setup
#pragma weak bl2_plat_sec_mem_layout
+#if MEASURED_BOOT
+#pragma weak bl2_plat_get_hash
+#endif
#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
bl2_tzram_layout.total_base, \
@@ -54,21 +60,13 @@
void arm_bl2_early_platform_setup(uintptr_t fw_config,
struct meminfo *mem_layout)
{
- const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
/* Initialize the console to provide early debug support */
arm_console_boot_init();
/* Setup the BL2 memory layout */
bl2_tzram_layout = *mem_layout;
- /* Fill the properties struct with the info from the config dtb */
- fconf_populate("FW_CONFIG", fw_config);
-
- /* TB_FW_CONFIG was also loaded by BL1 */
- tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
- assert(tb_fw_config_info != NULL);
-
- fconf_populate("TB_FW", tb_fw_config_info->config_addr);
+ fw_config_base = fw_config;
/* Initialise the IO layer and register platform IO devices */
plat_arm_io_setup();
@@ -132,6 +130,7 @@
#if ARM_CRYPTOCELL_INTEG
ARM_MAP_BL_COHERENT_RAM,
#endif
+ ARM_MAP_BL_CONFIG_REGION,
{0}
};
@@ -148,7 +147,18 @@
void bl2_plat_arch_setup(void)
{
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+
arm_bl2_plat_arch_setup();
+
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", fw_config_base);
+
+ /* TB_FW_CONFIG was also loaded by BL1 */
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ fconf_populate("TB_FW", tb_fw_config_info->config_addr);
}
int arm_bl2_handle_post_image_load(unsigned int image_id)
@@ -225,3 +235,11 @@
{
return arm_bl2_plat_handle_post_image_load(image_id);
}
+
+#if MEASURED_BOOT
+/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
+void bl2_plat_get_hash(void *data)
+{
+ arm_bl2_get_hash(data);
+}
+#endif
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index ded8f89..58ccf0e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -114,6 +114,18 @@
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
bl32_image_ep_info.pc = BL32_BASE;
bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+
+#if defined(SPD_spmd)
+ /* SPM (hafnium in secure world) expects SPM Core manifest base address
+ * in x0, which in !RESET_TO_BL31 case loaded after base of non shared
+ * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non
+ * shared SRAM is allocated to BL31, so to avoid overwriting of manifest
+ * keep it in the last page.
+ */
+ bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE +
+ PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE;
+#endif
+
# endif /* BL32_BASE */
/* Populate entry point information for BL33 */
@@ -130,6 +142,14 @@
bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+#if defined(SPD_spmd) && !(ARM_LINUX_KERNEL_AS_BL33)
+ /*
+ * Hafnium in normal world expects its manifest address in x0, which
+ * is loaded at base of DRAM.
+ */
+ bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE;
+#endif
+
# if ARM_LINUX_KERNEL_AS_BL33
/*
* According to the file ``Documentation/arm64/booting.txt`` of the
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 60c777e..e2b99a3 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -13,7 +13,9 @@
#include <common/debug.h>
#include <common/romlib.h>
#include <lib/mmio.h>
+#include <lib/smccc.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
@@ -235,6 +237,23 @@
}
#endif
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
+ * otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
/*
* Weak function to get ARM platform SOC-ID, Always return SOC-ID=0
* ToDo: Get proper SOC-ID for every ARM platform and define this
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index a92bf25..96ab2d3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -337,3 +337,9 @@
$(error "To reclaim init code xlat tables v2 must be used")
endif
endif
+
+ifeq (${MEASURED_BOOT},1)
+ MEASURED_BOOT_MK := drivers/measured_boot/measured_boot.mk
+ $(info Including ${MEASURED_BOOT_MK})
+ include ${MEASURED_BOOT_MK}
+endif
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 633445b..6b3a611 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -23,6 +23,7 @@
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <lib/fconf/fconf_tbbr_getter.h>
+
#include <plat/arm/common/arm_dyn_cfg_helpers.h>
#include <plat/arm/common/plat_arm.h>
@@ -98,13 +99,14 @@
tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) {
- /* As libfdt use void *, we can't avoid this cast */
+ /* As libfdt uses void *, we can't avoid this cast */
void *dtb = (void *)tb_fw_cfg_dtb;
err = arm_set_dtb_mbedtls_heap_info(dtb,
mbedtls_heap_addr, mbedtls_heap_size);
if (err < 0) {
- ERROR("BL1: unable to write shared Mbed TLS heap information to DTB\n");
+ ERROR("%swrite shared Mbed TLS heap information%s",
+ "BL1: unable to ", " to DTB\n");
panic();
}
#if !MEASURED_BOOT
@@ -124,13 +126,13 @@
#if MEASURED_BOOT
/*
- * Puts the BL2 hash data to TB_FW_CONFIG DTB.
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
* Executed only from BL1.
*/
-void arm_bl1_set_bl2_hash(image_desc_t *image_desc)
+void arm_bl1_set_bl2_hash(const image_desc_t *image_desc)
{
unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
- image_info_t image_info = image_desc->image_info;
+ const image_info_t image_info = image_desc->image_info;
uintptr_t tb_fw_cfg_dtb;
int err;
const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
@@ -154,13 +156,15 @@
(void *)image_info.image_base,
image_info.image_size, hash_data);
if (err != 0) {
- ERROR("BL1: unable to calculate BL2 hash\n");
+ ERROR("%scalculate%s\n", "BL1: unable to ",
+ " BL2 hash");
panic();
}
err = arm_set_bl2_hash_info((void *)tb_fw_cfg_dtb, hash_data);
if (err < 0) {
- ERROR("BL1: unable to write BL2 hash data to DTB\n");
+ ERROR("%swrite%sdata%s\n", "BL1: unable to ",
+ " BL2 hash ", "to DTB\n");
panic();
}
@@ -171,6 +175,21 @@
*/
flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize((void *)tb_fw_cfg_dtb));
}
+
+/*
+ * Reads TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB.
+ * Executed only from BL2.
+ */
+void arm_bl2_get_hash(void *data)
+{
+ const void *bl2_hash;
+
+ assert(data != NULL);
+
+ /* Retrieve TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB */
+ bl2_hash = FCONF_GET_PROPERTY(tbbr, dyn_config, bl2_hash_data);
+ (void)memcpy(data, bl2_hash, TCG_DIGEST_SIZE);
+}
#endif /* MEASURED_BOOT */
#endif /* TRUSTED_BOARD_BOOT */
@@ -184,7 +203,7 @@
unsigned int i;
bl_mem_params_node_t *cfg_mem_params = NULL;
uintptr_t image_base;
- size_t image_size;
+ uint32_t image_size;
const unsigned int config_ids[] = {
HW_CONFIG_ID,
SOC_FW_CONFIG_ID,
@@ -202,14 +221,15 @@
/* Get the config load address and size from TB_FW_CONFIG */
cfg_mem_params = get_bl_mem_params_node(config_ids[i]);
if (cfg_mem_params == NULL) {
- VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n");
+ VERBOSE("%sHW_CONFIG in bl_mem_params_node\n",
+ "Couldn't find ");
continue;
}
dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]);
if (dtb_info == NULL) {
- VERBOSE("Couldn't find config_id %d load info in TB_FW_CONFIG\n",
- config_ids[i]);
+ VERBOSE("%sconfig_id %d load info in TB_FW_CONFIG\n",
+ "Couldn't find ", config_ids[i]);
continue;
}
@@ -223,30 +243,32 @@
*/
if (config_ids[i] != HW_CONFIG_ID) {
- if (check_uptr_overflow(image_base, image_size))
+ if (check_uptr_overflow(image_base, image_size)) {
continue;
-
+ }
#ifdef BL31_BASE
/* Ensure the configs don't overlap with BL31 */
if ((image_base >= BL31_BASE) &&
- (image_base <= BL31_LIMIT))
+ (image_base <= BL31_LIMIT)) {
continue;
+ }
#endif
/* Ensure the configs are loaded in a valid address */
- if (image_base < ARM_BL_RAM_BASE)
+ if (image_base < ARM_BL_RAM_BASE) {
continue;
+ }
#ifdef BL32_BASE
/*
* If BL32 is present, ensure that the configs don't
* overlap with it.
*/
if ((image_base >= BL32_BASE) &&
- (image_base <= BL32_LIMIT))
+ (image_base <= BL32_LIMIT)) {
continue;
+ }
#endif
}
-
cfg_mem_params->image_info.image_base = image_base;
cfg_mem_params->image_info.image_max_size = (uint32_t)image_size;
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index f110e3b..5f20c8d 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -6,9 +6,13 @@
#include <assert.h>
+#if MEASURED_BOOT
+#include <common/desc_image_load.h>
+#endif
+#include <common/fdt_wrappers.h>
+
#include <libfdt.h>
-#include <common/fdt_wrappers.h>
#include <plat/arm/common/arm_dyn_cfg_helpers.h>
#include <plat/arm/common/plat_arm.h>
@@ -17,6 +21,15 @@
#if MEASURED_BOOT
#define DTB_PROP_BL2_HASH_DATA "bl2_hash_data"
+#ifdef SPD_opteed
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this property should be removed when this feature is supported.
+ */
+#define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr"
+#endif
+#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
+#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
static int dtb_root = -1;
#endif /* MEASURED_BOOT */
@@ -37,18 +50,19 @@
/* Check if the pointer to DT is correct */
if (fdt_check_header(dtb) != 0) {
- WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
+ WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG");
return -1;
}
/* Assert the node offset point to "arm,tb_fw" compatible property */
*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
if (*node < 0) {
- WARN("The compatible property `arm,tb_fw` not found in the config\n");
+ WARN("The compatible property '%s' not%s", "arm,tb_fw",
+ " found in the config\n");
return -1;
}
- VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
+ VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n");
return 0;
}
@@ -76,7 +90,8 @@
*/
int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
if (err < 0) {
- ERROR("Invalid TB_FW_CONFIG loaded. Unable to get root node\n");
+ ERROR("Invalid%s loaded. Unable to get root node\n",
+ " TB_FW_CONFIG");
return -1;
}
@@ -90,16 +105,16 @@
err = fdtw_write_inplace_cells(dtb, dtb_root,
DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
if (err < 0) {
- ERROR("Unable to write DTB property %s\n",
- DTB_PROP_MBEDTLS_HEAP_ADDR);
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR);
return -1;
}
err = fdtw_write_inplace_cells(dtb, dtb_root,
DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
if (err < 0) {
- ERROR("Unable to write DTB property %s\n",
- DTB_PROP_MBEDTLS_HEAP_SIZE);
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE);
return -1;
}
@@ -124,7 +139,165 @@
/*
* Write the BL2 hash data in the DTB.
*/
- return fdtw_write_inplace_bytes(dtb, dtb_root, DTB_PROP_BL2_HASH_DATA,
+ return fdtw_write_inplace_bytes(dtb, dtb_root,
+ DTB_PROP_BL2_HASH_DATA,
TCG_DIGEST_SIZE, data);
}
+
+/*
+ * Write the Event Log address and its size in the DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+static int arm_set_event_log_info(uintptr_t config_base,
+#ifdef SPD_opteed
+ uintptr_t sm_log_addr,
+#endif
+ uintptr_t log_addr, size_t log_size)
+{
+ /* As libfdt uses void *, we can't avoid this cast */
+ void *dtb = (void *)config_base;
+ const char *compatible = "arm,tpm_event_log";
+ int err, node;
+
+ /*
+ * Verify that the DTB is valid, before attempting to write to it,
+ * and get the DTB root node.
+ */
+
+ /* Check if the pointer to DT is correct */
+ err = fdt_check_header(dtb);
+ if (err < 0) {
+ WARN("Invalid DTB file passed\n");
+ return err;
+ }
+
+ /* Assert the node offset point to compatible property */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible);
+ if (node < 0) {
+ WARN("The compatible property '%s' not%s", compatible,
+ " found in the config\n");
+ return node;
+ }
+
+ VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
+
+#ifdef SPD_opteed
+ if (sm_log_addr != 0UL) {
+ err = fdtw_write_inplace_cells(dtb, node,
+ DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR);
+ return err;
+ }
+ }
+#endif
+ err = fdtw_write_inplace_cells(dtb, node,
+ DTB_PROP_HW_LOG_ADDR, 2, &log_addr);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_HW_LOG_ADDR);
+ return err;
+ }
+
+ err = fdtw_write_inplace_cells(dtb, node,
+ DTB_PROP_HW_LOG_SIZE, 1, &log_size);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_HW_LOG_SIZE);
+ } else {
+ /*
+ * Ensure that the info written to the DTB is visible
+ * to other images.
+ */
+ flush_dcache_range(config_base, fdt_totalsize(dtb));
+ }
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TOS_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+ size_t log_size)
+{
+ int err;
+
+ assert(config_base != 0UL);
+ assert(log_addr != 0UL);
+
+ /* Write the Event Log address and its size in the DTB */
+ err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+ 0UL,
+#endif
+ log_addr, log_size);
+ if (err < 0) {
+ ERROR("%sEvent Log data to TOS_FW_CONFIG\n",
+ "Unable to write ");
+ }
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the NT_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int arm_set_nt_fw_info(uintptr_t config_base,
+#ifdef SPD_opteed
+ uintptr_t log_addr,
+#endif
+ size_t log_size, uintptr_t *ns_log_addr)
+{
+ uintptr_t ns_addr;
+ const bl_mem_params_node_t *cfg_mem_params;
+ int err;
+
+ assert(config_base != 0UL);
+ assert(ns_log_addr != NULL);
+
+ /* Get the config load address and size from NT_FW_CONFIG */
+ cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+ assert(cfg_mem_params != NULL);
+
+ /* Calculate Event Log address in Non-secure memory */
+ ns_addr = cfg_mem_params->image_info.image_base +
+ cfg_mem_params->image_info.image_max_size;
+
+ /* Check for memory space */
+ if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) {
+ return -1;
+ }
+
+ /* Write the Event Log address and its size in the DTB */
+ err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+ log_addr,
+#endif
+ ns_addr, log_size);
+
+ /* Return Event Log address in Non-secure memory */
+ *ns_log_addr = (err < 0) ? 0UL : ns_addr;
+ return err;
+}
#endif /* MEASURED_BOOT */
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 48cc4fe..350ecd1 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -51,7 +51,7 @@
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {UUID_TRUSTED_OS_FW_CONTENT_CERT},
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {UUID_NON_TRUSTED_FW_CONTENT_CERT},
#if defined(SPD_spmd)
- [SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
+ [SIP_SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
#endif
#endif /* ARM_IO_IN_DTB */
#endif /* TRUSTED_BOARD_BOOT */
@@ -184,9 +184,9 @@
open_fip
},
#if defined(SPD_spmd)
- [SP_CONTENT_CERT_ID] = {
+ [SIP_SP_CONTENT_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&arm_uuid_spec[SP_CONTENT_CERT_ID],
+ (uintptr_t)&arm_uuid_spec[SIP_SP_CONTENT_CERT_ID],
open_fip
},
#endif
@@ -233,7 +233,7 @@
{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
#if defined(SPD_spmd)
- {SP_CONTENT_CERT_ID, "sp_content_cert_uuid"},
+ {SIP_SP_CONTENT_CERT_ID, "sip_sp_content_cert_uuid"},
#endif
#endif /* TRUSTED_BOARD_BOOT */
};
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
index 64e873e..4459264 100644
--- a/plat/arm/common/fconf/arm_fconf_sp.c
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -30,7 +30,7 @@
union uuid_helper_t uuid_helper;
unsigned int index = 0;
uint32_t val32;
- const unsigned int sp_start_index = SP_CONTENT_CERT_ID + 1;
+ const unsigned int sp_start_index = SP_PKG1_ID;
/* As libfdt use void *, we can't avoid this cast */
const void *dtb = (void *)config;
@@ -45,6 +45,11 @@
}
fdt_for_each_subnode(sp_node, dtb, node) {
+ if (index == MAX_SP_IDS) {
+ ERROR("FCONF: Reached max number of SPs\n");
+ return -1;
+ }
+
err = fdt_read_uint32_array(dtb, sp_node, "uuid", 4,
uuid_helper.word);
if (err < 0) {
@@ -87,15 +92,10 @@
policies[sp_start_index + index].check = open_fip;
index++;
-
- if (index >= MAX_SP_IDS) {
- ERROR("FCONF: reached max number of SPs\n");
- return -1;
- }
}
if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
- ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
+ ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node);
return sp_node;
}
diff --git a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
index e416540..54b2423 100644
--- a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
+++ b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
@@ -8,7 +8,7 @@
/ {
/* Platform Config */
- plat_arm_bl2 {
+ tb_fw-config {
compatible = "arm,tb_fw";
hw_config_addr = <0x0 0x83000000>;
hw_config_max_size = <0x01000000>;
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index 5733781..2baa29a 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -27,7 +27,9 @@
#pragma weak bl1_plat_fwu_done
#pragma weak bl1_plat_handle_pre_image_load
#pragma weak bl1_plat_handle_post_image_load
-
+#if MEASURED_BOOT
+#pragma weak bl1_plat_set_bl2_hash
+#endif
unsigned int bl1_plat_get_next_image_id(void)
{
@@ -116,3 +118,12 @@
(void *) bl2_tzram_layout);
return 0;
}
+
+#if MEASURED_BOOT
+/*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+}
+#endif
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index d38fc6f..89b77ba 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -11,6 +11,7 @@
#include <common/debug.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
#include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
#include <smccc_helpers.h>
#include <tools_share/firmware_encrypted.h>
@@ -25,6 +26,7 @@
#pragma weak bl2_plat_handle_post_image_load
#pragma weak plat_try_next_boot_source
#pragma weak plat_get_enc_key_info
+#pragma weak plat_is_smccc_feature_available
#pragma weak plat_get_soc_version
#pragma weak plat_get_soc_revision
@@ -38,6 +40,11 @@
return SMC_ARCH_CALL_NOT_SUPPORTED;
}
+int32_t plat_is_smccc_feature_available(u_register_t fid __unused)
+{
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
void bl2_el3_plat_prepare_exit(void)
{
}
diff --git a/plat/imx/common/imx_sip_handler.c b/plat/imx/common/imx_sip_handler.c
index 62048b6..f9f5577 100644
--- a/plat/imx/common/imx_sip_handler.c
+++ b/plat/imx/common/imx_sip_handler.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <arch.h>
#include <stdlib.h>
#include <stdint.h>
#include <services/std_svc.h>
@@ -12,6 +13,7 @@
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <imx_sip_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
#include <sci/sci.h>
#if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
@@ -185,3 +187,37 @@
return ret;
}
+
+int imx_kernel_entry_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ static entry_point_info_t bl33_image_ep_info;
+ entry_point_info_t *next_image_info;
+ unsigned int mode;
+
+ if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000))
+ return SMC_UNK;
+
+ mode = MODE32_svc;
+
+ next_image_info = &bl33_image_ep_info;
+
+ next_image_info->pc = x1;
+
+ next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+
+ next_image_info->args.arg0 = 0;
+ next_image_info->args.arg1 = 0;
+ next_image_info->args.arg2 = x3;
+
+ SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+ cm_init_my_context(next_image_info);
+ cm_prepare_el3_exit(NON_SECURE);
+
+ return 0;
+}
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 4893b9f..20e1479 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -26,6 +26,9 @@
u_register_t flags)
{
switch (smc_fid) {
+ case IMX_SIP_AARCH32:
+ SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4));
+ break;
#if defined(PLAT_imx8mq)
case IMX_SIP_GET_SOC_INFO:
SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 5898f7a..0a2d750 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -28,6 +28,11 @@
#define IMX_SIP_MISC_SET_TEMP 0xC200000C
+#define IMX_SIP_AARCH32 0xC20000FD
+
+int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4);
#if defined(PLAT_imx8mq)
int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3);
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index e4338b9..0804135 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -8,6 +8,8 @@
#include <arch_helpers.h>
#include <assert.h>
#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <services/arm_arch_svc.h>
#include <tegra_def.h>
#include <tegra_platform.h>
#include <tegra_private.h>
@@ -286,3 +288,21 @@
{
return (int32_t)((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor());
}
+
+/*****************************************************************************
+ * plat_smccc_feature_available() - This function checks whether SMCCC feature
+ * is availabile for the platform or not.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 27ba6f7..7076a71 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -196,4 +196,11 @@
******************************************************************************/
#define PLAT_PCPU_DATA_SIZE 2
+/*******************************************************************************
+ * Number of parallel entry slots in SMT SCMI server entry context. For this
+ * platform, SCMI server is reached through SMC only, hence the number of
+ * entry slots.
+ ******************************************************************************/
+#define PLAT_SMT_ENTRY_COUNT PLATFORM_CORE_COUNT
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index 2da64ac..b6cb91e 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -22,4 +22,6 @@
void stm32mp1_syscfg_disable_io_compensation(void);
uint32_t stm32mp_get_ddr_ns_size(void);
+
+void stm32mp1_init_scmi_server(void);
#endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
index b872758..57240bc 100644
--- a/plat/st/stm32mp1/include/stm32mp1_smc.h
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -29,6 +29,16 @@
*/
#define STM32_SMC_BSEC 0x82001003
+/*
+ * STM32_SIP_SMC_SCMI_AGENT0
+ * STM32_SIP_SMC_SCMI_AGENT1
+ * Process SCMI message pending in SCMI shared memory buffer.
+ *
+ * Argument a0: (input) SMCC ID
+ */
+#define STM32_SIP_SMC_SCMI_AGENT0 0x82002000
+#define STM32_SIP_SMC_SCMI_AGENT1 0x82002001
+
/* SMC function IDs for SiP Service queries */
#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
#define STM32_SIP_SVC_UID 0x8200ff01
@@ -40,7 +50,7 @@
#define STM32_SIP_SVC_VERSION_MINOR 0x1
/* Number of STM32 SiP Calls implemented */
-#define STM32_COMMON_SIP_NUM_CALLS 4
+#define STM32_COMMON_SIP_NUM_CALLS 3
/* Service for BSEC */
#define STM32_SMC_READ_SHADOW 0x01
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
index 72af9ff..49375a6 100644
--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -9,6 +9,7 @@
#include <common/debug.h>
#include <common/runtime_svc.h>
+#include <drivers/st/scmi-msg.h>
#include <lib/psci/psci.h>
#include <tools_share/uuid.h>
@@ -65,6 +66,13 @@
ret2_enabled = true;
break;
+ case STM32_SIP_SMC_SCMI_AGENT0:
+ scmi_smt_fastcall_smc_entry(0);
+ break;
+ case STM32_SIP_SMC_SCMI_AGENT1:
+ scmi_smt_fastcall_smc_entry(1);
+ break;
+
default:
WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
ret1 = SMC_UNK;
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index 7327eef..5d7d495 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -25,9 +25,17 @@
# Generic PSCI
BL32_SOURCES += plat/common/plat_psci_common.c
+# SCMI server drivers
+BL32_SOURCES += drivers/st/scmi-msg/base.c \
+ drivers/st/scmi-msg/clock.c \
+ drivers/st/scmi-msg/entry.c \
+ drivers/st/scmi-msg/reset_domain.c \
+ drivers/st/scmi-msg/smt.c
+
# stm32mp1 specific services
BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
- plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+ plat/st/stm32mp1/services/stm32mp1_svc_setup.c \
+ plat/st/stm32mp1/stm32mp1_scmi.c
# Arm Archtecture services
BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 9b4c2d2..b639fcb 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -197,6 +197,8 @@
}
stm32mp_lock_periph_registering();
+
+ stm32mp1_init_scmi_server();
}
void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index bce5994..ea18a30 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -62,6 +62,9 @@
STM32MP_SYSRAM_SIZE - \
STM32MP_NS_SYSRAM_SIZE)
+#define STM32MP_SCMI_NS_SHM_BASE STM32MP_NS_SYSRAM_BASE
+#define STM32MP_SCMI_NS_SHM_SIZE STM32MP_NS_SYSRAM_SIZE
+
#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE
#define STM32MP_SEC_SYSRAM_SIZE (STM32MP_SYSRAM_SIZE - \
STM32MP_NS_SYSRAM_SIZE)
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
new file mode 100644
index 0000000..80faf0c
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+
+#define TIMEOUT_US_1MS 1000U
+
+#define SCMI_CLOCK_NAME_SIZE 16U
+#define SCMI_RSTD_NAME_SIZE 16U
+
+/*
+ * struct stm32_scmi_clk - Data for the exposed clock
+ * @clock_id: Clock identifier in RCC clock driver
+ * @name: Clock string ID exposed to agent
+ * @enabled: State of the SCMI clock
+ */
+struct stm32_scmi_clk {
+ unsigned long clock_id;
+ const char *name;
+ bool enabled;
+};
+
+/*
+ * struct stm32_scmi_rstd - Data for the exposed reset controller
+ * @reset_id: Reset identifier in RCC reset driver
+ * @name: Reset string ID exposed to agent
+ */
+struct stm32_scmi_rstd {
+ unsigned long reset_id;
+ const char *name;
+};
+
+/* Locate all non-secure SMT message buffers in last page of SYSRAM */
+#define SMT_BUFFER_BASE STM32MP_SCMI_NS_SHM_BASE
+#define SMT_BUFFER0_BASE SMT_BUFFER_BASE
+#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200)
+
+CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >=
+ (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE),
+ assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size);
+
+static struct scmi_msg_channel scmi_channel[] = {
+ [0] = {
+ .shm_addr = SMT_BUFFER0_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+ [1] = {
+ .shm_addr = SMT_BUFFER1_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+ return &scmi_channel[agent_id];
+}
+
+#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
+ [_scmi_id] = { \
+ .clock_id = _id, \
+ .name = _name, \
+ .enabled = _init_enabled, \
+ }
+
+static struct stm32_scmi_clk stm32_scmi0_clock[] = {
+ CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
+ CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
+ CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
+ CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
+ CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
+ CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
+ CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
+ CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
+ CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
+ CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
+ CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
+ CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
+ CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
+ CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
+ CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
+ CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
+ CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
+ CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
+ CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
+ CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
+ CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
+};
+
+static struct stm32_scmi_clk stm32_scmi1_clock[] = {
+ CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
+ CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
+ CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
+};
+
+#define RESET_CELL(_scmi_id, _id, _name) \
+ [_scmi_id] = { \
+ .reset_id = _id, \
+ .name = _name, \
+ }
+
+static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
+ RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
+ RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
+ RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
+ RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
+ RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
+ RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
+ RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
+ RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
+ RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
+ RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
+ RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+};
+
+struct scmi_agent_resources {
+ struct stm32_scmi_clk *clock;
+ size_t clock_count;
+ struct stm32_scmi_rstd *rstd;
+ size_t rstd_count;
+};
+
+static const struct scmi_agent_resources agent_resources[] = {
+ [0] = {
+ .clock = stm32_scmi0_clock,
+ .clock_count = ARRAY_SIZE(stm32_scmi0_clock),
+ .rstd = stm32_scmi0_reset_domain,
+ .rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
+ },
+ [1] = {
+ .clock = stm32_scmi1_clock,
+ .clock_count = ARRAY_SIZE(stm32_scmi1_clock),
+ },
+};
+
+static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(agent_resources));
+
+ return &agent_resources[agent_id];
+}
+
+#if ENABLE_ASSERTIONS
+static size_t plat_scmi_protocol_count_paranoid(void)
+{
+ unsigned int n = 0U;
+ unsigned int count = 0U;
+
+ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+ if (agent_resources[n].clock_count) {
+ count++;
+ break;
+ }
+ }
+
+ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+ if (agent_resources[n].rstd_count) {
+ count++;
+ break;
+ }
+ }
+
+ return count;
+}
+#endif
+
+static const char vendor[] = "ST";
+static const char sub_vendor[] = "";
+
+const char *plat_scmi_vendor_name(void)
+{
+ return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+ return sub_vendor;
+}
+
+/* Currently supporting Clocks and Reset Domains */
+static const uint8_t plat_protocol_list[] = {
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_PROTOCOL_ID_RESET_DOMAIN,
+ 0U /* Null termination */
+};
+
+size_t plat_scmi_protocol_count(void)
+{
+ const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
+
+ assert(count == plat_scmi_protocol_count_paranoid());
+
+ return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
+{
+ assert(plat_scmi_protocol_count_paranoid() ==
+ (ARRAY_SIZE(plat_protocol_list) - 1U));
+
+ return plat_protocol_list;
+}
+
+/*
+ * Platform SCMI clocks
+ */
+static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+ size_t n = 0U;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->clock_count; n++) {
+ if (n == scmi_id) {
+ return &resource->clock[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+ if (resource == NULL) {
+ return 0U;
+ }
+
+ return resource->clock_count;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return NULL;
+ }
+
+ return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+ unsigned long *array, size_t *nb_elts)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if (clock == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (array == NULL) {
+ *nb_elts = 1U;
+ } else if (*nb_elts == 1U) {
+ *array = stm32mp_clk_get_rate(clock->clock_id);
+ } else {
+ return SCMI_GENERIC_ERROR;
+ }
+
+ return SCMI_SUCCESS;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return 0U;
+ }
+
+ return stm32mp_clk_get_rate(clock->clock_id);
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return 0U;
+ }
+
+ return (int32_t)clock->enabled;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool enable_not_disable)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if (clock == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (enable_not_disable) {
+ if (!clock->enabled) {
+ VERBOSE("SCMI clock %u enable\n", scmi_id);
+ stm32mp_clk_enable(clock->clock_id);
+ clock->enabled = true;
+ }
+ } else {
+ if (clock->enabled) {
+ VERBOSE("SCMI clock %u disable\n", scmi_id);
+ stm32mp_clk_disable(clock->clock_id);
+ clock->enabled = false;
+ }
+ }
+
+ return SCMI_SUCCESS;
+}
+
+/*
+ * Platform SCMI reset domains
+ */
+static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+ size_t n;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->rstd_count; n++) {
+ if (n == scmi_id) {
+ return &resource->rstd[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return NULL;
+ }
+
+ return rstd->name;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+ if (resource == NULL) {
+ return 0U;
+ }
+
+ return resource->rstd_count;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+ uint32_t state)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+ return SCMI_DENIED;
+ }
+
+ /* Supports only reset with context loss */
+ if (state != 0U) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
+
+ if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
+ return SCMI_HARDWARE_ERROR;
+ }
+
+ if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
+ return SCMI_HARDWARE_ERROR;
+ }
+
+ return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool assert_not_deassert)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (assert_not_deassert) {
+ VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
+ stm32mp_reset_set(rstd->reset_id);
+ } else {
+ VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
+ stm32mp_reset_release(rstd->reset_id);
+ }
+
+ return SCMI_SUCCESS;
+}
+
+/*
+ * Initialize platform SCMI resources
+ */
+void stm32mp1_init_scmi_server(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
+ scmi_smt_init_agent_channel(&scmi_channel[i]);
+ }
+
+ for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
+ const struct scmi_agent_resources *res = &agent_resources[i];
+ size_t j;
+
+ for (j = 0U; j < res->clock_count; j++) {
+ struct stm32_scmi_clk *clk = &res->clock[j];
+
+ if ((clk->name == NULL) ||
+ (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
+ ERROR("Invalid SCMI clock name\n");
+ panic();
+ }
+
+ /* Sync SCMI clocks with their targeted initial state */
+ if (clk->enabled &&
+ stm32mp_nsec_can_access_clock(clk->clock_id)) {
+ stm32mp_clk_enable(clk->clock_id);
+ }
+ }
+
+ for (j = 0U; j < res->rstd_count; j++) {
+ struct stm32_scmi_rstd *rstd = &res->rstd[j];
+
+ if ((rstd->name == NULL) ||
+ (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
+ ERROR("Invalid SCMI reset domain name\n");
+ panic();
+ }
+ }
+ }
+}
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 588656d..37bfc62 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -24,8 +24,9 @@
switch (arg1) {
case SMCCC_VERSION:
case SMCCC_ARCH_FEATURES:
+ return SMC_ARCH_CALL_SUCCESS;
case SMCCC_ARCH_SOC_ID:
- return SMC_OK;
+ return plat_is_smccc_feature_available(arg1);
#if WORKAROUND_CVE_2017_5715
case SMCCC_ARCH_WORKAROUND_1:
if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)