Merge "Initialize platform for MediaTek mt8192" into integration
diff --git a/Makefile b/Makefile
index bc5604b..f4589d9 100644
--- a/Makefile
+++ b/Makefile
@@ -121,6 +121,10 @@
# Extend the signing to include leaf functions
BP_OPTION := pac-ret+leaf
ENABLE_PAUTH := 1
+else ifeq (${BRANCH_PROTECTION},4)
+ # Turn on branch target identification mechanism
+ BP_OPTION := bti
+ ENABLE_BTI := 1
else
$(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION})
endif
@@ -193,10 +197,8 @@
# Memory tagging is supported in architecture Armv8.5-A AArch64 and onwards
ifeq ($(ARCH), aarch64)
-ifeq ($(shell test $(ARM_ARCH_MAJOR) -gt 8; echo $$?),0)
-mem_tag_arch_support = yes
-else ifeq ($(shell test $(ARM_ARCH_MAJOR) -eq 8 -a $(ARM_ARCH_MINOR) -ge 5; \
- echo $$?),0)
+# Check if revision is greater than or equal to 8.5
+ifeq "8.5" "$(word 1, $(sort 8.5 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
mem_tag_arch_support = yes
endif
endif
@@ -449,8 +451,10 @@
include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
-BUILD_BASE := ./build
-BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
+ifeq (${BUILD_BASE},)
+ BUILD_BASE := ./build
+endif
+BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${BUILD_TYPE}
SPDS := $(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*))))
@@ -482,6 +486,10 @@
$(error SPMD with SPM at S-EL2 requires CTX_INCLUDE_EL2_REGS option)
endif
endif
+
+ ifeq ($(findstring optee_sp,$(ARM_SPMC_MANIFEST_DTS)),optee_sp)
+ DTC_CPPFLAGS += -DOPTEE_SP_FW_CONFIG
+ endif
else
# All other SPDs in spd directory
SPD_DIR := spd
@@ -657,6 +665,10 @@
SDEI_SUPPORT is enabled")
endif
+ifeq ($(COT_DESC_IN_DTB),1)
+ $(info CoT in device tree is an experimental feature)
+endif
+
# If pointer authentication is used in the firmware, make sure that all the
# registers associated to it are also saved and restored.
# Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1.
@@ -901,6 +913,7 @@
$(eval $(call assert_boolean,ENCRYPT_BL32))
$(eval $(call assert_boolean,ERRATA_SPECULATIVE_AT))
$(eval $(call assert_boolean,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call assert_boolean,COT_DESC_IN_DTB))
$(eval $(call assert_numeric,ARM_ARCH_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -981,6 +994,7 @@
$(eval $(call add_define,USE_SPINLOCK_CAS))
$(eval $(call add_define,ERRATA_SPECULATIVE_AT))
$(eval $(call add_define,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call add_define,COT_DESC_IN_DTB))
ifeq (${SANITIZE_UB},trap)
$(eval $(call add_define,MONITOR_TRAPS))
@@ -1193,7 +1207,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}
@@ -1259,7 +1273,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_el3.ld.S b/bl2/bl2_el3.ld.S
index 8c45d98..bc1794c 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -105,17 +105,7 @@
__DATA_RAM_START__ = __DATA_START__;
__DATA_RAM_END__ = __DATA_END__;
- /*
- * .rela.dyn needs to come after .data for the read-elf utility to parse
- * this section correctly. Ensure 8-byte alignment so that the fields of
- * RELA data structure are aligned.
- */
- . = ALIGN(8);
- __RELA_START__ = .;
- .rela.dyn . : {
- } >RAM
- __RELA_END__ = .;
-
+ RELA_SECTION >RAM
STACK_SECTION >RAM
BSS_SECTION >RAM
XLAT_TABLE_SECTION >RAM
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/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 11e86a3..5026500 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -115,17 +115,7 @@
__RW_START__ = . ;
DATA_SECTION >RAM
-
- /*
- * .rela.dyn needs to come after .data for the read-elf utility to parse
- * this section correctly. Ensure 8-byte alignment so that the fields of
- * RELA data structure are aligned.
- */
- . = ALIGN(8);
- __RELA_START__ = .;
- .rela.dyn . : {
- } >RAM
- __RELA_END__ = .;
+ RELA_SECTION >RAM
#ifdef BL31_PROGBITS_LIMIT
ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.")
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index bdcd2cf..d86ae55 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -71,17 +71,7 @@
__RW_START__ = . ;
DATA_SECTION >RAM
-
- /*
- * .rela.dyn needs to come after .data for the read-elf utility to parse
- * this section correctly. Ensure 8-byte alignment so that the fields of
- * RELA data structure are aligned.
- */
- . = ALIGN(8);
- __RELA_START__ = .;
- .rela.dyn . : {
- } >RAM
- __RELA_END__ = .;
+ RELA_SECTION >RAM
#ifdef TSP_PROGBITS_LIMIT
ASSERT(. <= TSP_PROGBITS_LIMIT, "TSP progbits has exceeded its limit.")
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index bf29186..0014d3b 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -21,7 +21,7 @@
:G: `soby-mathew`_
:M: Sandrine Bailleux <sandrine.bailleux@arm.com>
:G: `sandrine-bailleux-arm`_
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
:G: `AlexeiFedorov`_
:M: Manish Pandey <manish.pandey2@arm.com>
:G: `manish-pandey-arm`_
@@ -60,6 +60,14 @@
:M: Etienne Carriere <etienne.carriere@linaro.org>
:G: `etienne-lms`_
+Build Definitions for CMake Build System
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:M: Jack Bond-Preston <Jack.Bond-Preston@arm.com>
+:G: `jackbondpreston-arm`_
+:F: /
+
Software Delegated Exception Interface (SDEI)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:M: Mark Dykes <mark.dykes@arm.com>
@@ -185,7 +193,7 @@
Activity Monitors Unit (AMU) extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
:G: `AlexeiFedorov`_
:F: lib/extensions/amu/
@@ -199,7 +207,7 @@
Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
:G: `AlexeiFedorov`_
:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
:G: `zelalem-aweke`_
@@ -221,7 +229,7 @@
Standard C library
^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
:G: `AlexeiFedorov`_
:M: John Powell <John.Powell@arm.com>
:G: `john-powell-arm`_
@@ -251,7 +259,7 @@
GIC driver
^^^^^^^^^^
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
:G: `AlexeiFedorov`_
:M: Manish Pandey <manish.pandey2@arm.com>
:G: `manish-pandey-arm`_
@@ -277,6 +285,15 @@
:F: include/drivers/io/io_encrypted.h
:F: include/tools_share/firmware_encrypted.h
+Measured Boot
+^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: drivers/measured_boot
+:F: include/drivers/measured_boot
+:F: plat/arm/board/fvp/fvp_measured_boot.c
Platform Ports
~~~~~~~~~~~~~~
@@ -320,6 +337,14 @@
:F: docs/plat/meson-axg.rst
:F: plat/amlogic/axg/
+Arm FPGA platform port
+^^^^^^^^^^^^^^^^^^^^^^
+:M: Andre Przywara <andre.przywara@arm.com>
+:G: `Andre-ARM`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: plat/arm/board/arm_fpga
+
Arm System Guidance for Infrastructure / Mobile FVP platforms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:M: Nariman Poushin <nariman.poushin@linaro.org>
@@ -613,6 +638,6 @@
.. _madhukar-Arm: https://github.com/madhukar-Arm
.. _john-powell-arm: https://github.com/john-powell-arm
.. _raghuncstate: https://github.com/raghuncstate
-
+.. _jackbondpreston-arm: https://github.com/jackbondpreston-arm
.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
new file mode 100644
index 0000000..46915db
--- /dev/null
+++ b/docs/components/cot-binding.rst
@@ -0,0 +1,328 @@
+Chain of trust bindings
+=======================
+
+The device tree allows to describe the chain of trust with the help of
+'cot' node which contain 'manifests' and 'images' as sub-nodes.
+'manifests' and 'images' nodes contains number of sub-nodes (i.e. 'certificate'
+and 'image' nodes) mentioning properties of the certificate and image respectively.
+
+Also, device tree describes 'non-volatile-counters' node which contains number of
+sub-nodes mentioning properties of all non-volatile-counters used in the chain of trust.
+
+cot
+------------------------------------------------------------------
+This is root node which contains 'manifests' and 'images' as sub-nodes
+
+
+Manifests and Certificate node bindings definition
+----------------------------------------------------------------
+
+- Manifests node
+ Description: Container of certificate nodes.
+
+ PROPERTIES
+
+ - compatible:
+ Usage: required
+
+ Value type: <string>
+
+ Definition: must be "arm, cert-descs"
+
+- Certificate node
+ Description:
+
+ Describes certificate properties which are used
+ during the authentication process.
+
+ PROPERTIES
+
+ - root-certificate
+ Usage:
+
+ Required for the certificate with no parent.
+ In other words, certificates which are validated
+ using root of trust public key.
+
+ Value type: <boolean>
+
+ - image-id
+ Usage: Required for every certificate with unique id.
+
+ Value type: <u32>
+
+ - parent
+ Usage:
+
+ It refers to their parent image, which typically contains
+ information to authenticate the certificate.
+ This property is required for all non-root certificates.
+
+ This property is not required for root-certificates
+ as root-certificates are validated using root of trust
+ public key provided by platform.
+
+ Value type: <phandle>
+
+ - signing-key
+ Usage:
+
+ This property is used to refer public key node present in
+ parent certificate node and it is required property for all
+ non-root certificates which are authenticated using public-key
+ present in parent certificate.
+
+ This property is not required for root-certificates
+ as root-certificates are validated using root of trust
+ public key provided by platform.
+
+ Value type: <phandle>
+
+ - antirollback-counter
+ Usage:
+
+ This property is used by all certificates which are
+ protected against rollback attacks using a non-volatile
+ counter and it is an optional property.
+
+ This property is used to refer one of the non-volatile
+ counter sub-node present in 'non-volatile counters' node.
+
+ Value type: <phandle>
+
+
+ SUBNODES
+ - Description:
+
+ Hash and public key information present in the certificate
+ are shown by these nodes.
+
+ - public key node
+ Description: Provide public key information in the certificate.
+
+ PROPERTIES
+
+ - oid
+ Usage:
+
+ This property provides the Object ID of public key
+ provided in the certificate which the help of which
+ public key information can be extracted.
+
+ Value type: <string>
+
+ - hash node
+ Description: Provide the hash information in the certificate.
+
+ PROPERTIES
+
+ - oid
+ Usage:
+
+ This property provides the Object ID of hash provided in
+ the certificate which the help of which hash information
+ can be extracted.
+
+ Value type: <string>
+
+Example:
+
+.. code:: c
+
+ cot {
+ manifests {
+ compatible = "arm, cert-descs”
+
+ trusted-key-cert: trusted-key-cert {
+ root-certificate;
+ image-id = <TRUSTED_KEY_CERT_ID>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ trusted-world-pk: trusted-world-pk {
+ oid = TRUSTED_WORLD_PK_OID;
+ };
+ non-trusted-world-pk: non-trusted-world-pk {
+ oid = NON_TRUSTED_WORLD_PK_OID;
+ };
+ };
+
+ scp_fw_key_cert: scp_fw_key_cert {
+ image-id = <SCP_FW_KEY_CERT_ID>;
+ parent = <&trusted-key-cert>;
+ signing-key = <&trusted_world_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ scp_fw_content_pk: scp_fw_content_pk {
+ oid = SCP_FW_CONTENT_CERT_PK_OID;
+ };
+ };
+ .
+ .
+ .
+
+ next-certificate {
+
+ };
+ };
+ };
+
+Images and Image node bindings definition
+-----------------------------------------
+
+- Images node
+ Description: Container of image nodes
+
+ PROPERTIES
+
+ - compatible:
+ Usage: required
+
+ Value type: <string>
+
+ Definition: must be "arm, img-descs"
+
+- Image node
+ Description:
+
+ Describes image properties which will be used during
+ authentication process.
+
+ PROPERTIES
+
+ - image-id
+ Usage: Required for every image with unique id.
+
+ Value type: <u32>
+
+ - parent
+ Usage:
+
+ Required for every image to provide a reference to
+ its parent image, which contains the necessary information
+ to authenticate it.
+
+ Value type: <phandle>
+
+ - hash
+ Usage:
+
+ Required for all images which are validated using
+ hash method. This property is used to refer hash
+ node present in parent certificate node.
+
+ Value type: <phandle>
+
+ Note:
+
+ Currently, all images are validated using 'hash'
+ method. In future, there may be multiple methods can
+ be used to validate the image.
+
+Example:
+
+.. code:: c
+
+ cot {
+ images {
+ compatible = "arm, img-descs";
+
+ scp_bl2_image {
+ image-id = <SCP_BL2_IMAGE_ID>;
+ parent = <&scp_fw_content_cert>;
+ hash = <&scp_fw_hash>;
+ };
+
+ .
+ .
+ .
+
+ next-img {
+
+ };
+ };
+ };
+
+non-volatile counter node binding definition
+--------------------------------------------
+
+- non-volatile counters node
+ Description: Contains properties for non-volatile counters.
+
+ PROPERTIES
+
+ - compatible:
+ Usage: required
+
+ Value type: <string>
+
+ Definition: must be "arm, non-volatile-counter"
+
+ - #address-cells
+ Usage: required
+
+ Value type: <u32>
+
+ Definition:
+
+ Must be set according to address size
+ of non-volatile counter register
+
+ - #size-cells
+ Usage: required
+
+ Value type: <u32>
+
+ Definition: must be set to 0
+
+ SUBNODE
+ - counters node
+ Description: Contains various non-volatile counters present in the platform.
+
+ PROPERTIES
+
+ - reg
+ Usage:
+
+ Register base address of non-volatile counter and it is required
+ property.
+
+ Value type: <u32>
+
+ - oid
+ Usage:
+
+ This property provides the Object ID of non-volatile counter
+ provided in the certificate and it is required property.
+
+ Value type: <string>
+
+Example:
+Below is non-volatile counters example for ARM platform
+
+.. code:: c
+
+ non-volatile-counters {
+ compatible = "arm, non-volatile-counter";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ counters {
+ trusted-nv-counter: trusted_nv_counter {
+ reg = <TFW_NVCTR_BASE>;
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+ non_trusted_nv_counter: non_trusted_nv_counter {
+ reg = <NTFW_CTR_BASE>;
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+
+ };
+ };
+ };
+
+Future update to chain of trust binding
+---------------------------------------
+
+This binding document needs to be revisited to generalise some terminologies
+which are currently specific to X.509 certificates for e.g. Object IDs.
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/docs/components/debugfs-design.rst b/docs/components/debugfs-design.rst
index 2096bdb..2536515 100644
--- a/docs/components/debugfs-design.rst
+++ b/docs/components/debugfs-design.rst
@@ -80,8 +80,8 @@
The communication with the 9p layer in BL31 is made through an SMC conduit
(`SMC Calling Convention`_), using a specific SiP Function Id. An NS
shared buffer is used to pass path string parameters, or e.g. to exchange
-data on a read operation. Refer to `ARM SiP Services`_ for a description
-of the SMC interface.
+data on a read operation. Refer to :ref:`ARM SiP Services <arm sip services>`
+for a description of the SMC interface.
Security considerations
-----------------------
diff --git a/docs/components/exception-handling.rst b/docs/components/exception-handling.rst
index 4cca5f4..86ed87c 100644
--- a/docs/components/exception-handling.rst
+++ b/docs/components/exception-handling.rst
@@ -10,13 +10,9 @@
- Asynchronous External Aborts
|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is
-described in the `Firmware Design document`__. However, the |EHF| changes the
-semantics of `interrupt handling`__ and `synchronous exceptions`__ other than
-SMCs.
-
-.. __: firmware-design.rst#handling-an-smc
-.. __: `Interrupt handling`_
-.. __: `Effect on SMC calls`_
+described in the :ref:`Firmware Design document <handling-an-smc>`. However, the
+|EHF| changes the semantics of `Interrupt handling`_ and :ref:`synchronous
+exceptions <Effect on SMC calls>` other than SMCs.
The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to
``1``, and is only available for AArch64 systems.
@@ -77,10 +73,9 @@
independently depending on platform choice and the nature of the exception
received.
-.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an
- EL3 component that operates in EL3 on behalf of Secure OS.
-
-.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers
+.. [#spd] Not to be confused with :ref:`Secure Payload Dispatcher
+ <firmware_design_sel1_spd>`, which is an EL3 component that operates in EL3
+ on behalf of Secure OS.
The role of Exception Handling Framework
----------------------------------------
@@ -139,6 +134,8 @@
the case; for non-interrupts, the |EHF| monitors and asserts this. See
`Transition of priority levels`_.
+.. _interrupt-handling:
+
Interrupt handling
------------------
@@ -151,15 +148,12 @@
sufficient priority are signalled as FIQs, and therefore will be routed to
EL3. As a result, S-EL1 software cannot expect to handle Non-secure
interrupts at S-EL1. Essentially, this deprecates the routing mode described
- as `CSS=0, TEL3=0`__.
-
- .. __: interrupt-framework-design.rst#el3-interrupts
+ as :ref:`CSS=0, TEL3=0 <EL3 interrupts>`.
In order for S-EL1 software to handle Non-secure interrupts while having
|EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts
- are received at EL3, but are then `synchronously`__ handled over to S-EL1.
-
- .. __: interrupt-framework-design.rst#secure-payload
+ are received at EL3, but are then :ref:`synchronously <sp-synchronous-int>`
+ handled over to S-EL1.
- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is
set to ``1`` so that *Group 0* interrupts target EL3.
@@ -176,6 +170,8 @@
Dispatchers are assigned interrupt priority levels in two steps:
+.. _Partitioning priority levels:
+
Partitioning priority levels
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -281,15 +277,13 @@
typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle,
void *cookie);
-The parameters are as obtained from the top-level `EL3 interrupt handler`__.
+The parameters are as obtained from the top-level :ref:`EL3 interrupt handler
+<el3-runtime-firmware>`.
-.. __: interrupt-framework-design.rst#el3-runtime-firmware
-
-The `SDEI dispatcher`__, for example, expects the platform to allocate two
-different priority levels—``PLAT_SDEI_CRITICAL_PRI``, and
-``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels.
-
-.. __: sdei.rst
+The :ref:`SDEI dispatcher<SDEI: Software Delegated Exception Interface>`, for
+example, expects the platform to allocate two different priority levels—
+``PLAT_SDEI_CRITICAL_PRI``, and ``PLAT_SDEI_NORMAL_PRI`` —and registers the
+same handler to handle both levels.
Interrupt handling example
--------------------------
@@ -365,16 +359,16 @@
See also the `Build-time flow`_ and the `Run-time flow`_.
+.. _Activating and Deactivating priorities:
+
Activating and Deactivating priorities
--------------------------------------
A priority level is said to be *active* when an exception of that priority is
being handled: for interrupts, this is implied when the interrupt is
-acknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit
-dispatches`__, this has to be done via calling ``ehf_activate_priority()``. See
-`Run-time flow`_.
-
-.. __: sdei.rst#explicit-dispatch-of-events
+acknowledged; for non-interrupt exceptions, such as SErrors or :ref:`SDEI
+explicit dispatches <explicit-dispatch-of-events>`, this has to be done via
+calling ``ehf_activate_priority()``. See `Run-time flow`_.
Conversely, when the dispatcher has reached a logical resolution for the cause
of the exception, the corresponding priority level ought to be deactivated. As
@@ -453,6 +447,8 @@
If these are violated, a panic will result.
+.. _Effect on SMC calls:
+
Effect on SMC calls
-------------------
@@ -538,10 +534,8 @@
interrupts belonging to different dispatchers.
#. The |EHF|, during its initialisation, registers a top-level interrupt handler
- with the `Interrupt Management Framework`__ for EL3 interrupts. This also
- results in setting the routing bits in ``SCR_EL3``.
-
- .. __: interrupt-framework-design.rst#el3-runtime-firmware
+ with the :ref:`Interrupt Management Framework<el3-runtime-firmware>` for EL3
+ interrupts. This also results in setting the routing bits in ``SCR_EL3``.
#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0
interrupt, and is taken to EL3.
diff --git a/docs/components/fconf/index.rst b/docs/components/fconf/index.rst
index 0da56ec..9020633 100644
--- a/docs/components/fconf/index.rst
+++ b/docs/components/fconf/index.rst
@@ -49,8 +49,10 @@
configuration properties which is usually a device tree file.
Example:
+ - FW_CONFIG: properties related to base address, maximum size and image id
+ of other DTBs etc.
- TB_FW: properties related to trusted firmware such as IO policies,
- base address of other DTBs, mbedtls heap info etc.
+ mbedtls heap info etc.
- HW_CONFIG: properties related to hardware configuration of the SoC
such as topology, GIC controller, PSCI hooks, CPU ID etc.
@@ -88,9 +90,10 @@
Loading the property device tree
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``fconf_load_config()`` must be called to load the device tree containing
-the properties' values. This must be done after the io layer is initialized, as
-the |DTB| is stored on an external device (FIP).
+The ``fconf_load_config(image_id)`` must be called to load fw_config and
+tb_fw_config devices tree containing the properties' values. This must be done
+after the io layer is initialized, as the |DTB| is stored on an external
+device (FIP).
.. uml:: ../../resources/diagrams/plantuml/fconf_bl1_load_config.puml
diff --git a/docs/components/index.rst b/docs/components/index.rst
index c5f6264..ffeef80 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -12,10 +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/platform-interrupt-controller-API.rst b/docs/components/platform-interrupt-controller-API.rst
index 9d02f45..069c87b 100644
--- a/docs/components/platform-interrupt-controller-API.rst
+++ b/docs/components/platform-interrupt-controller-API.rst
@@ -286,6 +286,8 @@
*Priority Mask Register*, and make sure memory updates are visible before
potential trigger due to mask update.
+.. _plat_ic_get_interrupt_id:
+
Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/components/ras.rst b/docs/components/ras.rst
index 86529d7..02207d8 100644
--- a/docs/components/ras.rst
+++ b/docs/components/ras.rst
@@ -9,10 +9,8 @@
paradigm for handling platform errors: exceptions resulting from errors are
routed to and handled in EL3. Said errors are Synchronous External Abort (SEA),
Asynchronous External Abort (signalled as SErrors), Fault Handling and Error
-Recovery interrupts. The |EHF| document mentions various `error handling
-use-cases`__.
-
-.. __: exception-handling.rst#delegation-use-cases
+Recovery interrupts. The |EHF| document mentions various :ref:`error handling
+use-cases <delegation-use-cases>` .
For the description of Arm RAS extensions, Standard Error Records, and the
precise definition of RAS terminology, please refer to the Arm Architecture
@@ -46,9 +44,7 @@
The RAS framework allows the platform to define handlers for External Abort,
Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please
-refer to the porting guide for the `RAS platform API descriptions`__.
-
-.. __: ../getting_started/porting-guide.rst#external-abort-handling-and-ras-support
+refer to :ref:`RAS Porting Guide <External Abort handling and RAS Support>`.
Registering RAS error records
-----------------------------
@@ -114,9 +110,8 @@
The ``data`` constant parameter describes the various properties of the error,
including the reason for the error, exception syndrome, and also ``flags``,
-``cookie``, and ``handle`` parameters from the `top-level exception handler`__.
-
-.. __: interrupt-framework-design.rst#el3-interrupts
+``cookie``, and ``handle`` parameters from the :ref:`top-level exception handler
+<EL3 interrupts>`.
The platform is expected populate an array using the macros above, and register
the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``,
@@ -229,21 +224,17 @@
As mentioned in earlier sections, RAS framework interacts with the |EHF| to
arbitrate handling of RAS exceptions with others that are routed to EL3. This
-means that the platform must partition a `priority level`__ for handling RAS
-exceptions. The platform must then define the macro ``PLAT_RAS_PRI`` to the
-priority level used for RAS exceptions. Platforms would typically want to
-allocate the highest secure priority for RAS handling.
+means that the platform must partition a :ref:`priority level <Partitioning
+priority levels>` for handling RAS exceptions. The platform must then define
+the macro ``PLAT_RAS_PRI`` to the priority level used for RAS exceptions.
+Platforms would typically want to allocate the highest secure priority for
+RAS handling.
-.. __: exception-handling.rst#partitioning-priority-levels
-
-Handling of both `interrupt`__ and `non-interrupt`__ exceptions follow the
-sequences outlined in the |EHF| documentation. I.e., for interrupts, the
-priority management is implicit; but for non-interrupt exceptions, they're
-explicit using `EHF APIs`__.
-
-.. __: exception-handling.rst#interrupt-flow
-.. __: exception-handling.rst#non-interrupt-flow
-.. __: exception-handling.rst#activating-and-deactivating-priorities
+Handling of both :ref:`interrupt <interrupt-flow>` and :ref:`non-interrupt
+<non-interrupt-flow>` exceptions follow the sequences outlined in the |EHF|
+documentation. I.e., for interrupts, the priority management is implicit; but
+for non-interrupt exceptions, they're explicit using :ref:`EHF APIs
+<Activating and Deactivating priorities>`.
--------------
diff --git a/docs/components/sdei.rst b/docs/components/sdei.rst
index c5275a0..60259c8 100644
--- a/docs/components/sdei.rst
+++ b/docs/components/sdei.rst
@@ -205,6 +205,8 @@
See the function ``sdei_client_el()`` in ``sdei_private.h``.
+.. _explicit-dispatch-of-events:
+
Explicit dispatch of events
---------------------------
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..d532901 100644
--- a/docs/components/secure-partition-manager-design.rst
+++ b/docs/components/secure-partition-manager-mm.rst
@@ -1,5 +1,20 @@
-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 (:ref:`Secure Partition Manager`).
+- SPM based on the MM interface.
+
+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..e09da53
--- /dev/null
+++ b/docs/components/secure-partition-manager.rst
@@ -0,0 +1,865 @@
+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] :ref:`Secure Partition Manager using MM interface<Secure Partition Manager (MM)>`
+
+.. _[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 591f2f8..6b6c639 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -227,6 +227,17 @@
- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76
CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
+- ``ERRATA_A76_1791580``: This applies errata 1791580 workaround to Cortex-A76
+ CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
+
+- ``ERRATA_A76_1800710``: This applies errata 1800710 workaround to Cortex-A76
+ CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
+
+For Cortex-A77, the following errata build flags are defined :
+
+- ``ERRATA_A77_1800714``: This applies errata 1800714 workaround to Cortex-A77
+ CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
+
For Cortex-A78, the following errata build flags are defined :
- ``ERRATA_A78_1688305``: This applies errata 1688305 workaround to Cortex-A78
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index b336b38..a357d58 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -83,6 +83,10 @@
platform. The Boot Loader stage may optionally specify a firmware
configuration file and/or hardware configuration file as listed below:
+- FW_CONFIG - The firmware configuration file. Holds properties shared across
+ all BLx images.
+ An example is the "dtb-registry" node, which contains the information about
+ the other device tree configurations (load-address, size, image_id).
- HW_CONFIG - The hardware configuration file. Can be shared by all Boot Loader
stages and also by the Normal World Rich OS.
- TB_FW_CONFIG - Trusted Boot Firmware configuration file. Shared between BL1
@@ -109,8 +113,8 @@
the generic hardware configuration is passed the next available argument.
For example,
- - If TB_FW_CONFIG is loaded by BL1, then its address is passed in ``arg0``
- to BL2.
+ - FW_CONFIG is loaded by BL1, then its address is passed in ``arg0`` to BL2.
+ - TB_FW_CONFIG address is retrieved by BL2 from FW_CONFIG device tree.
- If HW_CONFIG is loaded by BL1, then its address is passed in ``arg2`` to
BL2. Note, ``arg1`` is already used for meminfo_t.
- If SOC_FW_CONFIG is loaded by BL2, then its address is passed in ``arg1``
@@ -953,6 +957,8 @@
|Image 1|
+.. _handling-an-smc:
+
Handling an SMC
~~~~~~~~~~~~~~~
@@ -984,7 +990,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
----------------------------------
@@ -1296,6 +1302,8 @@
already been performed and act as appropriate. Possible courses of actions are,
e.g. skip the action the second time, or undo/redo it.
+.. _configuring-secure-interrupts:
+
Configuring secure interrupts
-----------------------------
@@ -1732,7 +1740,7 @@
``bl2_mem_params_descs`` contains parameters passed from BL2 to next the
BL image during boot.
-``fw_configs`` includes soc_fw_config, tos_fw_config and tb_fw_config.
+``fw_configs`` includes soc_fw_config, tos_fw_config, tb_fw_config and fw_config.
**FVP with TSP in Trusted SRAM with firmware configs :**
(These diagrams only cover the AArch64 case)
@@ -1757,7 +1765,7 @@
| | <<<<<<<<<<<<< | BL31 PROGBITS |
| | <<<<<<<<<<<<< |----------------|
| | <<<<<<<<<<<<< | BL32 |
- 0x04002000 +----------+ +----------------+
+ 0x04003000 +----------+ +----------------+
| CONFIG |
0x04001000 +----------+
| Shared |
@@ -1794,7 +1802,7 @@
|--------------| <<<<<<<<<<<<< |----------------|
| | <<<<<<<<<<<<< | BL31 PROGBITS |
| | +----------------+
- +--------------+
+ 0x04003000 +--------------+
| CONFIG |
0x04001000 +--------------+
| Shared |
@@ -1828,7 +1836,7 @@
|----------| <<<<<<<<<<<<< |----------------|
| | <<<<<<<<<<<<< | BL31 PROGBITS |
| | +----------------+
- 0x04002000 +----------+
+ 0x04003000 +----------+
| CONFIG |
0x04001000 +----------+
| Shared |
diff --git a/docs/design/interrupt-framework-design.rst b/docs/design/interrupt-framework-design.rst
index 14f7227..dfb2eac 100644
--- a/docs/design/interrupt-framework-design.rst
+++ b/docs/design/interrupt-framework-design.rst
@@ -138,6 +138,8 @@
reason to route the interrupt to EL3 software and then hand it back to
non-secure software for handling.
+.. _EL3 interrupts:
+
EL3 interrupts
^^^^^^^^^^^^^^
@@ -148,10 +150,8 @@
However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is
invalid as EL3 interrupts are unconditionally routed to EL3, and EL3
- interrupts will always preempt Secure EL1/EL0 execution. See `exception
- handling`__ documentation.
-
- .. __: exception-handling.rst#interrupt-handling
+ interrupts will always preempt Secure EL1/EL0 execution. See :ref:`exception
+ handling<interrupt-handling>` documentation.
#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in
Secure-EL1/Secure-EL0. This is a valid routing model as secure software
@@ -301,6 +301,8 @@
`Software components`_) during the registration of a handler for an interrupt
type.
+.. _el3-runtime-firmware:
+
EL3 runtime firmware
~~~~~~~~~~~~~~~~~~~~
@@ -899,14 +901,14 @@
|Image 2|
-Secure payload
-~~~~~~~~~~~~~~
+.. _sp-synchronous-int:
+
+Secure payload interrupt handling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The SP should implement one or both of the synchronous and asynchronous
interrupt handling models depending upon the interrupt routing model it has
-chosen (as described in section `Secure Payload`__).
-
-.. __: #sp-int-registration
+chosen (as described in section :ref:`Secure Payload <sp-int-registration>`).
In the synchronous model, it should begin handling a Secure-EL1 interrupt after
receiving control from the SPD service at an entrypoint agreed upon during build
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index f207886..0acc886 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -88,6 +88,7 @@
- 1: Enables all types of branch protection features
- 2: Return address signing to its standard level
- 3: Extend the signing to include leaf functions
+- 4: Turn on branch target identification mechanism
The table below summarizes ``BRANCH_PROTECTION`` values, GCC compilation options
and resulting PAuth/BTI features.
@@ -103,6 +104,8 @@
+-------+--------------+-------+-----+
| 3 | pac-ret+leaf | Y | N |
+-------+--------------+-------+-----+
+ | 4 | bti | N | Y |
+ +-------+--------------+-------+-----+
This option defaults to 0 and this is an experimental feature.
Note that Pointer Authentication is enabled for Non-secure world
@@ -116,6 +119,8 @@
- ``BUILD_STRING``: Input string for VERSION_STRING, which allows the TF-A
build to be uniquely identified. Defaults to the current git commit id.
+- ``BUILD_BASE``: Output directory for the build. Defaults to ``./build``
+
- ``CFLAGS``: Extra user options appended on the compiler's command line in
addition to the options set by the build system.
@@ -343,16 +348,14 @@
- ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have
inherent support for specific EL3 type interrupts. Setting this build option
to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both
- by `platform abstraction layer`__ and `Interrupt Management Framework`__.
+ by :ref:`platform abstraction layer<platform Interrupt Controller API>` and
+ :ref:`Interrupt Management Framework<Interrupt Management Framework>`.
This allows GICv2 platforms to enable features requiring EL3 interrupt type.
This also means that all GICv2 Group 0 interrupts are delivered to EL3, and
the Secure Payload interrupts needs to be synchronously handed over to Secure
EL1 for handling. The default value of this option is ``0``, which means the
Group 0 interrupts are assumed to be handled by Secure EL1.
- .. __: platform-interrupt-controller-API.rst
- .. __: interrupt-framework-design.rst
-
- ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError
Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to
``0`` (default), these exceptions will be trapped in the current exception
@@ -645,6 +648,13 @@
configuration device tree, instead of static structure in the code base.
This is currently an experimental feature.
+- ``COT_DESC_IN_DTB``: This flag determines whether to create COT descriptors
+ at runtime using fconf. If this flag is enabled, COT descriptors are
+ statically captured in tb_fw_config file in the form of device tree nodes
+ and properties. Currently, COT descriptors used by BL2 are moved to the
+ device tree and COT descriptors used by BL1 are retained in the code
+ base statically. This is currently an experimental feature.
+
- ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in
runtime using firmware configuration framework. The platform specific SDEI
shared and private events configuration is retrieved from device tree rather
@@ -711,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 b7a93e4..6b8bbc6 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
---------------------------------------------
@@ -1424,7 +1437,7 @@
On Arm standard platforms, the arguments received are :
- arg0 - Points to load address of HW_CONFIG if present
+ arg0 - Points to load address of FW_CONFIG
arg1 - ``meminfo`` structure populated by BL1. The platform copies
the contents of ``meminfo`` as it may be subsequently overwritten by BL2.
@@ -1736,6 +1749,10 @@
which is list of executable images following BL31,
arg1 - Points to load address of SOC_FW_CONFIG if present
+ except in case of Arm FVP platform.
+
+ In case of Arm FVP platform, Points to load address
+ of FW_CONFIG.
arg2 - Points to load address of HW_CONFIG if present
@@ -2465,9 +2482,7 @@
``FVP_USE_GIC_DRIVER`` (See :ref:`build_options_arm_fvp_platform` for more
details).
-See also: `Interrupt Controller Abstraction APIs`__.
-
-.. __: ../design/platform-interrupt-controller-API.rst
+See also: :ref:`Interrupt Controller Abstraction APIs<Platform Interrupt Controller API>`.
Function : plat_interrupt_type_to_line() [mandatory]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2592,9 +2607,7 @@
the highest pending interrupt has begun. It should return the raw, unmodified
value obtained from the interrupt controller when acknowledging an interrupt.
The actual interrupt number shall be extracted from this raw value using the API
-`plat_ic_get_interrupt_id()`__.
-
-.. __: ../design/platform-interrupt-controller-API.rst#function-unsigned-int-plat-ic-get-interrupt-id-unsigned-int-raw-optional
+`plat_ic_get_interrupt_id()<plat_ic_get_interrupt_id>`.
This function in Arm standard platforms using GICv2, reads the *Interrupt
Acknowledge Register* (``GICC_IAR``). This changes the state of the highest
@@ -2725,6 +2738,8 @@
registers x0 through x5 to do its work. The return value is 0 on successful
completion; otherwise the return value is -1.
+.. _External Abort handling and RAS Support:
+
External Abort handling and RAS Support
---------------------------------------
diff --git a/docs/perf/psci-performance-juno.rst b/docs/perf/psci-performance-juno.rst
index c127c1c..eab3e4d 100644
--- a/docs/perf/psci-performance-juno.rst
+++ b/docs/perf/psci-performance-juno.rst
@@ -286,7 +286,7 @@
--------------
-*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
-.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf
+.. _Juno R1 platform: https://static.docs.arm.com/100122/0100/arm_versatile_express_juno_r1_development_platform_(v2m_juno_r1)_technical_reference_manual_100122_0100_05_en.pdf
.. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index a1e0659..d82380d 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -34,7 +34,7 @@
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
-.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
+.. _U-Boot documentation: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/sunxi/README.sunxi64
Trusted OS dispatcher
---------------------
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 9622de6..2e50068 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -91,6 +91,9 @@
platforms. If this option is specified, then the path to the CryptoCell
SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag.
+- ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
+ SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
+
For a better understanding of these options, the Arm development platform memory
map is explained in the :ref:`Firmware Design`.
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index f23ec28..745e31f 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -37,12 +37,16 @@
- ``FVP_Base_Cortex-A76AEx4``
- ``FVP_Base_Cortex-A76AEx8``
- ``FVP_Base_Cortex-A77x4``
+- ``FVP_Base_Neoverse-E1x1``
+- ``FVP_Base_Neoverse-E1x2``
+- ``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
@@ -631,7 +635,7 @@
*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
-.. _TB_FW_CONFIG for FVP: ../plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+.. _TB_FW_CONFIG for FVP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
.. _Arm's website: `FVP models`_
.. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms
.. _Linaro Release 19.06: http://releases.linaro.org/members/arm/platforms/19.06
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
index ba087a2..f184b69 100644
--- a/docs/plat/imx8m.rst
+++ b/docs/plat/imx8m.rst
@@ -33,6 +33,7 @@
Target_SoC should be "imx8mq" for i.MX8MQ SoC.
Target_SoC should be "imx8mm" for i.MX8MM SoC.
Target_SoC should be "imx8mn" for i.MX8MN SoC.
+ Target_SoC should be "imx8mp" for i.MX8MP SoC.
Deploy TF-A Images
~~~~~~~~~~~~~~~~~~
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index 6f28721..da4ba56 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -77,6 +77,15 @@
Flag defining the LLC (L3) cache state. The cache is enabled by default (``LLC_ENABLE=1``).
+- LLC_SRAM
+
+ Flag enabling the LLC (L3) cache SRAM support. The LLC SRAM is activated and used
+ by Trusted OS (OP-TEE OS, BL32). The TF-A only prepares CCU address translation windows
+ for SRAM address range at BL31 execution stage with window target set to DRAM-0.
+ When Trusted OS activates LLC SRAM, the CCU window target is changed to SRAM.
+ There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n.
+ Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y.
+
- MARVELL_SECURE_BOOT
Build trusted(=1)/non trusted(=0) image, default is non trusted.
diff --git a/docs/plat/meson-axg.rst b/docs/plat/meson-axg.rst
index 1e4b2c2..6f6732e 100644
--- a/docs/plat/meson-axg.rst
+++ b/docs/plat/meson-axg.rst
@@ -24,4 +24,4 @@
instructions in the `U-Boot repository`_, replacing the mentioned **bl31.img**
by the one built from this port.
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/s400/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/s400.rst
diff --git a/docs/plat/meson-g12a.rst b/docs/plat/meson-g12a.rst
index 7cd1bf7..9588ec4 100644
--- a/docs/plat/meson-g12a.rst
+++ b/docs/plat/meson-g12a.rst
@@ -20,8 +20,8 @@
CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a
This port has been tested on a SEI510 board. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
mentioned **bl31.img** by the one built from this port.
.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README.g12a
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/sei510/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/sei510.rst
diff --git a/docs/plat/meson-gxl.rst b/docs/plat/meson-gxl.rst
index c6d8504..0751f1d 100644
--- a/docs/plat/meson-gxl.rst
+++ b/docs/plat/meson-gxl.rst
@@ -20,8 +20,8 @@
CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl
This port has been tested on a Lepotato. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
mentioned **bl31.img** by the one built from this port.
.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/p212/README.libretech-cc
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/p212.rst
diff --git a/docs/plat/qemu.rst b/docs/plat/qemu.rst
index afa32c1..66b8247 100644
--- a/docs/plat/qemu.rst
+++ b/docs/plat/qemu.rst
@@ -20,11 +20,46 @@
Current limitations:
- Only cold boot is supported
-- No build instructions for QEMU\_EFI.fd and rootfs-arm64.cpio.gz
-``QEMU_EFI.fd`` can be dowloaded from
+Getting non-TF images
+---------------------
+
+``QEMU_EFI.fd`` can be downloaded from
http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd
+or, can be built as follows:
+
+.. code:: shell
+
+ git clone https://github.com/tianocore/edk2.git
+ cd edk2
+ git submodule update --init
+ make -C BaseTools
+ source edksetup.sh
+ export GCC5_AARCH64_PREFIX=aarch64-linux-gnu-
+ build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemuKernel.dsc
+
+````
+
+Then, you will get ``Build/ArmVirtQemuKernel-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd``
+
+Please note you do not need to use GCC 5 in spite of the environment variable
+``GCC5_AARCH64_PREFIX``
+
+The rootfs can be built by using Buildroot as follows:
+
+.. code:: shell
+
+ git clone git://git.buildroot.net/buildroot.git
+ cd buildroot
+ make qemu_aarch64_virt_defconfig
+ utils/config -e BR2_TARGET_ROOTFS_CPIO
+ utils/config -e BR2_TARGET_ROOTFS_CPIO_GZIP
+ make olddefconfig
+ make
+
+Then, you will get ``output/images/rootfs.cpio.gz``.
+
Booting via semi-hosting option
-------------------------------
@@ -43,14 +78,14 @@
make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu
-To start (QEMU v4.1.0):
+To start (QEMU v5.0.0):
.. code:: shell
qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \
-kernel Image \
- -append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2" \
- -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin \
+ -append "console=ttyAMA0,38400 keep_bootcon" \
+ -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios bl1.bin \
-d unimp -semihosting-config enable,target=native
Booting via flash based firmwares
@@ -92,12 +127,12 @@
dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc
-To start (QEMU v2.6.0):
+To start (QEMU v5.0.0):
.. code:: shell
qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \
-kernel Image -no-acpi \
- -append 'console=ttyAMA0,38400 keep_bootcon root=/dev/vda2' \
- -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios flash.bin \
+ -append 'console=ttyAMA0,38400 keep_bootcon' \
+ -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin \
-d unimp
diff --git a/docs/process/security-reporting.asc b/docs/process/security-reporting.asc
deleted file mode 100644
index 8c41f7b..0000000
--- a/docs/process/security-reporting.asc
+++ /dev/null
@@ -1,45 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: PGP Desktop 10.2.0 (Build 2317)
-
-mQENBFey/QMBCACyxJaLsMYU794ZfzLdY172tHXRJfP0X3b34HU35G7kYl1zNiYc
-/NoygtQdtDv/aW1B2A/YTNhGge+gX4BWAREd5CYDbdPEoMWC395/qbnmMmez7YNY
-PEJ9Iq9e5AayAWwZTL1zgKwdvE+WTwWok/nMbsifJSEdhdrOIHNqRcZgplUUyZ2R
-sDqFtSbACO3xj4Psk8KJ23Ax7UZgULouZOJaHOnyq8F9V/U7zWvX4Odf96XaC1Em
-cUTsG0kQfa7Y4Hqqjzowq366I4k2o2LAtuLPWNCvq5jjEceLs2+qV4cNLgyL2dzO
-wtUL6EdkrGfkxsPHpsVKXig4wjeX9ehCSqRlABEBAAG0PVRydXN0ZWQgRmlybXdh
-cmUgU2VjdXJpdHkgPHRydXN0ZWQtZmlybXdhcmUtc2VjdXJpdHlAYXJtLmNvbT6J
-AYwEEAECAHYFAley/SEwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWlsLWVuY29kaW5n
-QHBncC5jb21wZ3BtaW1lCAsJCAcDAgEKAhkBGRhsZGFwOi8va2V5c2VydmVyLnBn
-cC5jb20FGwMAAAAFFgADAgEFHgEAAAAGFQgJCgMCAAoJEDq378tFoN/QFJsH/0ly
-H91LYYzKIQrbolQw7Rp47lgzH88uN1rInYpW2GaTbjwPffAhYJ4VsN8RaiFskD9m
-DjMg4vY8p0jPTCUX1Acq20Wq0Ybv3HcrtjUp4ie0+rLUi3043yJyKFMWkJC2Kr+p
-SobnxSrAie4HDFUgSaPoh9Qf1zXEzOavdgcziMiyS5iVUf6NXYZ9z82OTZ6TdPKS
-u+L5zOHTdrV3+hD54w00Xa+EIE7u4v0to6Uwm977508hyGuvpOVq+u7+S3qJQvnY
-+JheStbgLsm6CyoRjyrlTE01ujAD6hI6Ef9yMgEljOBEy4phKAJ67SCRLEOiCp5U
-YHFCULwhzIyg2y3WmZSJASIEEAECAAwFAlezAnwFAwASdQAACgkQlxC4m8pXrXzd
-GAf/T8YEICI9qQt2vnCtCbBvVaTc2sAphVZ51kZVDqCDPB7znDtJYRBpi/9IPELt
-mYwIElMx2mqmahVaeUghmbzmcLZe8QHUi8GanO1mh+ook6uyjRojSIq6VUVV5uUf
-tuscfhpilOvUclqMqYEIgXfl08YwS40Kmmj0qokwad0co0zGQ8GEhlgMi2yvJfiG
-fPS0Xcn1J0980E/VgJQCAKwZvukrbb32WVwuhgepqs/4/62PZNxglcErioFt6P0A
-ik4t9Hr0uErqCeEKiYtmEw5e9ioRdX7CV+tJgIk907Tpv6E0iDFRJHmJBvmsz82O
-stOazS3wZ5Xck7asTqkvoyo9Z7kBDQRXsv0DAQgAsmL1UUIWyoNmYJWixSPDmclP
-0ul3T1FCOsIlWTeVeshnHByYdgZOfce78ETCUoq8G7qvYm4GRrEDpqVbxqTxJioP
-4Li05WDdNCKzSoqWd8ADA48gYnnJEu2NhA7ZkEC6u3+Mdbmd3M0J6nsAWeE0BV1p
-F5zI600sJuoH2QNWB7Kv5N3GCFE4IgCIH8MwDo4Y4FTZtygx4GjEtSExiOIz+bpX
-2+GkFCQGpIyLHLP4FmQmrsNzsIdEyFuG0IdoVuQ2PtNLiw+Wkm7CXWgRmFx/dtPN
-eVnOFWdbTtjBWVv/Z6zbANos2knfc75KR4FCQ6pWRvVeJuMuMopUDkfFDMtR8QAR
-AQABiQJBBBgBAgErBQJXsv0EBRsMAAAAwF0gBBkBCAAGBQJXsv0DAAoJENaB8ph8
-s9hu/nsH/Rx696ZR+1vZi5qCTUwo6s0Qa15x4OuyJEM85VgMLVY7/MZpp1Y8If6u
-A5BynQpy4QIPxIRsRx6twduW9/gb8UVhpMRPyuJ+5sSv0/KeUqkPbKSUGro2zGlR
-sjqPrchi6uafWZqOR/y/DNkEvkgZZaP+f9xs2qWKuoF08yTioo76QoroA4DVuVAT
-MkDFe9d3natAmfmjO4kvxuthg3y7R+sdXrCHpYYJZdbiR6gyj7e8whlSLwHQT3lz
-7QBL/CvVvL/dmhu5pk8fsksbehepMQTkCJ6GGEamOPEhwh7IvlzhEt97U4uzjuMd
-BPjqOCes+4QTmn/+lMTySG0kXxnHOEUACgkQOrfvy0Wg39D8Jgf/Uf3epkMOJ9xm
-N1l5vW8tQQ6RR055YQxQ9P6JMyCQGEJmGOcvrasCho69wMQDy4AYVtJaZd25LH/3
-LX/lcyDOP4C9VYXM+IxlcaRmjBKqWx9UzQeeioIkfmjMpJFU846ZP1dacge0lPx8
-p6ocPbM0rkv0xuF/dwkDQd4BPSmv4/3/UM8FRoYo8Q7SHkDR98wJ8FCm6k9wRtWC
-K/jzmBswY2TewAHom3jLzTM0FZ/n5Sini3EGAI2EvnQrxWRpeE7ZOkHKqLHEOaHl
-zeST4U/cUgxhwgnhbGJ7zmrFsHpYnnZYM3mIKfQ3/EhksZ68TF9IB1tfUiQTij4r
-9jWa0ybRdQ==
-=nZZb
------END PGP PUBLIC KEY BLOCK-----
diff --git a/docs/process/security.rst b/docs/process/security.rst
index c3935da..516eb98 100644
--- a/docs/process/security.rst
+++ b/docs/process/security.rst
@@ -20,40 +20,13 @@
Although we try to keep TF-A secure, we can only do so with the help of the
community of developers and security researchers.
-If you think you have found a security vulnerability, please **do not** report it
-in the `issue tracker`_. Instead send an email to
-trusted-firmware-security@arm.com
-
-Please include:
-
-* Trusted Firmware-A version (or commit) affected
-
-* A description of the concern or vulnerability
-
-* Details on how to replicate the vulnerability, including:
-
- - Configuration details
-
- - Proof of concept exploit code
-
- - Any additional software or tools required
-
-We recommend using :download:`this PGP/GPG key <./security-reporting.asc>` for
-encrypting the information. This key is also available at
-http://keyserver.pgp.com and LDAP port 389 of the same server.
-
-The fingerprint for this key is:
-
-::
-
- 1309 2C19 22B4 8E87 F17B FE5C 3AB7 EFCB 45A0 DFD0
-
-If you would like replies to be encrypted, please provide your public key.
-
-Please give us the time to respond to you and fix the vulnerability before going
-public. We do our best to respond and fix any issues quickly. We also need to
-ensure providers of products that use TF-A have a chance to consider the
-implications of the vulnerability and its remedy.
+If you think you have found a security vulnerability, please **do not** report
+it in the `issue tracker`_. Instead, please follow the `TrustedFirmware.org
+security incident process`_. One of the goals of this process is to ensure
+providers of products that use TF-A have a chance to consider the implications
+of the vulnerability and its remedy before it is made public. As such, please
+follow the disclosure plan outlined in the process. We do our best to respond
+and fix any issues quickly.
Afterwards, we encourage you to write-up your findings about the TF-A source
code.
@@ -61,8 +34,8 @@
Attribution
-----------
-We will name and thank you in the :ref:`Change Log & Release Notes` distributed with the source
-code and in any published security advisory.
+We will name and thank you in the :ref:`Change Log & Release Notes` distributed
+with the source code and in any published security advisory.
Security Advisories
-------------------
@@ -96,7 +69,6 @@
+-----------+------------------------------------------------------------------+
.. _issue tracker: https://developer.trustedfirmware.org/project/board/1/
-.. _this PGP/GPG key: security-reporting.asc
.. |TFV-1| replace:: :ref:`Advisory TFV-1 (CVE-2016-10319)`
.. |TFV-2| replace:: :ref:`Advisory TFV-2 (CVE-2017-7564)`
@@ -107,6 +79,8 @@
.. |TFV-7| replace:: :ref:`Advisory TFV-7 (CVE-2018-3639)`
.. |TFV-8| replace:: :ref:`Advisory TFV-8 (CVE-2018-19440)`
+.. _TrustedFirmware.org security incident process: https://developer.trustedfirmware.org/w/collaboration/security_center/
+
--------------
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
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/fconf_bl1_load_config.puml b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
index e613eef..e513ed4 100644
--- a/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
+++ b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
@@ -13,6 +13,7 @@
box "platform common code"
participant plat_bl1_common
+ participant fconf_dyn_cfg_getter
participant fconf
end box
@@ -20,12 +21,17 @@
fvp_bl1_setup -> arm_bl1_setup : arm_bl1_platform_setup()
arm_bl1_setup -> arm_io_storage : plat_arm_io_setup()
note over arm_io_storage : register and setup fip
-arm_bl1_setup -> fconf : fconf_load_config()
+arm_bl1_setup -> fconf : set_fw_config_info(fw_config_base, max_size)
+note over fconf
+ set fw_config information
+ (address, size, image_id)
+ in global dtb_infos array.
+end note
activate fconf
- note over fconf
- create and populate an
- image_desc_t for FW_CONFIG
- end note
+ arm_bl1_setup -> fconf : fconf_load_config(FW_CONFIG_ID)
+ fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID)
+ fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID)
+ fconf_dyn_cfg_getter -> fconf: fw_config_info
fconf -> bl_common : load_auth_image(FW_CONFIG_ID, &image_info)
activate bl_common
note over bl_common
@@ -33,18 +39,38 @@
with info from plat_io_policy
end note
bl_common -> arm_io_storage
- arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, tb_fw_cfg)
- note over fconf: use staticaly defined policies in bl1
+ arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, FW_CONFIG_ID)
+ note over fconf: use statically defined policies in bl1
+ fconf <- bl_common : image_info
+ deactivate bl_common
+ note over fconf : get fw_config_dtb from image_info
+ arm_bl1_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID)
+ fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID)
+ fconf_dyn_cfg_getter -> arm_bl1_setup: fw_config_info
+ arm_bl1_setup -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb)
+ arm_bl1_setup -> fconf: fconf_load_config(TB_FW_CONFIG_ID)
+ fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID)
+ fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID)
+ fconf_dyn_cfg_getter -> fconf: tb_fw_config_info
+ fconf -> bl_common : load_auth_image(TB_FW_CONFIG_ID, &image_info)
+ activate bl_common
+ note over bl_common
+ load and auth image from fip
+ with info from plat_io_policy
+ end note
+ bl_common -> arm_io_storage
+ arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, TB_FW_CONFIG_ID)
+ note over fconf: use statically defined policies in bl1
fconf <- bl_common : image_info
deactivate bl_common
note over fconf : get tb_fw_config_dtb from image_info
- fconf -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID)
- fconf <- plat_bl1_common : BL2_IMAGE_DESC
- note over fconf
- set ep_info.args.arg0 of BL2_IMAGE_DESC
- to FW_CONFIG base address
+ fconf -> arm_bl1_setup
+ arm_bl1_setup -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID)
+ arm_bl1_setup <- plat_bl1_common : BL2_IMAGE_DESC
+ note over arm_bl1_setup
+ set ep_info.args.arg0 of BL2_IMAGE_DESC
+ to FW_CONFIG base address
end note
-arm_bl1_setup <- fconf
deactivate fconf
== load & auth, prepare and jump to BL2 ==
diff --git a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
index 881f253..c536ee0 100644
--- a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
+++ b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
@@ -8,6 +8,7 @@
box "platform common code"
participant fconf
participant fconf_tbbr_getter
+participant fconf_dyn_cfg_getter
end box
box "arm platform code" #LightBlue
@@ -25,10 +26,17 @@
end note
arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t fw_config, mem_layout)
activate arm_bl2_setup
- arm_bl2_setup -> fconf: fconf_polulate("TB_FW", fw_config)
+ arm_bl2_setup -> fconf: fconf_populate("FW_CONFIG", fw_config)
activate fconf
+ fconf -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb)
+ note over fconf_dyn_cfg_getter: read dtb_registry properties from dtb
+ fconf_dyn_cfg_getter -> arm_bl2_setup
+ arm_bl2_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID)
+ fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID)
+ fconf_dyn_cfg_getter -> arm_bl2_setup: tb_fw_config_info
+ arm_bl2_setup -> fconf: fconf_populate("TB_FW_CONFIG", tb_fw_config)
fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb)
- note over fconf_tbbr_getter: read tbbr propeties from dtb
+ note over fconf_tbbr_getter: read tbbr properties from dtb
fconf -> arm_fconf_io: fconf_populate_arm_io_policies(uintptr_t dtb)
note over arm_fconf_io: read arm io propeties from dtb
deactivate fconf
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/css/scp/css_bom_bootloader.c b/drivers/arm/css/scp/css_bom_bootloader.c
index 1fc1270..74121b4 100644
--- a/drivers/arm/css/scp/css_bom_bootloader.c
+++ b/drivers/arm/css/scp/css_bom_bootloader.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -51,13 +51,13 @@
* All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31
* usually resides except when ARM_BL31_IN_DRAM is
* set). Ensure that SCP_BL2/SCP_BL2U do not overflow into shared RAM and
- * the tb_fw_config.
+ * the fw_config.
*/
CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2);
CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2);
-CASSERT(SCP_BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
-CASSERT(SCP_BL2U_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
+CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
+CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
static void scp_boot_message_start(void)
{
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
index 38b2f67..bf6405f 100644
--- a/drivers/arm/gic/common/gic_common.c
+++ b/drivers/arm/gic/common/gic_common.c
@@ -1,9 +1,11 @@
/*
- * 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
*/
+#pragma message __FILE__ " is deprecated, use gicv2.mk instead"
+
#include <assert.h>
#include <drivers/arm/gic_common.h>
diff --git a/drivers/arm/gic/v2/gicdv2_helpers.c b/drivers/arm/gic/v2/gicdv2_helpers.c
new file mode 100644
index 0000000..db9ba87
--- /dev/null
+++ b/drivers/arm/gic/v2/gicdv2_helpers.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+
+#include "../common/gic_common_private.h"
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+/*
+ * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
+ * `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> IGROUPR_SHIFT;
+
+ return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ISENABLER_SHIFT;
+
+ return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ICENABLER_SHIFT;
+
+ return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ISPENDR_SHIFT;
+
+ return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ICPENDR_SHIFT;
+
+ return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ISACTIVER_SHIFT;
+
+ return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ICACTIVER_SHIFT;
+
+ return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> IPRIORITYR_SHIFT;
+
+ return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICGFR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ICFGR_SHIFT;
+
+ return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> NSACR_SHIFT;
+
+ return mmio_read_32(base + GICD_NSACR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+/*
+ * Accessor to write the GIC Distributor IGROUPR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> IGROUPR_SHIFT;
+
+ mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ISENABLER_SHIFT;
+
+ mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ICENABLER_SHIFT;
+
+ mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ISPENDR_SHIFT;
+
+ mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ICPENDR_SHIFT;
+
+ mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ISACTIVER_SHIFT;
+
+ mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ICACTIVER_SHIFT;
+
+ mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> IPRIORITYR_SHIFT;
+
+ mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICFGR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> ICFGR_SHIFT;
+
+ mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
+{
+ unsigned int n = id >> NSACR_SHIFT;
+
+ mmio_write_32(base + GICD_NSACR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor functions for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+ unsigned int reg_val = gicd_read_igroupr(base, id);
+
+ return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_igroupr(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+ unsigned int reg_val = gicd_read_igroupr(base, id);
+
+ gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
+}
+
+void gicd_clr_igroupr(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+ unsigned int reg_val = gicd_read_igroupr(base, id);
+
+ gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
+}
+
+void gicd_set_isenabler(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
+
+ gicd_write_isenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_icenabler(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
+
+ gicd_write_icenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_ispendr(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
+
+ gicd_write_ispendr(base, id, (1U << bit_num));
+}
+
+void gicd_set_icpendr(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
+
+ gicd_write_icpendr(base, id, (1U << bit_num));
+}
+
+unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+ unsigned int reg_val = gicd_read_isactiver(base, id);
+
+ return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_isactiver(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+
+ gicd_write_isactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_icactiver(uintptr_t base, unsigned int id)
+{
+ unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
+
+ gicd_write_icactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+ uint8_t val = pri & GIC_PRI_MASK;
+
+ mmio_write_8(base + GICD_IPRIORITYR + id, val);
+}
+
+void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+ /* Interrupt configuration is a 2-bit field */
+ unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
+ unsigned int bit_shift = bit_num << 1;
+
+ uint32_t reg_val = gicd_read_icfgr(base, id);
+
+ /* Clear the field, and insert required configuration */
+ reg_val &= ~(GIC_CFG_MASK << bit_shift);
+ reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
+
+ gicd_write_icfgr(base, id, reg_val);
+}
diff --git a/drivers/arm/gic/v2/gicv2.mk b/drivers/arm/gic/v2/gicv2.mk
new file mode 100644
index 0000000..49996bb
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# No support for extended PPI and SPI range
+GIC_EXT_INTID := 0
+
+GICV2_SOURCES += drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/arm/gic/v2/gicdv2_helpers.c
+
+# Set GICv2 build option
+$(eval $(call add_define,GIC_EXT_INTID))
\ No newline at end of file
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index c5bced0..4b21b92 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -247,6 +247,15 @@
assert(driver_data != NULL);
assert(driver_data->gicc_base != 0U);
+ /*
+ * Ensure the write to peripheral registers are *complete* before the write
+ * to GIC_EOIR.
+ *
+ * Note: The completion gurantee depends on various factors of system design
+ * and the barrier is the best core can do by which execution of further
+ * instructions waits till the barrier is alive.
+ */
+ dsbishst();
gicc_write_EOIR(driver_data->gicc_base, id);
}
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
index c1a9f0d..6e106ba 100644
--- a/drivers/arm/gic/v3/gic-x00.c
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -1,5 +1,6 @@
/*
- * 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
*/
@@ -20,30 +21,32 @@
#include "gicv3_private.h"
/* GIC-600 specific register offsets */
-#define GICR_PWRR 0x24
-#define IIDR_MODEL_ARM_GIC_600 0x0200043b
+#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
-#define PWRR_RDAG_SHIFT 1
-#define PWRR_RDGPD_SHIFT 2
-#define PWRR_RDGPO_SHIFT 3
+#define PWRR_RDPD_SHIFT 0
+#define PWRR_RDAG_SHIFT 1
+#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
-/* GIC-600 specific accessor functions */
+/* GIC-600/Clayton specific accessor functions */
static void gicr_write_pwrr(uintptr_t base, unsigned int val)
{
mmio_write_32(base + GICR_PWRR, val);
@@ -56,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)
@@ -91,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);
}
@@ -101,24 +108,30 @@
{
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;
}
-static bool gicv3_is_gic600(uintptr_t gicr_base)
+static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base)
{
uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
- return (reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600;
+ /*
+ * The Arm GIC-600 and GIC-Clayton models have their redistributors
+ * powered down at reset.
+ */
+ return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
+ ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
+ ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
}
-#endif
+#endif /* GICV3_SUPPORT_GIC600 */
void gicv3_distif_pre_save(unsigned int proc_num)
{
@@ -130,7 +143,6 @@
arm_gicv3_distif_post_restore(proc_num);
}
-
/*
* Power off GIC-600 redistributor (if configured and detected)
*/
@@ -140,7 +152,7 @@
uintptr_t gicr_base = get_gicr_base(proc_num);
/* Attempt to power redistributor off */
- if (gicv3_is_gic600(gicr_base)) {
+ if (gicv3_redists_need_power_mgmt(gicr_base)) {
gic600_pwr_off(gicr_base);
}
#endif
@@ -155,7 +167,7 @@
uintptr_t gicr_base = get_gicr_base(proc_num);
/* Power redistributor on */
- if (gicv3_is_gic600(gicr_base)) {
+ if (gicv3_redists_need_power_mgmt(gicr_base)) {
gic600_pwr_on(gicr_base);
}
#endif
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 f28ddaa..68f3d46 100644
--- a/drivers/auth/dualroot/cot.c
+++ b/drivers/auth/dualroot/cot.c
@@ -16,6 +16,7 @@
* Allocate static buffers to store the authentication parameters extracted from
* the certificates.
*/
+static unsigned char fw_config_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char hw_config_hash_buf[HASH_DER_LEN];
@@ -58,6 +59,8 @@
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
+static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
#ifdef IMAGE_BL1
static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
@@ -165,6 +168,13 @@
.ptr = (void *)hw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
+ },
+ [3] = {
+ .type_desc = &fw_config_hash,
+ .data = {
+ .ptr = (void *)fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
}
}
};
@@ -218,6 +228,22 @@
}
}
};
+
+static const auth_img_desc_t fw_config = {
+ .img_id = FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &fw_config_hash
+ }
+ }
+ }
+};
+
#endif /* IMAGE_BL1 */
#ifdef IMAGE_BL2
@@ -667,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]) {
@@ -749,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 */
@@ -860,6 +886,7 @@
[BL2_IMAGE_ID] = &bl2_image,
[HW_CONFIG_ID] = &hw_config,
[TB_FW_CONFIG_ID] = &tb_fw_config,
+ [FW_CONFIG_ID] = &fw_config,
[FWU_CERT_ID] = &fwu_cert,
[SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
[BL2U_IMAGE_ID] = &bl2u_image,
@@ -887,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_bl1.c b/drivers/auth/tbbr/tbbr_cot_bl1.c
index f3bb376..e4c9221 100644
--- a/drivers/auth/tbbr/tbbr_cot_bl1.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl1.c
@@ -150,6 +150,21 @@
}
};
+static const auth_img_desc_t fw_config = {
+ .img_id = FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &fw_config_hash
+ }
+ }
+ }
+};
+
/*
* TBBR Chain of trust definition
*/
@@ -158,6 +173,7 @@
[BL2_IMAGE_ID] = &bl2_image,
[HW_CONFIG_ID] = &hw_config,
[TB_FW_CONFIG_ID] = &tb_fw_config,
+ [FW_CONFIG_ID] = &fw_config,
[FWU_CERT_ID] = &fwu_cert,
[SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
[BL2U_IMAGE_ID] = &bl2u_image,
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/auth/tbbr/tbbr_cot_common.c b/drivers/auth/tbbr/tbbr_cot_common.c
index 0a4b75e..ff3f22d 100644
--- a/drivers/auth/tbbr/tbbr_cot_common.c
+++ b/drivers/auth/tbbr/tbbr_cot_common.c
@@ -23,9 +23,10 @@
* established, we can reuse some of the buffers on different stages
*/
+static unsigned char fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char hw_config_hash_buf[HASH_DER_LEN];
unsigned char tb_fw_hash_buf[HASH_DER_LEN];
-unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
-unsigned char hw_config_hash_buf[HASH_DER_LEN];
unsigned char scp_fw_hash_buf[HASH_DER_LEN];
unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
@@ -48,7 +49,9 @@
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
-auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
+auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
/* trusted_boot_fw_cert */
@@ -95,6 +98,13 @@
.ptr = (void *)hw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
+ },
+ [3] = {
+ .type_desc = &fw_config_hash,
+ .data = {
+ .ptr = (void *)fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
}
}
};
diff --git a/drivers/brcm/rng.c b/drivers/brcm/rng.c
new file mode 100644
index 0000000..ee2e656
--- /dev/null
+++ b/drivers/brcm/rng.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define RNG_CTRL_REG (RNG_BASE_ADDR + 0x00)
+#define RNG_CTRL_MASK 0x00001FFF
+#define RNG_CTRL_ENABLE 0x00000001
+#define RNG_CTRL_DISABLE 0x00000000
+
+#define RNG_SOFT_RESET_REG (RNG_BASE_ADDR + 0x04)
+#define RNG_SOFT_RESET_MASK 0x00000001
+
+#define RNG_FIFO_DATA_REG (RNG_BASE_ADDR + 0x20)
+
+#define RNG_FIFO_COUNT_REG (RNG_BASE_ADDR + 0x24)
+#define RNG_FIFO_COUNT_MASK 0x000000FF
+
+#define RNG_FIFO_WORDS_MAX 16
+#define MAX_WAIT_COUNT_50US 20000
+
+
+static void rng_reset(void)
+{
+ /* Disable RBG */
+ mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK);
+
+ /* Reset RNG and RBG */
+ mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+
+ /* Take all out of reset */
+ mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+}
+
+static void rng_enable(void)
+{
+ /* Setup RNG. */
+ mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE);
+}
+
+int rng_init(void)
+{
+ rng_reset();
+
+ rng_enable();
+
+ return 0;
+}
+
+int rng_read(uint32_t *p_out, uint32_t *words_read)
+{
+ uint32_t available_words;
+ uint32_t i;
+ uint32_t word_processed = 0;
+ uint32_t wait_count = MAX_WAIT_COUNT_50US;
+
+ if (*words_read == 0) {
+ ERROR("RNG Parameter: No word requested\n");
+ return -1;
+ }
+
+ do {
+ available_words = mmio_read_32(RNG_FIFO_COUNT_REG);
+ available_words &= RNG_FIFO_COUNT_MASK;
+
+ if (available_words != 0) {
+ available_words = MIN(available_words,
+ *words_read - word_processed);
+
+ for (i = 0; i < available_words; i++)
+ p_out[word_processed + i] =
+ mmio_read_32(RNG_FIFO_DATA_REG);
+ word_processed += available_words;
+ } else {
+ udelay(50);
+ }
+
+ if (word_processed == *words_read)
+ break;
+
+ } while (--wait_count);
+
+ if (word_processed != *words_read) {
+ ERROR("RNG Timeout: requested %d word(s) got %d\n",
+ *words_read, word_processed);
+ *words_read = word_processed;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 02f85d6..6e15295 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -36,7 +36,7 @@
typedef struct {
unsigned int file_pos;
fip_toc_entry_t entry;
-} file_state_t;
+} fip_file_state_t;
/*
* Maintain dev_spec per FIP Device
@@ -49,7 +49,6 @@
uint16_t plat_toc_flag;
} fip_dev_state_t;
-static const uuid_t uuid_null;
/*
* Only one file can be open across all FIP device
* as backends like io_memmap don't support
@@ -57,7 +56,7 @@
* backend handle should be maintained per FIP device
* if the same support is available in the backend
*/
-static file_state_t current_file = {0};
+static fip_file_state_t current_fip_file = {0};
static uintptr_t backend_dev_handle;
static uintptr_t backend_image_spec;
@@ -288,6 +287,7 @@
int result;
uintptr_t backend_handle;
const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
+ static const uuid_t uuid_null = { {0} }; /* Double braces for clang */
size_t bytes_read;
int found_file = 0;
@@ -300,9 +300,9 @@
* When the system supports dynamic memory allocation we can allow more
* than one open file at a time if needed.
*/
- if (current_file.entry.offset_address != 0) {
+ if (current_fip_file.entry.offset_address != 0U) {
WARN("fip_file_open : Only one open file at a time.\n");
- return -ENOMEM;
+ return -ENFILE;
}
/* Attempt to access the FIP image */
@@ -326,31 +326,32 @@
found_file = 0;
do {
result = io_read(backend_handle,
- (uintptr_t)¤t_file.entry,
- sizeof(current_file.entry),
+ (uintptr_t)¤t_fip_file.entry,
+ sizeof(current_fip_file.entry),
&bytes_read);
if (result == 0) {
- if (compare_uuids(¤t_file.entry.uuid,
+ if (compare_uuids(¤t_fip_file.entry.uuid,
&uuid_spec->uuid) == 0) {
found_file = 1;
- break;
}
} else {
WARN("Failed to read FIP (%i)\n", result);
goto fip_file_open_close;
}
- } while (compare_uuids(¤t_file.entry.uuid, &uuid_null) != 0);
+ } while ((found_file == 0) &&
+ (compare_uuids(¤t_fip_file.entry.uuid,
+ &uuid_null) != 0));
if (found_file == 1) {
/* All fine. Update entity info with file state and return. Set
- * the file position to 0. The 'current_file.entry' holds the
- * base and size of the file.
+ * the file position to 0. The 'current_fip_file.entry' holds
+ * the base and size of the file.
*/
- current_file.file_pos = 0;
- entity->info = (uintptr_t)¤t_file;
+ current_fip_file.file_pos = 0;
+ entity->info = (uintptr_t)¤t_fip_file;
} else {
/* Did not find the file in the FIP. */
- current_file.entry.offset_address = 0;
+ current_fip_file.entry.offset_address = 0;
result = -ENOENT;
}
@@ -368,7 +369,7 @@
assert(entity != NULL);
assert(length != NULL);
- *length = ((file_state_t *)entity->info)->entry.size;
+ *length = ((fip_file_state_t *)entity->info)->entry.size;
return 0;
}
@@ -379,7 +380,7 @@
size_t *length_read)
{
int result;
- file_state_t *fp;
+ fip_file_state_t *fp;
size_t file_offset;
size_t bytes_read;
uintptr_t backend_handle;
@@ -397,7 +398,7 @@
goto fip_file_read_exit;
}
- fp = (file_state_t *)entity->info;
+ fp = (fip_file_state_t *)entity->info;
/* Seek to the position in the FIP where the payload lives */
file_offset = fp->entry.offset_address + fp->file_pos;
@@ -436,8 +437,8 @@
/* Clear our current file pointer.
* If we had malloc() we would free() here.
*/
- if (current_file.entry.offset_address != 0) {
- zeromem(¤t_file, sizeof(current_file));
+ if (current_fip_file.entry.offset_address != 0U) {
+ zeromem(¤t_fip_file, sizeof(current_fip_file));
}
/* Clear the Entity info. */
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index eed50cc..eb69163 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -27,9 +27,9 @@
uintptr_t base;
unsigned long long file_pos;
unsigned long long size;
-} file_state_t;
+} memmap_file_state_t;
-static file_state_t current_file = {0};
+static memmap_file_state_t current_memmap_file = {0};
/* Identify the device type as memmap */
static io_type_t device_type_memmap(void)
@@ -71,7 +71,7 @@
/* No state associated with this device so structure can be const */
-static const io_dev_info_t memmap_dev_info = {
+static io_dev_info_t memmap_dev_info = {
.funcs = &memmap_dev_funcs,
.info = (uintptr_t)NULL
};
@@ -82,8 +82,7 @@
io_dev_info_t **dev_info)
{
assert(dev_info != NULL);
- *dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
-
+ *dev_info = &memmap_dev_info;
return 0;
}
@@ -109,16 +108,16 @@
* spec at a time. When we have dynamic memory we can malloc and set
* entity->info.
*/
- if (current_file.in_use == 0) {
+ if (current_memmap_file.in_use == 0) {
assert(block_spec != NULL);
assert(entity != NULL);
- current_file.in_use = 1;
- current_file.base = block_spec->offset;
+ current_memmap_file.in_use = 1;
+ current_memmap_file.base = block_spec->offset;
/* File cursor offset for seek and incremental reads etc. */
- current_file.file_pos = 0;
- current_file.size = block_spec->length;
- entity->info = (uintptr_t)¤t_file;
+ current_memmap_file.file_pos = 0;
+ current_memmap_file.size = block_spec->length;
+ entity->info = (uintptr_t)¤t_memmap_file;
result = 0;
} else {
WARN("A Memmap device is already active. Close first.\n");
@@ -133,13 +132,13 @@
signed long long offset)
{
int result = -ENOENT;
- file_state_t *fp;
+ memmap_file_state_t *fp;
/* We only support IO_SEEK_SET for the moment. */
if (mode == IO_SEEK_SET) {
assert(entity != NULL);
- fp = (file_state_t *) entity->info;
+ fp = (memmap_file_state_t *) entity->info;
/* Assert that new file position is valid */
assert((offset >= 0) &&
@@ -160,7 +159,7 @@
assert(entity != NULL);
assert(length != NULL);
- *length = (size_t)((file_state_t *)entity->info)->size;
+ *length = (size_t)((memmap_file_state_t *)entity->info)->size;
return 0;
}
@@ -170,13 +169,13 @@
static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
{
- file_state_t *fp;
+ memmap_file_state_t *fp;
unsigned long long pos_after;
assert(entity != NULL);
assert(length_read != NULL);
- fp = (file_state_t *) entity->info;
+ fp = (memmap_file_state_t *) entity->info;
/* Assert that file position is valid for this read operation */
pos_after = fp->file_pos + length;
@@ -198,13 +197,13 @@
static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
size_t length, size_t *length_written)
{
- file_state_t *fp;
+ memmap_file_state_t *fp;
unsigned long long pos_after;
assert(entity != NULL);
assert(length_written != NULL);
- fp = (file_state_t *) entity->info;
+ fp = (memmap_file_state_t *) entity->info;
/* Assert that file position is valid for this write operation */
pos_after = fp->file_pos + length;
@@ -230,7 +229,7 @@
entity->info = 0;
/* This would be a mem free() if we had malloc.*/
- zeromem((void *)¤t_file, sizeof(current_file));
+ zeromem((void *)¤t_memmap_file, sizeof(current_memmap_file));
return 0;
}
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
index 4ceddc6..1c2f84d 100644
--- a/drivers/io/io_semihosting.c
+++ b/drivers/io/io_semihosting.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -51,8 +51,7 @@
};
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t sh_dev_info = {
+static io_dev_info_t sh_dev_info = {
.funcs = &sh_dev_funcs,
.info = (uintptr_t)NULL
};
@@ -63,7 +62,7 @@
io_dev_info_t **dev_info)
{
assert(dev_info != NULL);
- *dev_info = (io_dev_info_t *)&sh_dev_info; /* cast away const */
+ *dev_info = &sh_dev_info;
return 0;
}
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index b8c1d64..0534268 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,36 +32,34 @@
#if ENABLE_ASSERTIONS
/* Return a boolean value indicating whether a device connector is valid */
-static int is_valid_dev_connector(const io_dev_connector_t *dev_con)
+static bool is_valid_dev_connector(const io_dev_connector_t *dev_con)
{
- int result = (dev_con != NULL) && (dev_con->dev_open != NULL);
- return result;
+ return (dev_con != NULL) && (dev_con->dev_open != NULL);
}
-
/* Return a boolean value indicating whether a device handle is valid */
-static int is_valid_dev(const uintptr_t dev_handle)
+static bool is_valid_dev(const uintptr_t dev_handle)
{
const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
- int result = (dev != NULL) && (dev->funcs != NULL) &&
+
+ return (dev != NULL) && (dev->funcs != NULL) &&
(dev->funcs->type != NULL) &&
(dev->funcs->type() < IO_TYPE_MAX);
- return result;
}
/* Return a boolean value indicating whether an IO entity is valid */
-static int is_valid_entity(const uintptr_t handle)
+static bool is_valid_entity(const uintptr_t handle)
{
const io_entity_t *entity = (io_entity_t *)handle;
- int result = (entity != NULL) &&
+
+ return (entity != NULL) &&
(is_valid_dev((uintptr_t)entity->dev_handle));
- return result;
}
/* Return a boolean value indicating whether a seek mode is valid */
-static int is_valid_seek_mode(io_seek_mode_t mode)
+static bool is_valid_seek_mode(io_seek_mode_t mode)
{
return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
}
@@ -71,15 +69,14 @@
/* Open a connection to a specific device */
-static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
+static int io_storage_dev_open(const io_dev_connector_t *dev_con,
+ const uintptr_t dev_spec,
io_dev_info_t **dev_info)
{
- int result;
assert(dev_info != NULL);
assert(is_valid_dev_connector(dev_con));
- result = dev_con->dev_open(dev_spec, dev_info);
- return result;
+ return dev_con->dev_open(dev_spec, dev_info);
}
@@ -116,7 +113,8 @@
unsigned int index = 0;
result = find_first_entity(NULL, &index);
assert(result == 0);
- *entity = entity_map[index] = &entity_pool[index];
+ *entity = &entity_pool[index];
+ entity_map[index] = &entity_pool[index];
++entity_count;
}
@@ -163,11 +161,8 @@
int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
uintptr_t *handle)
{
- int result;
assert(handle != NULL);
-
- result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
- return result;
+ return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
}
diff --git a/drivers/marvell/cache_llc.c b/drivers/marvell/cache_llc.c
index 3df93a4..4b06b47 100644
--- a/drivers/marvell/cache_llc.c
+++ b/drivers/marvell/cache_llc.c
@@ -31,19 +31,19 @@
void llc_flush_all(int ap_index)
{
- mmio_write_32(L2X0_CLEAN_INV_WAY(ap_index), LLC_WAY_MASK);
+ mmio_write_32(LLC_CLEAN_INV_WAY(ap_index), LLC_ALL_WAYS_MASK);
llc_cache_sync(ap_index);
}
void llc_clean_all(int ap_index)
{
- mmio_write_32(L2X0_CLEAN_WAY(ap_index), LLC_WAY_MASK);
+ mmio_write_32(LLC_CLEAN_WAY(ap_index), LLC_ALL_WAYS_MASK);
llc_cache_sync(ap_index);
}
void llc_inv_all(int ap_index)
{
- mmio_write_32(L2X0_INV_WAY(ap_index), LLC_WAY_MASK);
+ mmio_write_32(LLC_INV_WAY(ap_index), LLC_ALL_WAYS_MASK);
llc_cache_sync(ap_index);
}
@@ -109,3 +109,81 @@
reg |= (0x1 << CCU_SET_POC_OFFSET);
mmio_write_32(CCU_HTC_CR(ap_index), reg);
}
+
+#if LLC_SRAM
+int llc_sram_enable(int ap_index, int size)
+{
+ uint32_t tc, way, ways_to_allocate;
+ uint32_t way_addr;
+
+ if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE))
+ return -1;
+
+ llc_enable(ap_index, 1);
+ llc_inv_all(ap_index);
+
+ ways_to_allocate = size / LLC_WAY_SIZE;
+
+ /* Lockdown all available ways for all traffic classes */
+ for (tc = 0; tc < LLC_TC_NUM; tc++)
+ mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK);
+
+ /* Clear the high bits of SRAM address */
+ mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0);
+
+ way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE;
+ for (way = 0; way < ways_to_allocate; way++) {
+ /* Trigger allocation block command */
+ mmio_write_32(LLC_BLK_ALOC(ap_index),
+ LLC_BLK_ALOC_BASE_ADDR(way_addr) |
+ LLC_BLK_ALOC_WAY_DATA_SET |
+ LLC_BLK_ALOC_WAY_ID(way));
+ way_addr += LLC_WAY_SIZE;
+ }
+ return 0;
+}
+
+void llc_sram_disable(int ap_index)
+{
+ uint32_t tc;
+
+ /* Disable the line lockings */
+ for (tc = 0; tc < LLC_TC_NUM; tc++)
+ mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0);
+
+ /* Invalidate all ways */
+ llc_inv_all(ap_index);
+}
+
+int llc_sram_test(int ap_index, int size, char *msg)
+{
+ uintptr_t addr, end_addr;
+ uint32_t data = 0;
+
+ if ((size <= 0) || (size > LLC_SIZE))
+ return -1;
+
+ INFO("=== LLC SRAM WRITE test %s\n", msg);
+ for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+ end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+ addr < end_addr; addr += 4) {
+ mmio_write_32(addr, addr);
+ }
+ INFO("=== LLC SRAM WRITE test %s PASSED\n", msg);
+ INFO("=== LLC SRAM READ test %s\n", msg);
+ for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+ end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+ addr < end_addr; addr += 4) {
+ data = mmio_read_32(addr);
+ if (data != addr) {
+ INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n",
+ msg, addr);
+ return -1;
+ }
+ }
+ INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n",
+ msg, data);
+ return 0;
+}
+
+#endif /* LLC_SRAM */
diff --git a/drivers/marvell/ccu.c b/drivers/marvell/ccu.c
index 1e4ab44..c73516e 100644
--- a/drivers/marvell/ccu.c
+++ b/drivers/marvell/ccu.c
@@ -54,8 +54,8 @@
win_id));
start = ((uint64_t)alr << ADDRESS_SHIFT);
end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
- printf("\tccu %02x 0x%016llx 0x%016llx\n",
- target_id, start, end);
+ printf("\tccu%d %02x 0x%016llx 0x%016llx\n",
+ win_id, target_id, start, end);
}
}
win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_index));
@@ -81,6 +81,12 @@
}
}
+int ccu_is_win_enabled(int ap_index, uint32_t win_id)
+{
+ return mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)) &
+ WIN_ENABLE_BIT;
+}
+
void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id)
{
uint32_t ccu_win_reg;
diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h
index 6eb7fd0..3678c90 100644
--- a/drivers/marvell/comphy/comphy-cp110.h
+++ b/drivers/marvell/comphy/comphy-cp110.h
@@ -659,18 +659,32 @@
(0x3f << HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET)
#define HPIPE_CDR_CONTROL_REG 0x418
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET 14
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK \
- (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET)
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET 12
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK \
- (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET)
-#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET 9
-#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK \
- (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET)
+#define HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET 0
+#define HPIPE_CRD_MIDPOINT_PHASE_OS_MASK \
+ (0x3f << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET)
#define HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET 6
#define HPIPE_CDR_MAX_DFE_ADAPT_1_MASK \
(0x7 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET)
+#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET 9
+#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK \
+ (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET)
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET 12
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK \
+ (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET)
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET 14
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK \
+ (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET)
+
+
+#define HPIPE_CDR_CONTROL1_REG 0x41c
+#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF 12
+#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK \
+ (0xf << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF)
+
+#define HPIPE_CDR_CONTROL2_REG 0x420
+#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF 12
+#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK \
+ (0xf << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF)
#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438
#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6
@@ -749,6 +763,30 @@
#define HPIPE_DFE_CTRL_28_PIPE4_MASK \
(0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET)
+#define HPIPE_TRX0_REG 0x4cc /*in doc 0x133*4*/
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF 2
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK \
+ (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF)
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF 0
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK \
+ (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF)
+
+#define HPIPE_TRX_REG1 0x4d0 /*in doc 0x134*4*/
+#define HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF 3
+#define HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK \
+ (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF)
+#define HPIPE_TRX_REG1_SUMFTAP_EN_OFF 10
+#define HPIPE_TRX_REG1_SUMFTAP_EN_MASK \
+ (0x3f << HPIPE_TRX_REG1_SUMFTAP_EN_OFF)
+
+#define HPIPE_TRX_REG2 0x4d8 /*in doc 0x136*4*/
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF 11
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK \
+ (0x1f << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF)
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF 7
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK \
+ (0xf << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF)
+
#define HPIPE_G1_SETTING_5_REG 0x538
#define HPIPE_G1_SETTING_5_G1_ICP_OFFSET 0
#define HPIPE_G1_SETTING_5_G1_ICP_MASK \
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index b682086..1d5b6f5 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -11,6 +11,7 @@
#include <common/debug.h>
#include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
#include <lib/mmio.h>
#include <lib/spinlock.h>
@@ -209,8 +210,10 @@
* as SFI1/XFI1 available only for CP115.
*/
if ((mode == COMPHY_SGMII_MODE ||
- mode == COMPHY_HS_SGMII_MODE ||
- mode == COMPHY_SFI_MODE || mode == COMPHY_XFI_MODE)
+ mode == COMPHY_HS_SGMII_MODE ||
+ mode == COMPHY_SFI_MODE ||
+ mode == COMPHY_XFI_MODE ||
+ mode == COMPHY_AP_MODE)
&& COMPHY_GET_ID(comphy_mode) == 1)
reg |= COMMON_SELECTOR_COMPHY4_PORT1 <<
comphy_offset;
@@ -2012,12 +2015,58 @@
return ret;
}
+static void rx_pre_train(uint64_t comphy_base, uint8_t comphy_index)
+{
+ uintptr_t hpipe_addr;
+ uint32_t mask, data;
+
+ hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
+ comphy_index);
+
+ debug("rx_training preparation\n\n");
+
+ mask = HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK;
+ data = (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF);
+ mask |= HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK;
+ data |= (0x0 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF);
+ reg_set(hpipe_addr + HPIPE_TRX0_REG, data, mask);
+
+
+ mask = HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
+ data = (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
+ mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK;
+ data |= (0x0 << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF);
+ reg_set(hpipe_addr + HPIPE_TRX_REG2, data, mask);
+
+ mask = HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK;
+ data = (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF);
+ reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
+
+ mask = HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK;
+ data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF);
+ reg_set(hpipe_addr + HPIPE_CDR_CONTROL1_REG, data, mask);
+
+ mask = HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK;
+ data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF);
+ reg_set(hpipe_addr + HPIPE_CDR_CONTROL2_REG, data, mask);
+
+ mask = HPIPE_CRD_MIDPOINT_PHASE_OS_MASK;
+ data = (0x0 << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET);
+ reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
+
+ mask = HPIPE_TRX_REG1_SUMFTAP_EN_MASK;
+ data = (0x38 << HPIPE_TRX_REG1_SUMFTAP_EN_OFF);
+ mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
+ data |= (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
+ reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
+}
+
int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
uint8_t comphy_index)
{
uint32_t mask, data, timeout;
uint32_t g1_ffe_cap_sel, g1_ffe_res_sel, align90, g1_dfe_res;
- uintptr_t hpipe_addr, sd_ip_addr;
+ uintptr_t hpipe_addr;
uint8_t ap_nr, cp_nr;
@@ -2025,30 +2074,10 @@
hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
comphy_index);
- sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
- comphy_index);
debug_enter();
- debug("stage: RF Reset\n");
-
- /* Release from hard reset */
- mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
- data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
- mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
- data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
- mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
- data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
- reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
- mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
- data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
- mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
- data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
- reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
- /* Wait 50ms - until band gap and ref clock ready */
- mdelay(50);
+ rx_pre_train(comphy_base, comphy_index);
debug("Preparation for rx_training\n\n");
@@ -2068,34 +2097,10 @@
data = 0 << HPIPE_DFE_RES_FORCE_OFFSET;
reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
- debug("PRBS31 loppback\n\n");
-
- /* Configure PRBS counters */
- mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
- data = 0xe << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
- mask = HPIPE_PHY_TEST_DATA_MASK;
- data = 0xc4 << HPIPE_PHY_TEST_DATA_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_DATA_REG, data, mask);
-
- mask = HPIPE_PHY_TEST_EN_MASK;
- data = 0x1 << HPIPE_PHY_TEST_EN_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
- mdelay(10);
- debug("Enable TX/RX training\n\n");
+ debug("Enable RX training\n\n");
mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
- mask |= HPIPE_TRX_RX_ANA_IF_CLK_ENE_MASK;
- data |= 0x1 << HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET;
- mask |= HPIPE_TRX_TX_CTRL_CLK_EN_MASK;
- data |= 0x1 << HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET;
- mask |= HPIPE_TRX_UPDATE_THEN_HOLD_MASK;
- data |= 0x1 << HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET;
- mask |= HPIPE_TRX_TX_F0T_EO_BASED_MASK;
- data |= 0x1 << HPIPE_TRX_TX_F0T_EO_BASED_OFFSET;
reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
/* Check the result of RX training */
@@ -2180,21 +2185,9 @@
data = 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
- /* Use the value from CAL_OS_PH_EXT */
- mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
- data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
- reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
- data, mask);
-
- /* Update align90 */
- mask = HPIPE_CAL_OS_PH_EXT_MASK;
- data = align90 << HPIPE_CAL_OS_PH_EXT_OFFSET;
- reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
- data, mask);
-
/* Force DFE resolution (use gen table value) */
mask = HPIPE_DFE_RES_FORCE_MASK;
- data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
+ data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
/* 0x111-G1 DFE_Setting_4 */
@@ -2202,38 +2195,6 @@
data = g1_dfe_res << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
- debug("PRBS31 loppback\n\n");
-
- mask = HPIPE_PHY_TEST_PT_TESTMODE_MASK;
- data = 0x1 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_OOB_0_REGISTER, data, mask);
-
- /* Configure PRBS counters */
- mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
- data = 0xe << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
- mask = HPIPE_PHY_TEST_DATA_MASK;
- data = 0xc4 << HPIPE_PHY_TEST_DATA_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_DATA_REG, data, mask);
-
- mask = HPIPE_PHY_TEST_EN_MASK;
- data = 0x1 << HPIPE_PHY_TEST_EN_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
- /* Reset PRBS error counter */
- mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
- data = 0x1 << HPIPE_PHY_TEST_RESET_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
- mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
- data = 0x0 << HPIPE_PHY_TEST_RESET_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
- mask = HPIPE_PHY_TEST_PT_TESTMODE_MASK;
- data = 0x1 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET;
- reg_set(hpipe_addr + HPIPE_PHY_TEST_OOB_0_REGISTER, data, mask);
-
printf("########################################################\n");
printf("# To use trained values update the ATF sources:\n");
printf("# plat/marvell/armada/a8k/<board_type>/board/phy-porting-layer.h ");
@@ -2252,12 +2213,6 @@
printf("};\n\n");
printf("########################################################\n");
- /* check */
- debug("PRBS error counter[0x%lx] 0x%x\n\n",
- hpipe_addr + HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG,
- mmio_read_32(hpipe_addr +
- HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG));
-
rx_trainng_done[ap_nr][cp_nr][comphy_index] = 1;
return 0;
@@ -2273,12 +2228,17 @@
* the network registers like: MG, AP, MAC, PCS, Serdes etc.)
*/
static int mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base,
- uint8_t comphy_index)
+ uint8_t comphy_index,
+ uint32_t comphy_mode)
{
uint32_t mask, data;
+ uint8_t ap_nr, cp_nr;
uintptr_t comphy_addr = comphy_addr =
COMPHY_ADDR(comphy_base, comphy_index);
+ /* configure phy selector for XFI/SFI */
+ mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
+ comphy_mode);
debug_enter();
debug("stage: RFU configurations - hard reset comphy\n");
/* RFU configurations - hard reset comphy */
@@ -2289,6 +2249,10 @@
reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
debug_exit();
+ /* Start AP Firmware */
+ mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
+ mg_start_ap_fw(cp_nr, comphy_index);
+
return 0;
}
@@ -2371,7 +2335,8 @@
comphy_mode);
break;
case (COMPHY_AP_MODE):
- err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index);
+ err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index,
+ comphy_mode);
break;
default:
ERROR("comphy%d: unsupported comphy mode\n", comphy_index);
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
new file mode 100644
index 0000000..98e1896
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mss_scp_bl2_format.h>
+
+/* CONFI REGISTERS */
+#define MG_CM3_CONFI_BASE(CP) (MVEBU_CP_REGS_BASE(CP) + 0x100000)
+#define MG_CM3_SRAM_BASE(CP) MG_CM3_CONFI_BASE(CP)
+#define MG_CM3_CONFI_GLOB_CFG_REG(CP) (MG_CM3_CONFI_BASE(CP) + 0x2B500)
+#define CM3_CPU_EN_BIT BIT(28)
+#define MG_CM3_MG_INT_MFX_REG(CP) (MG_CM3_CONFI_BASE(CP) + 0x2B054)
+#define CM3_SYS_RESET_BIT BIT(0)
+
+#define MG_CM3_SHARED_MEM_BASE(CP) (MG_CM3_SRAM_BASE(CP) + 0x1FC00ULL)
+
+#define MG_SRAM_SIZE 0x20000 /* 128KB */
+
+#define MG_ACK_TIMEOUT 10
+
+/**
+ * struct ap_sharedmem_ctrl - used to pass information between the HOST and CM3
+ * @init_done: Set by CM3 when ap_proces initialzied. Host check if CM3 set
+ * this flag to confirm that the process is running
+ * @lane_nr: Set by Host to mark which comphy lane should be configure. E.g.:
+ * - A8K development board uses comphy lane 2 for eth0
+ * - CN913x development board uses comphy lane 4 for eth0
+ */
+struct ap_sharedmem_ctrl {
+ uint32_t init_done;
+ uint32_t lane_nr;
+};
+
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index)
+{
+ uintptr_t mg_regs = MG_CM3_SRAM_BASE(cp_index);
+
+ if (size > MG_SRAM_SIZE) {
+ ERROR("image is too big to fit into MG CM3 memory\n");
+ return 1;
+ }
+
+ NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
+ src_addr, size, mg_regs);
+
+ /* Copy image to MG CM3 SRAM */
+ memcpy((void *)mg_regs, (void *)src_addr, size);
+
+ /* Don't release MG CM3 from reset - it will be done by next step
+ * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
+ * has enabeld 802.3. auto-neg) will be choosen.
+ */
+
+ return 0;
+}
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index)
+{
+ volatile struct ap_sharedmem_ctrl *ap_shared_ctrl =
+ (void *)MG_CM3_SHARED_MEM_BASE(cp_nr);
+ int timeout = MG_ACK_TIMEOUT;
+
+ if (mmio_read_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr)) & CM3_CPU_EN_BIT) {
+ VERBOSE("cm3 already running\n");
+ return; /* cm3 already running */
+ }
+
+ /*
+ * Mark which comphy lane should be used - it will be read via shared
+ * mem by ap process
+ */
+ ap_shared_ctrl->lane_nr = comphy_index;
+ /* Make sure it took place before enabling cm3 */
+ dmbst();
+
+ mmio_setbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), CM3_CPU_EN_BIT);
+ mmio_setbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), CM3_SYS_RESET_BIT);
+
+ /* Check for ap process initialization by fw */
+ while (ap_shared_ctrl->init_done != 1 && timeout--)
+ VERBOSE("Waiting for ap process ack, timeout %d\n", timeout);
+
+ if (timeout == 0) {
+ ERROR("AP process failed, disabling cm3\n");
+ mmio_clrbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr),
+ CM3_SYS_RESET_BIT);
+ mmio_clrbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr),
+ CM3_CPU_EN_BIT);
+ }
+}
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
new file mode 100644
index 0000000..e2756de
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index);
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index);
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/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 2f4dcad..d6cd8b1 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -577,6 +577,43 @@
1, 2, 3, 4, 4, 4, 4, 4
};
+static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
+ [_HSI] = "HSI",
+ [_HSE] = "HSE",
+ [_CSI] = "CSI",
+ [_LSI] = "LSI",
+ [_LSE] = "LSE",
+ [_I2S_CKIN] = "I2S_CKIN",
+ [_HSI_KER] = "HSI_KER",
+ [_HSE_KER] = "HSE_KER",
+ [_HSE_KER_DIV2] = "HSE_KER_DIV2",
+ [_CSI_KER] = "CSI_KER",
+ [_PLL1_P] = "PLL1_P",
+ [_PLL1_Q] = "PLL1_Q",
+ [_PLL1_R] = "PLL1_R",
+ [_PLL2_P] = "PLL2_P",
+ [_PLL2_Q] = "PLL2_Q",
+ [_PLL2_R] = "PLL2_R",
+ [_PLL3_P] = "PLL3_P",
+ [_PLL3_Q] = "PLL3_Q",
+ [_PLL3_R] = "PLL3_R",
+ [_PLL4_P] = "PLL4_P",
+ [_PLL4_Q] = "PLL4_Q",
+ [_PLL4_R] = "PLL4_R",
+ [_ACLK] = "ACLK",
+ [_PCLK1] = "PCLK1",
+ [_PCLK2] = "PCLK2",
+ [_PCLK3] = "PCLK3",
+ [_PCLK4] = "PCLK4",
+ [_PCLK5] = "PCLK5",
+ [_HCLK6] = "KCLK6",
+ [_HCLK2] = "HCLK2",
+ [_CK_PER] = "CK_PER",
+ [_CK_MPU] = "CK_MPU",
+ [_CK_MCU] = "CK_MCU",
+ [_USB_PHY_48] = "USB_PHY_48",
+};
+
/* RCC clock device driver private */
static unsigned long stm32mp1_osc[NB_OSC];
static struct spinlock reg_lock;
@@ -2007,6 +2044,165 @@
}
}
+#ifdef STM32MP_SHARED_RESOURCES
+/*
+ * Get the parent ID of the target parent clock, for tagging as secure
+ * shared clock dependencies.
+ */
+static int get_parent_id_parent(unsigned int parent_id)
+{
+ enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
+ enum stm32mp1_pll_id pll_id;
+ uint32_t p_sel;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ switch (parent_id) {
+ case _ACLK:
+ case _PCLK4:
+ case _PCLK5:
+ s = _AXIS_SEL;
+ break;
+ case _PLL1_P:
+ case _PLL1_Q:
+ case _PLL1_R:
+ pll_id = _PLL1;
+ break;
+ case _PLL2_P:
+ case _PLL2_Q:
+ case _PLL2_R:
+ pll_id = _PLL2;
+ break;
+ case _PLL3_P:
+ case _PLL3_Q:
+ case _PLL3_R:
+ pll_id = _PLL3;
+ break;
+ case _PLL4_P:
+ case _PLL4_Q:
+ case _PLL4_R:
+ pll_id = _PLL4;
+ break;
+ case _PCLK1:
+ case _PCLK2:
+ case _HCLK2:
+ case _HCLK6:
+ case _CK_PER:
+ case _CK_MPU:
+ case _CK_MCU:
+ case _USB_PHY_48:
+ /* We do not expect to access these */
+ panic();
+ break;
+ default:
+ /* Other parents have no parent */
+ return -1;
+ }
+
+ if (s != _UNKNOWN_SEL) {
+ const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
+
+ p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
+ sel->msk;
+
+ if (p_sel < sel->nb_parent) {
+ return (int)sel->parent[p_sel];
+ }
+ } else {
+ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+
+ p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
+ RCC_SELR_REFCLK_SRC_MASK;
+
+ if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
+ return (int)pll->refclk[p_sel];
+ }
+ }
+
+ VERBOSE("No parent selected for %s\n",
+ stm32mp1_clk_parent_name[parent_id]);
+
+ return -1;
+}
+
+static void secure_parent_clocks(unsigned long parent_id)
+{
+ int grandparent_id;
+
+ switch (parent_id) {
+ case _PLL3_P:
+ case _PLL3_Q:
+ case _PLL3_R:
+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+ break;
+
+ /* These clocks are always secure when RCC is secure */
+ case _ACLK:
+ case _HCLK2:
+ case _HCLK6:
+ case _PCLK4:
+ case _PCLK5:
+ case _PLL1_P:
+ case _PLL1_Q:
+ case _PLL1_R:
+ case _PLL2_P:
+ case _PLL2_Q:
+ case _PLL2_R:
+ case _HSI:
+ case _HSI_KER:
+ case _LSI:
+ case _CSI:
+ case _CSI_KER:
+ case _HSE:
+ case _HSE_KER:
+ case _HSE_KER_DIV2:
+ case _LSE:
+ break;
+
+ default:
+ VERBOSE("Cannot secure parent clock %s\n",
+ stm32mp1_clk_parent_name[parent_id]);
+ panic();
+ }
+
+ grandparent_id = get_parent_id_parent(parent_id);
+ if (grandparent_id >= 0) {
+ secure_parent_clocks(grandparent_id);
+ }
+}
+
+void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
+{
+ int parent_id;
+
+ if (!stm32mp1_rcc_is_secure()) {
+ return;
+ }
+
+ switch (clock_id) {
+ case PLL1:
+ case PLL2:
+ /* PLL1/PLL2 are always secure: nothing to do */
+ break;
+ case PLL3:
+ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+ break;
+ case PLL4:
+ ERROR("PLL4 cannot be secured\n");
+ panic();
+ break;
+ default:
+ /* Others are expected gateable clock */
+ parent_id = stm32mp1_clk_get_parent(clock_id);
+ if (parent_id < 0) {
+ INFO("No parent found for clock %lu\n", clock_id);
+ } else {
+ secure_parent_clocks(parent_id);
+ }
+ break;
+ }
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+
static void sync_earlyboot_clocks_state(void)
{
unsigned int idx;
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 3184df9..515947c 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -300,7 +300,9 @@
break;
}
#else
+ /* BL32 uses hash if it is assigned only to secure world */
if (hash_info.status == DT_SECURE) {
+ stm32mp_register_secure_periph_iomem(hash_info.base);
break;
}
#endif
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index a13c341..bb77371 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -254,6 +254,15 @@
mmio_read_32(base + GPIO_AFRH_OFFSET));
stm32mp_clk_disable(clock);
+
+ if (status == DT_SECURE) {
+ stm32mp_register_secure_gpio(bank, pin);
+ set_gpio_secure_cfg(bank, pin, true);
+
+ } else {
+ stm32mp_register_non_secure_gpio(bank, pin);
+ set_gpio_secure_cfg(bank, pin, false);
+ }
}
void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
index ea6fbb2..c052b4d 100644
--- a/drivers/st/iwdg/stm32_iwdg.c
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -137,6 +137,12 @@
((dt_info.status & DT_NON_SECURE) != 0) ?
"non-" : "");
+ if ((dt_info.status & DT_NON_SECURE) != 0) {
+ stm32mp_register_non_secure_periph_iomem(iwdg->base);
+ } else {
+ stm32mp_register_secure_periph_iomem(iwdg->base);
+ }
+
#if defined(IMAGE_BL2)
if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) {
return -1;
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 9e9dddc..b2bb482 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -54,6 +54,15 @@
return fdt_get_status(node);
}
+static bool dt_pmic_is_secure(void)
+{
+ int status = dt_pmic_status();
+
+ return (status >= 0) &&
+ (status == DT_SECURE) &&
+ (i2c_handle.dt_status == DT_SECURE);
+}
+
/*
* Get PMIC and its I2C bus configuration from the device tree.
* Return 0 on success, negative on error, 1 if no PMIC node is found.
@@ -223,6 +232,19 @@
return true;
}
+static void register_pmic_shared_peripherals(void)
+{
+ uintptr_t i2c_base = i2c_handle.i2c_base_addr;
+
+ if (dt_pmic_is_secure()) {
+ stm32mp_register_secure_periph_iomem(i2c_base);
+ } else {
+ if (i2c_base != 0U) {
+ stm32mp_register_non_secure_periph_iomem(i2c_base);
+ }
+ }
+}
+
void initialize_pmic(void)
{
unsigned long pmic_version;
@@ -232,6 +254,8 @@
return;
}
+ register_pmic_shared_peripherals();
+
if (stpmic1_get_version(&pmic_version) != 0) {
ERROR("Failed to access PMIC\n");
panic();
diff --git a/drivers/st/scmi-msg/base.c b/drivers/st/scmi-msg/base.c
new file mode 100644
index 0000000..e44bc52
--- /dev/null
+++ b/drivers/st/scmi-msg/base.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <assert.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+static bool message_id_is_supported(unsigned int message_id);
+
+static void report_version(struct scmi_msg *msg)
+{
+ struct scmi_protocol_version_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .version = SCMI_PROTOCOL_VERSION_BASE,
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+ size_t protocol_count = plat_scmi_protocol_count();
+ struct scmi_protocol_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ /* Null agent count since agent discovery is not supported */
+ .attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0U),
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+ struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+ struct scmi_protocol_message_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ /* For this protocol, attributes shall be zero */
+ .attributes = 0U,
+ };
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (!message_id_is_supported(in_args->message_id)) {
+ scmi_status_response(msg, SCMI_NOT_FOUND);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void discover_vendor(struct scmi_msg *msg)
+{
+ const char *name = plat_scmi_vendor_name();
+ struct scmi_base_discover_vendor_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name);
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void discover_sub_vendor(struct scmi_msg *msg)
+{
+ const char *name = plat_scmi_sub_vendor_name();
+ struct scmi_base_discover_sub_vendor_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name);
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void discover_implementation_version(struct scmi_msg *msg)
+{
+ struct scmi_protocol_version_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .version = SCMI_IMPL_VERSION,
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static unsigned int count_protocols_in_list(const uint8_t *protocol_list)
+{
+ unsigned int count = 0U;
+
+ if (protocol_list != NULL) {
+ while (protocol_list[count] != 0U) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+#define MAX_PROTOCOL_IN_LIST 8U
+
+static void discover_list_protocols(struct scmi_msg *msg)
+{
+ const struct scmi_base_discover_list_protocols_a2p *a2p = NULL;
+ struct scmi_base_discover_list_protocols_p2a p2a = {
+ .status = SCMI_SUCCESS,
+ };
+ uint8_t outargs[sizeof(p2a) + MAX_PROTOCOL_IN_LIST] = { 0U };
+ const uint8_t *list = NULL;
+ unsigned int count = 0U;
+
+ if (msg->in_size != sizeof(*a2p)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ assert(msg->out_size > sizeof(outargs));
+
+ a2p = (void *)msg->in;
+
+ list = plat_scmi_protocol_list(msg->agent_id);
+ count = count_protocols_in_list(list);
+ if (count > a2p->skip) {
+ count = MIN(count - a2p->skip, MAX_PROTOCOL_IN_LIST);
+ } else {
+ count = 0U;
+ }
+
+ p2a.num_protocols = count;
+
+ memcpy(outargs, &p2a, sizeof(p2a));
+ memcpy(outargs + sizeof(p2a), list + a2p->skip, count);
+
+ scmi_write_response(msg, outargs, sizeof(outargs));
+}
+
+static const scmi_msg_handler_t scmi_base_handler_table[] = {
+ [SCMI_PROTOCOL_VERSION] = report_version,
+ [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+ [SCMI_BASE_DISCOVER_VENDOR] = discover_vendor,
+ [SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor,
+ [SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] =
+ discover_implementation_version,
+ [SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols,
+};
+
+static bool message_id_is_supported(unsigned int message_id)
+{
+ return (message_id < ARRAY_SIZE(scmi_base_handler_table)) &&
+ (scmi_base_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg)
+{
+ unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+ if (message_id >= ARRAY_SIZE(scmi_base_handler_table)) {
+ VERBOSE("Base handle not found %u\n", msg->message_id);
+ return NULL;
+ }
+
+ return scmi_base_handler_table[message_id];
+}
diff --git a/drivers/st/scmi-msg/base.h b/drivers/st/scmi-msg/base.h
new file mode 100644
index 0000000..c4a9c64
--- /dev/null
+++ b/drivers/st/scmi-msg/base.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+
+#ifndef SCMI_MSG_BASE_H
+#define SCMI_MSG_BASE_H
+
+#include <stdint.h>
+
+#define SCMI_PROTOCOL_VERSION_BASE 0x20000U
+
+#define SCMI_DEFAULT_STRING_LENGTH 16U
+
+enum scmi_base_message_id {
+ SCMI_BASE_DISCOVER_VENDOR = 0x003,
+ SCMI_BASE_DISCOVER_SUB_VENDOR = 0x004,
+ SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x005,
+ SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x006,
+ SCMI_BASE_DISCOVER_AGENT = 0x007,
+ SCMI_BASE_NOTIFY_ERRORS = 0x008,
+};
+
+/*
+ * PROTOCOL_ATTRIBUTES
+ */
+
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS 0
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS 8
+
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK 0xFFU
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK 0xFF00U
+
+#define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \
+ ((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \
+ SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \
+ (((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \
+ SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK))
+
+/*
+ * BASE_DISCOVER_VENDOR
+ */
+struct scmi_base_discover_vendor_p2a {
+ int32_t status;
+ char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH];
+};
+
+/*
+ * BASE_DISCOVER_SUB_VENDOR
+ */
+struct scmi_base_discover_sub_vendor_p2a {
+ int32_t status;
+ char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH];
+};
+
+/*
+ * BASE_DISCOVER_IMPLEMENTATION_VERSION
+ * No special structure right now, see protocol_version.
+ */
+
+/*
+ * BASE_DISCOVER_LIST_PROTOCOLS
+ */
+struct scmi_base_discover_list_protocols_a2p {
+ uint32_t skip;
+};
+
+struct scmi_base_discover_list_protocols_p2a {
+ int32_t status;
+ uint32_t num_protocols;
+ uint32_t protocols[];
+};
+
+#endif /* SCMI_MSG_BASE_H */
diff --git a/drivers/st/scmi-msg/clock.c b/drivers/st/scmi-msg/clock.c
new file mode 100644
index 0000000..319557c
--- /dev/null
+++ b/drivers/st/scmi-msg/clock.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <cdefs.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+#pragma weak plat_scmi_clock_count
+#pragma weak plat_scmi_clock_get_name
+#pragma weak plat_scmi_clock_rates_array
+#pragma weak plat_scmi_clock_rates_by_step
+#pragma weak plat_scmi_clock_get_rate
+#pragma weak plat_scmi_clock_set_rate
+#pragma weak plat_scmi_clock_get_state
+#pragma weak plat_scmi_clock_set_state
+
+static bool message_id_is_supported(unsigned int message_id);
+
+size_t plat_scmi_clock_count(unsigned int agent_id __unused)
+{
+ return 0U;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused)
+{
+ return NULL;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned long *rates __unused,
+ size_t *nb_elts __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned long *steps __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused)
+{
+ return 0U;
+}
+
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned long rate __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ bool enable_not_disable __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+static void report_version(struct scmi_msg *msg)
+{
+ struct scmi_protocol_version_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .version = SCMI_PROTOCOL_VERSION_CLOCK,
+ };
+
+ if (msg->in_size != 0) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+ size_t agent_count = plat_scmi_clock_count(msg->agent_id);
+ struct scmi_protocol_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count),
+ };
+
+ if (msg->in_size != 0) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+ struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+ struct scmi_protocol_message_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ /* For this protocol, attributes shall be zero */
+ .attributes = 0U,
+ };
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (!message_id_is_supported(in_args->message_id)) {
+ scmi_status_response(msg, SCMI_NOT_FOUND);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_clock_attributes(struct scmi_msg *msg)
+{
+ const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in;
+ struct scmi_clock_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ };
+ const char *name = NULL;
+ unsigned int clock_id = 0U;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+ return;
+ }
+
+
+ name = plat_scmi_clock_get_name(msg->agent_id, clock_id);
+ if (name == NULL) {
+ scmi_status_response(msg, SCMI_NOT_FOUND);
+ return;
+ }
+
+ COPY_NAME_IDENTIFIER(return_values.clock_name, name);
+
+ return_values.attributes = plat_scmi_clock_get_state(msg->agent_id,
+ clock_id);
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_clock_rate_get(struct scmi_msg *msg)
+{
+ const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in;
+ unsigned long rate = 0U;
+ struct scmi_clock_rate_get_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ };
+ unsigned int clock_id = 0U;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+ return;
+ }
+
+ rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id);
+
+ return_values.rate[0] = (uint32_t)rate;
+ return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32);
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_clock_rate_set(struct scmi_msg *msg)
+{
+ const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in;
+ unsigned long rate = 0U;
+ int32_t status = 0;
+ unsigned int clock_id = 0U;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+ return;
+ }
+
+ rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) |
+ in_args->rate[0]);
+
+ status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate);
+
+ scmi_status_response(msg, status);
+}
+
+static void scmi_clock_config_set(struct scmi_msg *msg)
+{
+ const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in;
+ int32_t status = SCMI_GENERIC_ERROR;
+ bool enable = false;
+ unsigned int clock_id = 0U;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+ return;
+ }
+
+ enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK;
+
+ status = plat_scmi_clock_set_state(msg->agent_id, clock_id, enable);
+
+ scmi_status_response(msg, status);
+}
+
+#define RATES_ARRAY_SIZE_MAX (SCMI_PLAYLOAD_MAX - \
+ sizeof(struct scmi_clock_describe_rates_p2a))
+
+#define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \
+ SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \
+ SCMI_CLOCK_RATE_FORMAT_LIST, \
+ (_rem_rates))
+#define SCMI_RATES_BY_STEP \
+ SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \
+ SCMI_CLOCK_RATE_FORMAT_RANGE, \
+ 0U)
+
+#define RATE_DESC_SIZE sizeof(struct scmi_clock_rate)
+
+static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates,
+ size_t nb_elt)
+{
+ uint32_t *out = (uint32_t *)(uintptr_t)dest;
+ size_t n;
+
+ ASSERT_SYM_PTR_ALIGN(out);
+
+ for (n = 0U; n < nb_elt; n++) {
+ out[2 * n] = (uint32_t)rates[n];
+ out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32);
+ }
+}
+
+static void scmi_clock_describe_rates(struct scmi_msg *msg)
+{
+ const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in;
+ struct scmi_clock_describe_rates_p2a p2a = {
+ .status = SCMI_SUCCESS,
+ };
+ size_t nb_rates;
+ int32_t status;
+ unsigned int clock_id;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+ if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+ return;
+ }
+
+ /* Platform may support array rate description */
+ status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL,
+ &nb_rates);
+ if (status == SCMI_SUCCESS) {
+ /* Currently 12 cells mex, so it's affordable for the stack */
+ unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE];
+ size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE;
+ size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb);
+ size_t rem_nb = nb_rates - in_args->rate_index - ret_nb;
+
+ status = plat_scmi_clock_rates_array(msg->agent_id, clock_id,
+ plat_rates, &ret_nb);
+ if (status == SCMI_SUCCESS) {
+ write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
+ plat_rates, ret_nb);
+
+ p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb,
+ rem_nb);
+ p2a.status = SCMI_SUCCESS;
+
+ memcpy(msg->out, &p2a, sizeof(p2a));
+ msg->out_size_out = sizeof(p2a) +
+ ret_nb * RATE_DESC_SIZE;
+ }
+ } else if (status == SCMI_NOT_SUPPORTED) {
+ unsigned long triplet[3] = { 0U, 0U, 0U };
+
+ /* Platform may support min§max/step triplet description */
+ status = plat_scmi_clock_rates_by_step(msg->agent_id, clock_id,
+ triplet);
+ if (status == SCMI_SUCCESS) {
+ write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
+ triplet, 3U);
+
+ p2a.num_rates_flags = SCMI_RATES_BY_STEP;
+ p2a.status = SCMI_SUCCESS;
+
+ memcpy(msg->out, &p2a, sizeof(p2a));
+ msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE);
+ }
+ } else {
+ /* Fallthrough generic exit sequence below with error status */
+ }
+
+ if (status != SCMI_SUCCESS) {
+ scmi_status_response(msg, status);
+ } else {
+ /*
+ * Message payload is already writen to msg->out, and
+ * msg->out_size_out updated.
+ */
+ }
+}
+
+static const scmi_msg_handler_t scmi_clock_handler_table[] = {
+ [SCMI_PROTOCOL_VERSION] = report_version,
+ [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+ [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes,
+ [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates,
+ [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set,
+ [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get,
+ [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set,
+};
+
+static bool message_id_is_supported(size_t message_id)
+{
+ return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) &&
+ (scmi_clock_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg)
+{
+ const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table);
+ unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+ if (message_id >= array_size) {
+ VERBOSE("Clock handle not found %u", msg->message_id);
+ return NULL;
+ }
+
+ return scmi_clock_handler_table[message_id];
+}
diff --git a/drivers/st/scmi-msg/clock.h b/drivers/st/scmi-msg/clock.h
new file mode 100644
index 0000000..a637934
--- /dev/null
+++ b/drivers/st/scmi-msg/clock.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#ifndef SCMI_MSG_CLOCK_H
+#define SCMI_MSG_CLOCK_H
+
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define SCMI_PROTOCOL_VERSION_CLOCK 0x20000U
+
+/*
+ * Identifiers of the SCMI Clock Management Protocol commands
+ */
+enum scmi_clock_command_id {
+ SCMI_CLOCK_ATTRIBUTES = 0x003,
+ SCMI_CLOCK_DESCRIBE_RATES = 0x004,
+ SCMI_CLOCK_RATE_SET = 0x005,
+ SCMI_CLOCK_RATE_GET = 0x006,
+ SCMI_CLOCK_CONFIG_SET = 0x007,
+};
+
+/* Protocol attributes */
+#define SCMI_CLOCK_CLOCK_COUNT_MASK GENMASK(15, 0)
+#define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK GENMASK(23, 16)
+
+#define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \
+ ((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \
+ (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK)))
+
+struct scmi_clock_attributes_a2p {
+ uint32_t clock_id;
+};
+
+#define SCMI_CLOCK_NAME_LENGTH_MAX 16U
+
+struct scmi_clock_attributes_p2a {
+ int32_t status;
+ uint32_t attributes;
+ char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX];
+};
+
+/*
+ * Clock Rate Get
+ */
+
+struct scmi_clock_rate_get_a2p {
+ uint32_t clock_id;
+};
+
+struct scmi_clock_rate_get_p2a {
+ int32_t status;
+ uint32_t rate[2];
+};
+
+/*
+ * Clock Rate Set
+ */
+
+/* If set, set the new clock rate asynchronously */
+#define SCMI_CLOCK_RATE_SET_ASYNC_POS 0
+/* If set, do not send a delayed asynchronous response */
+#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS 1
+/* Round up, if set, otherwise round down */
+#define SCMI_CLOCK_RATE_SET_ROUND_UP_POS 2
+/* If set, the platform chooses the appropriate rounding mode */
+#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS 3
+
+#define SCMI_CLOCK_RATE_SET_ASYNC_MASK \
+ BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS)
+#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \
+ BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS)
+#define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \
+ BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS)
+#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \
+ BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS)
+
+struct scmi_clock_rate_set_a2p {
+ uint32_t flags;
+ uint32_t clock_id;
+ uint32_t rate[2];
+};
+
+struct scmi_clock_rate_set_p2a {
+ int32_t status;
+};
+
+/*
+ * Clock Config Set
+ */
+
+#define SCMI_CLOCK_CONFIG_SET_ENABLE_POS 0
+
+#define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \
+ BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS)
+
+struct scmi_clock_config_set_a2p {
+ uint32_t clock_id;
+ uint32_t attributes;
+};
+
+struct scmi_clock_config_set_p2a {
+ int32_t status;
+};
+
+/*
+ * Clock Describe Rates
+ */
+
+#define SCMI_CLOCK_RATE_FORMAT_RANGE 1U
+#define SCMI_CLOCK_RATE_FORMAT_LIST 0U
+
+#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK GENMASK_32(31, 16)
+#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS 16
+
+#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK BIT(12)
+#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS 12
+
+#define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK GENMASK_32(11, 0)
+
+#define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \
+ ( \
+ ((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \
+ (((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \
+ SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \
+ (((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \
+ SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \
+ )
+
+struct scmi_clock_rate {
+ uint32_t low;
+ uint32_t high;
+};
+
+struct scmi_clock_describe_rates_a2p {
+ uint32_t clock_id;
+ uint32_t rate_index;
+};
+
+struct scmi_clock_describe_rates_p2a {
+ int32_t status;
+ uint32_t num_rates_flags;
+ struct scmi_clock_rate rates[];
+};
+
+#endif /* SCMI_MSG_CLOCK_H */
diff --git a/drivers/st/scmi-msg/common.h b/drivers/st/scmi-msg/common.h
new file mode 100644
index 0000000..ef5953b
--- /dev/null
+++ b/drivers/st/scmi-msg/common.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#ifndef SCMI_MSG_COMMON_H
+#define SCMI_MSG_COMMON_H
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "base.h"
+#include "clock.h"
+#include "reset_domain.h"
+
+#define SCMI_VERSION 0x20000U
+#define SCMI_IMPL_VERSION 0U
+
+#define SCMI_PLAYLOAD_MAX 92U
+
+/*
+ * Copy name identifier in target buffer following the SCMI specification
+ * that state name identifier shall be a null terminated string.
+ */
+#define COPY_NAME_IDENTIFIER(_dst_array, _name) \
+ do { \
+ assert(strlen(_name) < sizeof(_dst_array)); \
+ strlcpy((_dst_array), (_name), sizeof(_dst_array)); \
+ } while (0)
+
+/* Common command identifiers shared by all procotols */
+enum scmi_common_message_id {
+ SCMI_PROTOCOL_VERSION = 0x000,
+ SCMI_PROTOCOL_ATTRIBUTES = 0x001,
+ SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002
+};
+
+/* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */
+struct scmi_protocol_version_p2a {
+ int32_t status;
+ uint32_t version;
+};
+
+/* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */
+struct scmi_protocol_attributes_p2a {
+ int32_t status;
+ uint32_t attributes;
+};
+
+/* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */
+struct scmi_protocol_message_attributes_a2p {
+ uint32_t message_id;
+};
+
+/* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */
+struct scmi_protocol_message_attributes_p2a {
+ int32_t status;
+ uint32_t attributes;
+};
+
+/*
+ * struct scmi_msg - SCMI message context
+ *
+ * @agent_id: SCMI agent ID, safely set from secure world
+ * @protocol_id: SCMI protocol ID for the related message, set by caller agent
+ * @message_id: SCMI message ID for the related message, set by caller agent
+ * @in: Address of the incoming message payload copied in secure memory
+ * @in_size: Byte length of the incoming message payload, set by caller agent
+ * @out: Address of of the output message payload message in non-secure memory
+ * @out_size: Byte length of the provisionned output buffer
+ * @out_size_out: Byte length of the output message payload
+ */
+struct scmi_msg {
+ unsigned int agent_id;
+ unsigned int protocol_id;
+ unsigned int message_id;
+ char *in;
+ size_t in_size;
+ char *out;
+ size_t out_size;
+ size_t out_size_out;
+};
+
+/*
+ * Type scmi_msg_handler_t is used by procotol drivers to safely find
+ * the handler function for the incoming message ID.
+ */
+typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg);
+
+/*
+ * scmi_msg_get_base_handler - Return a handler for a base message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg);
+
+/*
+ * scmi_msg_get_clock_handler - Return a handler for a clock message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg);
+
+/*
+ * scmi_msg_get_rstd_handler - Return a handler for a reset domain message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg);
+
+/*
+ * Process Read, process and write response for input SCMI message
+ *
+ * @msg: SCMI message context
+ */
+void scmi_process_message(struct scmi_msg *msg);
+
+/*
+ * Write SCMI response payload to output message shared memory
+ *
+ * @msg: SCMI message context
+ * @payload: Output message payload
+ * @size: Byte size of output message payload
+ */
+void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size);
+
+/*
+ * Write status only SCMI response payload to output message shared memory
+ *
+ * @msg: SCMI message context
+ * @status: SCMI status value returned to caller
+ */
+void scmi_status_response(struct scmi_msg *msg, int32_t status);
+#endif /* SCMI_MSG_COMMON_H */
diff --git a/drivers/st/scmi-msg/entry.c b/drivers/st/scmi-msg/entry.c
new file mode 100644
index 0000000..eefcb31
--- /dev/null
+++ b/drivers/st/scmi-msg/entry.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+
+#include <assert.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+
+#include "common.h"
+
+void scmi_status_response(struct scmi_msg *msg, int32_t status)
+{
+ assert(msg->out && msg->out_size >= sizeof(int32_t));
+
+ memcpy(msg->out, &status, sizeof(int32_t));
+ msg->out_size_out = sizeof(int32_t);
+}
+
+void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size)
+{
+ /*
+ * Output payload shall be at least the size of the status
+ * Output buffer shall be at least be the size of the status
+ * Output paylaod shall fit in output buffer
+ */
+ assert(payload && size >= sizeof(int32_t) && size <= msg->out_size &&
+ msg->out && msg->out_size >= sizeof(int32_t));
+
+ memcpy(msg->out, payload, size);
+ msg->out_size_out = size;
+}
+
+void scmi_process_message(struct scmi_msg *msg)
+{
+ scmi_msg_handler_t handler = NULL;
+
+ switch (msg->protocol_id) {
+ case SCMI_PROTOCOL_ID_BASE:
+ handler = scmi_msg_get_base_handler(msg);
+ break;
+ case SCMI_PROTOCOL_ID_CLOCK:
+ handler = scmi_msg_get_clock_handler(msg);
+ break;
+ case SCMI_PROTOCOL_ID_RESET_DOMAIN:
+ handler = scmi_msg_get_rstd_handler(msg);
+ break;
+ default:
+ break;
+ }
+
+ if (handler) {
+ handler(msg);
+ return;
+ }
+
+ ERROR("Agent %u Protocol 0x%x Message 0x%x: not supported",
+ msg->agent_id, msg->protocol_id, msg->message_id);
+
+ scmi_status_response(msg, SCMI_NOT_SUPPORTED);
+}
diff --git a/drivers/st/scmi-msg/reset_domain.c b/drivers/st/scmi-msg/reset_domain.c
new file mode 100644
index 0000000..b477302
--- /dev/null
+++ b/drivers/st/scmi-msg/reset_domain.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <cdefs.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+static bool message_id_is_supported(unsigned int message_id);
+
+#pragma weak plat_scmi_rstd_count
+#pragma weak plat_scmi_rstd_get_name
+#pragma weak plat_scmi_rstd_autonomous
+#pragma weak plat_scmi_rstd_set_state
+
+size_t plat_scmi_rstd_count(unsigned int agent_id __unused)
+{
+ return 0U;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused)
+{
+ return NULL;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned int state __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ bool assert_not_deassert __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+static void report_version(struct scmi_msg *msg)
+{
+ struct scmi_protocol_version_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN,
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+ struct scmi_protocol_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .attributes = plat_scmi_rstd_count(msg->agent_id),
+ };
+
+ if (msg->in_size != 0U) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+ struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+ struct scmi_protocol_message_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ /* For this protocol, attributes shall be zero */
+ .attributes = 0U,
+ };
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ if (!message_id_is_supported(in_args->message_id)) {
+ scmi_status_response(msg, SCMI_NOT_FOUND);
+ return;
+ }
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void reset_domain_attributes(struct scmi_msg *msg)
+{
+ struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in;
+ struct scmi_reset_domain_attributes_p2a return_values;
+ const char *name = NULL;
+ unsigned int domain_id = 0U;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id);
+
+ if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+ return;
+ }
+
+ name = plat_scmi_rstd_get_name(msg->agent_id, domain_id);
+ if (name == NULL) {
+ scmi_status_response(msg, SCMI_NOT_FOUND);
+ return;
+ }
+
+ zeromem(&return_values, sizeof(return_values));
+ COPY_NAME_IDENTIFIER(return_values.name, name);
+ return_values.status = SCMI_SUCCESS;
+ return_values.flags = 0U; /* Async and Notif are not supported */
+ return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT;
+
+ scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void reset_request(struct scmi_msg *msg)
+{
+ struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in;
+ struct scmi_reset_domain_request_p2a out_args = {
+ .status = SCMI_SUCCESS,
+ };
+ unsigned int domain_id = 0U;
+
+ if (msg->in_size != sizeof(*in_args)) {
+ scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+ return;
+ }
+
+ domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id);
+
+ if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) {
+ scmi_status_response(msg, SCMI_NOT_FOUND);
+ return;
+ }
+
+ if ((in_args->flags & SCMI_RESET_DOMAIN_AUTO) != 0U) {
+ out_args.status = plat_scmi_rstd_autonomous(msg->agent_id,
+ domain_id,
+ in_args->reset_state);
+ } else if ((in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) != 0U) {
+ out_args.status = plat_scmi_rstd_set_state(msg->agent_id,
+ domain_id, true);
+ } else {
+ out_args.status = plat_scmi_rstd_set_state(msg->agent_id,
+ domain_id, false);
+ }
+
+ if (out_args.status != SCMI_SUCCESS) {
+ scmi_status_response(msg, out_args.status);
+ } else {
+ scmi_write_response(msg, &out_args, sizeof(out_args));
+ }
+}
+
+static const scmi_msg_handler_t scmi_rstd_handler_table[] = {
+ [SCMI_PROTOCOL_VERSION] = report_version,
+ [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+ [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes,
+ [SCMI_RESET_DOMAIN_REQUEST] = reset_request,
+};
+
+static bool message_id_is_supported(unsigned int message_id)
+{
+ return (message_id < ARRAY_SIZE(scmi_rstd_handler_table)) &&
+ (scmi_rstd_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg)
+{
+ unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+ if (message_id >= ARRAY_SIZE(scmi_rstd_handler_table)) {
+ VERBOSE("Reset domain handle not found %u\n", msg->message_id);
+ return NULL;
+ }
+
+ return scmi_rstd_handler_table[message_id];
+}
diff --git a/drivers/st/scmi-msg/reset_domain.h b/drivers/st/scmi-msg/reset_domain.h
new file mode 100644
index 0000000..47bee5e
--- /dev/null
+++ b/drivers/st/scmi-msg/reset_domain.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+#ifndef SCMI_MSG_RESET_DOMAIN_H
+#define SCMI_MSG_RESET_DOMAIN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define SCMI_PROTOCOL_VERSION_RESET_DOMAIN 0x10000U
+
+#define SCMI_RESET_STATE_ARCH BIT(31)
+#define SCMI_RESET_STATE_IMPL 0U
+
+/*
+ * Identifiers of the SCMI Reset Domain Management Protocol commands
+ */
+enum scmi_reset_domain_command_id {
+ SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03,
+ SCMI_RESET_DOMAIN_REQUEST = 0x04,
+ SCMI_RESET_DOMAIN_NOTIFY = 0x05,
+};
+
+/*
+ * Identifiers of the SCMI Reset Domain Management Protocol responses
+ */
+enum scmi_reset_domain_response_id {
+ SCMI_RESET_ISSUED = 0x00,
+ SCMI_RESET_COMPLETE = 0x04,
+};
+
+/*
+ * PROTOCOL_ATTRIBUTES
+ */
+
+#define SCMI_RESET_DOMAIN_COUNT_MASK GENMASK_32(15, 0)
+
+struct scmi_reset_domain_protocol_attributes_p2a {
+ int32_t status;
+ uint32_t attributes;
+};
+
+/* Value for scmi_reset_domain_attributes_p2a:flags */
+#define SCMI_RESET_DOMAIN_ATTR_ASYNC BIT(31)
+#define SCMI_RESET_DOMAIN_ATTR_NOTIF BIT(30)
+
+/* Value for scmi_reset_domain_attributes_p2a:latency */
+#define SCMI_RESET_DOMAIN_ATTR_UNK_LAT 0x7fffffffU
+#define SCMI_RESET_DOMAIN_ATTR_MAX_LAT 0x7ffffffeU
+
+/* Macro for scmi_reset_domain_attributes_p2a:name */
+#define SCMI_RESET_DOMAIN_ATTR_NAME_SZ 16U
+
+struct scmi_reset_domain_attributes_a2p {
+ uint32_t domain_id;
+};
+
+struct scmi_reset_domain_attributes_p2a {
+ int32_t status;
+ uint32_t flags;
+ uint32_t latency;
+ char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ];
+};
+
+/*
+ * RESET
+ */
+
+/* Values for scmi_reset_domain_request_a2p:flags */
+#define SCMI_RESET_DOMAIN_ASYNC BIT(2)
+#define SCMI_RESET_DOMAIN_EXPLICIT BIT(1)
+#define SCMI_RESET_DOMAIN_AUTO BIT(0)
+
+struct scmi_reset_domain_request_a2p {
+ uint32_t domain_id;
+ uint32_t flags;
+ uint32_t reset_state;
+};
+
+struct scmi_reset_domain_request_p2a {
+ int32_t status;
+};
+
+/*
+ * RESET_NOTIFY
+ */
+
+/* Values for scmi_reset_notify_p2a:flags */
+#define SCMI_RESET_DOMAIN_DO_NOTIFY BIT(0)
+
+struct scmi_reset_domain_notify_a2p {
+ uint32_t domain_id;
+ uint32_t notify_enable;
+};
+
+struct scmi_reset_domain_notify_p2a {
+ int32_t status;
+};
+
+/*
+ * RESET_COMPLETE
+ */
+
+struct scmi_reset_domain_complete_p2a {
+ int32_t status;
+ uint32_t domain_id;
+};
+
+/*
+ * RESET_ISSUED
+ */
+
+struct scmi_reset_domain_issued_p2a {
+ uint32_t domain_id;
+ uint32_t reset_state;
+};
+
+#endif /* SCMI_MSG_RESET_DOMAIN_H */
diff --git a/drivers/st/scmi-msg/smt.c b/drivers/st/scmi-msg/smt.c
new file mode 100644
index 0000000..2d5cd73
--- /dev/null
+++ b/drivers/st/scmi-msg/smt.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/cassert.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include "common.h"
+
+/* Legacy SMT/SCMI messages are 128 bytes at most including SMT header */
+#define SCMI_PLAYLOAD_MAX 92U
+#define SCMI_PLAYLOAD_U32_MAX (SCMI_PLAYLOAD_MAX / sizeof(uint32_t))
+
+/**
+ * struct smt_header - SMT formatted header for SMT base shared memory transfer
+ *
+ * @status: Bit flags, see SMT_STATUS_*
+ * @flags: Bit flags, see SMT_FLAG_*
+ * @length: Byte size of message payload (variable) + ::message_header (32bit)
+ * payload: SCMI message payload data
+ */
+struct smt_header {
+ uint32_t reserved0;
+ uint32_t status;
+ uint64_t reserved1;
+ uint32_t flags;
+ uint32_t length; /* message_header + payload */
+ uint32_t message_header;
+ uint32_t payload[];
+};
+
+CASSERT(SCMI_PLAYLOAD_MAX + sizeof(struct smt_header) <= SMT_BUF_SLOT_SIZE,
+ assert_scmi_message_max_length_fits_in_smt_buffer_slot);
+
+/* Flag set in smt_header::status when SMT does not contain pending message */
+#define SMT_STATUS_FREE BIT(0)
+/* Flag set in smt_header::status when SMT reports an error */
+#define SMT_STATUS_ERROR BIT(1)
+
+/* Flag set in smt_header::flags when SMT uses interrupts */
+#define SMT_FLAG_INTR_ENABLED BIT(1)
+
+/* Bit fields packed in smt_header::message_header */
+#define SMT_MSG_ID_MASK GENMASK_32(7, 0)
+#define SMT_HDR_MSG_ID(_hdr) ((_hdr) & SMT_MSG_ID_MASK)
+
+#define SMT_MSG_TYPE_MASK GENMASK_32(9, 8)
+#define SMT_HDR_TYPE_ID(_hdr) (((_hdr) & SMT_MSG_TYPE_MASK) >> 8)
+
+#define SMT_MSG_PROT_ID_MASK GENMASK_32(17, 10)
+#define SMT_HDR_PROT_ID(_hdr) (((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10)
+
+/*
+ * Provision input message payload buffers for fastcall SMC context entries
+ * and for interrupt context execution entries.
+ */
+static uint32_t fast_smc_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX];
+static uint32_t interrupt_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX];
+
+/* SMP protection on channel access */
+static struct spinlock smt_channels_lock;
+
+/* If channel is not busy, set busy and return true, otherwise return false */
+static bool channel_set_busy(struct scmi_msg_channel *chan)
+{
+ bool channel_is_busy;
+
+ spin_lock(&smt_channels_lock);
+
+ channel_is_busy = chan->busy;
+
+ if (!channel_is_busy) {
+ chan->busy = true;
+ }
+
+ spin_unlock(&smt_channels_lock);
+
+ return !channel_is_busy;
+}
+
+static void channel_release_busy(struct scmi_msg_channel *chan)
+{
+ chan->busy = false;
+}
+
+static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *chan)
+{
+ return (struct smt_header *)chan->shm_addr;
+}
+
+/*
+ * Creates a SCMI message instance in secure memory and pushes it in the SCMI
+ * message drivers. Message structure contains SCMI protocol meta-data and
+ * references to input payload in secure memory and output message buffer
+ * in shared memory.
+ */
+static void scmi_proccess_smt(unsigned int agent_id, uint32_t *payload_buf)
+{
+ struct scmi_msg_channel *chan;
+ struct smt_header *smt_hdr;
+ size_t in_payload_size;
+ uint32_t smt_status;
+ struct scmi_msg msg;
+ bool error = true;
+
+ chan = plat_scmi_get_channel(agent_id);
+ if (chan == NULL) {
+ return;
+ }
+
+ smt_hdr = channel_to_smt_hdr(chan);
+ assert(smt_hdr);
+
+ smt_status = __atomic_load_n(&smt_hdr->status, __ATOMIC_RELAXED);
+
+ if (!channel_set_busy(chan)) {
+ VERBOSE("SCMI channel %u busy", agent_id);
+ goto out;
+ }
+
+ in_payload_size = __atomic_load_n(&smt_hdr->length, __ATOMIC_RELAXED) -
+ sizeof(smt_hdr->message_header);
+
+ if (in_payload_size > SCMI_PLAYLOAD_MAX) {
+ VERBOSE("SCMI payload too big %u", in_payload_size);
+ goto out;
+ }
+
+ if ((smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) != 0U) {
+ VERBOSE("SCMI channel bad status 0x%x",
+ smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE));
+ goto out;
+ }
+
+ /* Fill message */
+ zeromem(&msg, sizeof(msg));
+ msg.in = (char *)payload_buf;
+ msg.in_size = in_payload_size;
+ msg.out = (char *)smt_hdr->payload;
+ msg.out_size = chan->shm_size - sizeof(*smt_hdr);
+
+ assert((msg.out != NULL) && (msg.out_size >= sizeof(int32_t)));
+
+ /* Here the payload is copied in secure memory */
+ memcpy(msg.in, smt_hdr->payload, in_payload_size);
+
+ msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header);
+ msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header);
+ msg.agent_id = agent_id;
+
+ scmi_process_message(&msg);
+
+ /* Update message length with the length of the response message */
+ smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header);
+
+ channel_release_busy(chan);
+ error = false;
+
+out:
+ if (error) {
+ VERBOSE("SCMI error");
+ smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE;
+ } else {
+ smt_hdr->status |= SMT_STATUS_FREE;
+ }
+}
+
+void scmi_smt_fastcall_smc_entry(unsigned int agent_id)
+{
+ scmi_proccess_smt(agent_id,
+ fast_smc_payload[plat_my_core_pos()]);
+}
+
+void scmi_smt_interrupt_entry(unsigned int agent_id)
+{
+ scmi_proccess_smt(agent_id,
+ interrupt_payload[plat_my_core_pos()]);
+}
+
+/* Init a SMT header for a shared memory buffer: state it a free/no-error */
+void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan)
+{
+ if (chan != NULL) {
+ struct smt_header *smt_header = channel_to_smt_hdr(chan);
+
+ if (smt_header != NULL) {
+ memset(smt_header, 0, sizeof(*smt_header));
+ smt_header->status = SMT_STATUS_FREE;
+
+ return;
+ }
+ }
+
+ panic();
+}
diff --git a/fdts/corstone700.dts b/fdts/corstone700.dtsi
similarity index 88%
rename from fdts/corstone700.dts
rename to fdts/corstone700.dtsi
index 851f5e6..2372207 100644
--- a/fdts/corstone700.dts
+++ b/fdts/corstone700.dtsi
@@ -1,22 +1,18 @@
/*
- * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-/dts-v1/;
+#include <dt-bindings/interrupt-controller/arm-gic.h>
/ {
- model = "corstone700";
compatible = "arm,Corstone-700";
interrupt-parent = <&gic>;
#address-cells = <1>;
#size-cells = <1>;
- chosen {
- bootargs = "console=ttyAMA0 \
- loglevel=9";
- };
+ chosen { };
cpus {
#address-cells = <1>;
@@ -28,7 +24,6 @@
reg = <0>;
next-level-cache = <&L2_0>;
};
-
};
memory@80000000 {
@@ -99,7 +94,21 @@
<1 14 0xf08>,
<1 11 0xf08>,
<1 10 0xf08>;
+ };
+
+ refclk: refclk@1a220000 {
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x1a220000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ frame@1a230000 {
+ frame-number = <0>;
+ interrupts = <0 2 0xf04>;
+ reg = <0x1a230000 0x1000>;
};
+ };
mbox_es0mhu0: mhu@1b000000 {
compatible = "arm,mhuv2","arm,primecell";
@@ -149,5 +158,4 @@
<0x1A010314 0x4>;
reg-names = "rstreg", "streg";
};
-
};
diff --git a/fdts/corstone700_fpga.dts b/fdts/corstone700_fpga.dts
new file mode 100644
index 0000000..814d6a8
--- /dev/null
+++ b/fdts/corstone700_fpga.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "corstone700.dtsi"
+
+/ {
+ model = "corstone700-fpga";
+
+ ethernet: eth@40100000 {
+ compatible = "smsc,lan9115";
+ reg = <0x40100000 0x10000>;
+ phy-mode = "mii";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <2>;
+ smsc,irq-push-pull;
+ };
+};
+
+&refclk {
+ clock-frequency = <32000000>;
+};
diff --git a/fdts/corstone700_fvp.dts b/fdts/corstone700_fvp.dts
new file mode 100644
index 0000000..3b1202d
--- /dev/null
+++ b/fdts/corstone700_fvp.dts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "corstone700.dtsi"
+
+/ {
+ model = "corstone700-fvp";
+
+ /*
+ * Intel StrataFlash J3 NOR flash: 2 x 16-bit interleaved components
+ * Flash total size: 32 MB
+ * Allocated flash space: 8 MB
+ */
+
+ flash@8500000 {
+ compatible = "cfi-flash";
+ reg = <0x8500000 0x800000>;
+ bank-width = <4>;
+ device-width= <2>;
+ };
+
+ ethernet: eth@4010000 {
+ compatible = "smsc,lan91c111";
+ reg = <0x40100000 0x10000>;
+ phy-mode = "mii";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 116 0xf04>;
+ reg-io-width = <2>;
+ smsc,irq-push-pull;
+ };
+};
+
+&refclk {
+ clock-frequency = <50000000>;
+};
diff --git a/fdts/cot_descriptors.dtsi b/fdts/cot_descriptors.dtsi
new file mode 100644
index 0000000..9308e17
--- /dev/null
+++ b/fdts/cot_descriptors.dtsi
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tools_share/tbbr_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ trusted_boot_fw_cert: trusted_boot_fw_cert {
+ root-certificate;
+ image-id =<TRUSTED_BOOT_FW_CERT_ID>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ tb_fw_hash: tb_fw_hash {
+ oid = TRUSTED_BOOT_FW_HASH_OID;
+ };
+ tb_fw_config_hash: tb_fw_config_hash {
+ oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+ };
+ hw_config_hash: hw_config_hash {
+ oid = HW_CONFIG_HASH_OID;
+ };
+ fw_config_hash: fw_config_hash {
+ oid = FW_CONFIG_HASH_OID;
+ };
+ };
+
+ trusted_key_cert: trusted_key_cert {
+ root-certificate;
+ image-id = <TRUSTED_KEY_CERT_ID>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ trusted_world_pk: trusted_world_pk {
+ oid = TRUSTED_WORLD_PK_OID;
+ };
+ non_trusted_world_pk: non_trusted_world_pk {
+ oid = NON_TRUSTED_WORLD_PK_OID;
+ };
+ };
+
+ scp_fw_key_cert: scp_fw_key_cert {
+ image-id = <SCP_FW_KEY_CERT_ID>;
+ parent = <&trusted_key_cert>;
+ signing-key = <&trusted_world_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ scp_fw_content_pk: scp_fw_content_pk {
+ oid = SCP_FW_CONTENT_CERT_PK_OID;
+ };
+ };
+
+ scp_fw_content_cert: scp_fw_content_cert {
+ image-id = <SCP_FW_CONTENT_CERT_ID>;
+ parent = <&scp_fw_key_cert>;
+ signing-key = <&scp_fw_content_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ scp_fw_hash: scp_fw_hash {
+ oid = SCP_FW_HASH_OID;
+ };
+ };
+
+ soc_fw_key_cert: soc_fw_key_cert {
+ image-id = <SOC_FW_KEY_CERT_ID>;
+ parent = <&trusted_key_cert>;
+ signing-key = <&trusted_world_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+ soc_fw_content_pk: soc_fw_content_pk {
+ oid = SOC_FW_CONTENT_CERT_PK_OID;
+ };
+ };
+
+ soc_fw_content_cert: soc_fw_content_cert {
+ image-id = <SOC_FW_CONTENT_CERT_ID>;
+ parent = <&soc_fw_key_cert>;
+ signing-key = <&soc_fw_content_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ soc_fw_hash: soc_fw_hash {
+ oid = SOC_AP_FW_HASH_OID;
+ };
+ soc_fw_config_hash: soc_fw_config_hash {
+ oid = SOC_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ trusted_os_fw_key_cert: trusted_os_fw_key_cert {
+ image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
+ parent = <&trusted_key_cert>;
+ signing-key = <&trusted_world_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ tos_fw_content_pk: tos_fw_content_pk {
+ oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
+ };
+ };
+
+ trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+ image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+ parent = <&trusted_os_fw_key_cert>;
+ signing-key = <&tos_fw_content_pk>;
+ antirollback-counter = <&trusted_nv_counter>;
+
+ tos_fw_hash: tos_fw_hash {
+ oid = TRUSTED_OS_FW_HASH_OID;
+ };
+ tos_fw_extra1_hash: tos_fw_extra1_hash {
+ oid = TRUSTED_OS_FW_EXTRA1_HASH_OID;
+ };
+ tos_fw_extra2_hash: tos_fw_extra2_hash {
+ oid = TRUSTED_OS_FW_EXTRA2_HASH_OID;
+ };
+ tos_fw_config_hash: tos_fw_config_hash {
+ oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ non_trusted_fw_key_cert: non_trusted_fw_key_cert {
+ image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
+ parent = <&trusted_key_cert>;
+ signing-key = <&non_trusted_world_pk>;
+ antirollback-counter = <&non_trusted_nv_counter>;
+
+ nt_fw_content_pk: nt_fw_content_pk {
+ oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&non_trusted_fw_key_cert>;
+ signing-key = <&nt_fw_content_pk>;
+ antirollback-counter = <&non_trusted_nv_counter>;
+
+ nt_world_bl_hash: nt_world_bl_hash {
+ oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+ };
+ nt_fw_config_hash: nt_fw_config_hash {
+ oid = NON_TRUSTED_FW_CONFIG_HASH_OID;
+ };
+ };
+
+#if defined(SPD_spmd)
+ 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>;
+
+ sp_pkg1_hash: sp_pkg1_hash {
+ oid = SP_PKG1_HASH_OID;
+ };
+ sp_pkg2_hash: sp_pkg2_hash {
+ oid = SP_PKG2_HASH_OID;
+ };
+ sp_pkg3_hash: sp_pkg3_hash {
+ oid = SP_PKG3_HASH_OID;
+ };
+ sp_pkg4_hash: sp_pkg4_hash {
+ oid = SP_PKG4_HASH_OID;
+ };
+ sp_pkg5_hash: sp_pkg5_hash {
+ oid = SP_PKG5_HASH_OID;
+ };
+ sp_pkg6_hash: sp_pkg6_hash {
+ oid = SP_PKG6_HASH_OID;
+ };
+ sp_pkg7_hash: sp_pkg7_hash {
+ oid = SP_PKG7_HASH_OID;
+ };
+ sp_pkg8_hash: sp_pkg8_hash {
+ oid = SP_PKG8_HASH_OID;
+ };
+ };
+#endif
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ hw_config {
+ image-id = <HW_CONFIG_ID>;
+ parent = <&trusted_boot_fw_cert>;
+ hash = <&hw_config_hash>;
+ };
+
+ tb_fw_config {
+ image-id = <TB_FW_CONFIG_ID>;
+ parent = <&trusted_boot_fw_cert>;
+ hash = <&tb_fw_config_hash>;
+ };
+
+ scp_bl2_image {
+ image-id = <SCP_BL2_IMAGE_ID>;
+ parent = <&scp_fw_content_cert>;
+ hash = <&scp_fw_hash>;
+ };
+
+ bl31_image {
+ image-id = <BL31_IMAGE_ID>;
+ parent = <&soc_fw_content_cert>;
+ hash = <&soc_fw_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <SOC_FW_CONFIG_ID>;
+ parent = <&soc_fw_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ bl32_image {
+ image-id = <BL32_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_hash>;
+ };
+
+ bl32_extra1_image {
+ image-id = <BL32_EXTRA1_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_extra1_hash>;
+ };
+
+ bl32_extra2_image {
+ image-id = <BL32_EXTRA2_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_extra2_hash>;
+ };
+
+ tos_fw_config {
+ image-id = <TOS_FW_CONFIG_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_config_hash>;
+ };
+
+ bl33_image {
+ image-id = <BL33_IMAGE_ID>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_world_bl_hash>;
+ };
+
+ nt_fw_config {
+ image-id = <NT_FW_CONFIG_ID>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_fw_config_hash>;
+ };
+
+#if defined(SPD_spmd)
+ sp_pkg1 {
+ image-id = <SP_PKG1_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg1_hash>;
+ };
+
+ sp_pkg2 {
+ image-id = <SP_PKG2_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg2_hash>;
+ };
+
+ sp_pkg3 {
+ image-id = <SP_PKG3_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg3_hash>;
+ };
+
+ sp_pkg4 {
+ image-id = <SP_PKG4_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg4_hash>;
+ };
+
+ sp_pkg5 {
+ image-id = <SP_PKG5_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg5_hash>;
+ };
+
+ sp_pkg6 {
+ image-id = <SP_PKG6_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg6_hash>;
+ };
+
+ sp_pkg7 {
+ image-id = <SP_PKG7_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg7_hash>;
+ };
+
+ sp_pkg8 {
+ image-id = <SP_PKG8_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg8_hash>;
+ };
+#endif
+ };
+};
+
+non-volatile-counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ counters {
+ trusted_nv_counter: trusted_nv_counter {
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+ non_trusted_nv_counter: non_trusted_nv_counter {
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+ };
+ };
+};
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/fdts/optee_sp_manifest.dts b/fdts/optee_sp_manifest.dts
new file mode 100644
index 0000000..02a5ef3
--- /dev/null
+++ b/fdts/optee_sp_manifest.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
+ * that has additional optional properties defined.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-manifest-1.0";
+
+ /* Properties */
+ description = "op-tee";
+ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+ uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+ id = <1>;
+ execution-ctx-count = <8>;
+ exception-level = <2>; /* S-EL1 */
+ execution-state = <0>; /* AARCH64 */
+ load-address = <0x6280000>;
+ entrypoint-offset = <0x1000>;
+ xlat-granule = <0>; /* 4KiB */
+ boot-order = <0>;
+ messaging-method = <0>; /* Direct messaging only */
+ run-time-model = <1>; /* Run to completion */
+
+ /* Boot protocol */
+ gp-register-num = <0x0>;
+};
diff --git a/include/common/bl_common.ld.h b/include/common/bl_common.ld.h
index 208e3d6..ab3391a 100644
--- a/include/common/bl_common.ld.h
+++ b/include/common/bl_common.ld.h
@@ -101,6 +101,17 @@
__DATA_END__ = .; \
}
+/*
+ * .rela.dyn needs to come after .data for the read-elf utility to parse
+ * this section correctly.
+ */
+#define RELA_SECTION \
+ .rela.dyn : ALIGN(STRUCT_ALIGN) { \
+ __RELA_START__ = .; \
+ *(.rela*) \
+ __RELA_END__ = .; \
+ }
+
#if !(defined(IMAGE_BL31) && RECLAIM_INIT_CODE)
#define STACK_SECTION \
stacks (NOLOAD) : { \
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index 1d8da18..a571092 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -9,6 +9,8 @@
#ifndef FDT_WRAPPERS_H
#define FDT_WRAPPERS_H
+#include <libfdt_env.h>
+
/* Number of cells, given total length in bytes. Each cell is 4 bytes long */
#define NCELLS(len) ((len) / 4U)
@@ -37,4 +39,11 @@
uint64_t fdtw_translate_address(const void *dtb, int bus_node,
uint64_t base_address);
+static inline uint32_t fdt_blob_size(const void *dtb)
+{
+ const uint32_t *dtb_header = dtb;
+
+ return fdt32_to_cpu(dtb_header[1]);
+}
+
#endif /* FDT_WRAPPERS_H */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index 1f9aab1..b29b135 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -10,7 +10,15 @@
#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)
+#define SP_PKG4_ID (MAX_IMAGE_IDS + 4)
+#define SP_PKG5_ID (MAX_IMAGE_IDS + 5)
+#define SP_PKG6_ID (MAX_IMAGE_IDS + 6)
+#define SP_PKG7_ID (MAX_IMAGE_IDS + 7)
+#define SP_PKG8_ID (MAX_IMAGE_IDS + 8)
#define MAX_SP_IDS U(8)
#define MAX_NUMBER_IDS (MAX_IMAGE_IDS + MAX_SP_IDS + U(1))
#else
diff --git a/include/drivers/arm/css/css_scp.h b/include/drivers/arm/css/css_scp.h
index f3c08c5..2b506ea 100644
--- a/include/drivers/arm/css/css_scp.h
+++ b/include/drivers/arm/css/css_scp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,13 +40,13 @@
/*
* All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31
* usually resides except when ARM_BL31_IN_DRAM is
- * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into tb_fw_config.
+ * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into fw_config.
*/
CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2);
CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2);
-CASSERT(SCP_BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
-CASSERT(SCP_BL2U_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
+CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
+CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
#endif
#endif /* CSS_SCP_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 77dc350..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)
@@ -332,6 +332,18 @@
static inline void gicv3_end_of_interrupt_sel1(unsigned int id)
{
+ /*
+ * Interrupt request deassertion from peripheral to GIC happens
+ * by clearing interrupt condition by a write to the peripheral
+ * register. It is desired that the write transfer is complete
+ * before the core tries to change GIC state from 'AP/Active' to
+ * a new state on seeing 'EOI write'.
+ * Since ICC interface writes are not ordered against Device
+ * memory writes, a barrier is required to ensure the ordering.
+ * The dsb will also ensure *completion* of previous writes with
+ * DEVICE nGnRnE attribute.
+ */
+ dsbishst();
write_icc_eoir1_el1(id);
}
@@ -345,6 +357,18 @@
static inline void gicv3_end_of_interrupt(unsigned int id)
{
+ /*
+ * Interrupt request deassertion from peripheral to GIC happens
+ * by clearing interrupt condition by a write to the peripheral
+ * register. It is desired that the write transfer is complete
+ * before the core tries to change GIC state from 'AP/Active' to
+ * a new state on seeing 'EOI write'.
+ * Since ICC interface writes are not ordered against Device
+ * memory writes, a barrier is required to ensure the ordering.
+ * The dsb will also ensure *completion* of previous writes with
+ * DEVICE nGnRnE attribute.
+ */
+ dsbishst();
return write_icc_eoir0_el1(id);
}
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/auth/tbbr_cot_common.h b/include/drivers/auth/tbbr_cot_common.h
index 0ea5f65..a51faee 100644
--- a/include/drivers/auth/tbbr_cot_common.h
+++ b/include/drivers/auth/tbbr_cot_common.h
@@ -10,8 +10,6 @@
#include <drivers/auth/auth_mod.h>
extern unsigned char tb_fw_hash_buf[HASH_DER_LEN];
-extern unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
-extern unsigned char hw_config_hash_buf[HASH_DER_LEN];
extern unsigned char scp_fw_hash_buf[HASH_DER_LEN];
extern unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
@@ -23,7 +21,7 @@
extern auth_param_type_desc_t tb_fw_hash;
extern auth_param_type_desc_t tb_fw_config_hash;
-extern auth_param_type_desc_t hw_config_hash;
+extern auth_param_type_desc_t fw_config_hash;
extern const auth_img_desc_t trusted_boot_fw_cert;
extern const auth_img_desc_t hw_config;
diff --git a/include/drivers/brcm/scp.h b/include/drivers/brcm/scp.h
index b7b5bad..7806314 100644
--- a/include/drivers/brcm/scp.h
+++ b/include/drivers/brcm/scp.h
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef SCP_H_
+#ifndef SCP_H
#define SCP_H
#include <stdint.h>
diff --git a/include/drivers/marvell/cache_llc.h b/include/drivers/marvell/cache_llc.h
index 85babb8..d6dd653 100644
--- a/include/drivers/marvell/cache_llc.h
+++ b/include/drivers/marvell/cache_llc.h
@@ -13,19 +13,35 @@
#define CACHE_LLC_H
#define LLC_CTRL(ap) (MVEBU_LLC_BASE(ap) + 0x100)
+#define LLC_SECURE_CTRL(ap) (MVEBU_LLC_BASE(ap) + 0x10C)
#define LLC_SYNC(ap) (MVEBU_LLC_BASE(ap) + 0x700)
-#define L2X0_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x77C)
-#define L2X0_CLEAN_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7BC)
-#define L2X0_CLEAN_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7FC)
-#define LLC_TC0_LOCK(ap) (MVEBU_LLC_BASE(ap) + 0x920)
+#define LLC_BANKED_MNT_AHR(ap) (MVEBU_LLC_BASE(ap) + 0x724)
+#define LLC_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x77C)
+#define LLC_BLK_ALOC(ap) (MVEBU_LLC_BASE(ap) + 0x78c)
+#define LLC_CLEAN_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7BC)
+#define LLC_CLEAN_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7FC)
+#define LLC_TCN_LOCK(ap, tc) (MVEBU_LLC_BASE(ap) + 0x920 + 4 * (tc))
#define MASTER_LLC_CTRL LLC_CTRL(MVEBU_AP0)
-#define MASTER_L2X0_INV_WAY L2X0_INV_WAY(MVEBU_AP0)
-#define MASTER_LLC_TC0_LOCK LLC_TC0_LOCK(MVEBU_AP0)
+#define MASTER_LLC_INV_WAY LLC_INV_WAY(MVEBU_AP0)
+#define MASTER_LLC_TC0_LOCK LLC_TCN_LOCK(MVEBU_AP0, 0)
#define LLC_CTRL_EN 1
#define LLC_EXCLUSIVE_EN 0x100
-#define LLC_WAY_MASK 0xFFFFFFFF
+#define LLC_ALL_WAYS_MASK 0xFFFFFFFF
+
+/* AP806/AP807 - 1MB 8-ways LLC */
+#define LLC_WAYS 8
+#define LLC_WAY_MASK ((1 << LLC_WAYS) - 1)
+#define LLC_SIZE (1024 * 1024)
+#define LLC_WAY_SIZE (LLC_SIZE / LLC_WAYS)
+#define LLC_TC_NUM 15
+
+#define LLC_BLK_ALOC_WAY_ID(way) ((way) & 0x1f)
+#define LLC_BLK_ALOC_WAY_DATA_DSBL (0x0 << 6)
+#define LLC_BLK_ALOC_WAY_DATA_CLR (0x1 << 6)
+#define LLC_BLK_ALOC_WAY_DATA_SET (0x3 << 6)
+#define LLC_BLK_ALOC_BASE_ADDR(addr) ((addr) & ~(LLC_WAY_SIZE - 1))
#ifndef __ASSEMBLER__
void llc_cache_sync(int ap_index);
@@ -36,6 +52,11 @@
void llc_enable(int ap_index, int excl_mode);
int llc_is_exclusive(int ap_index);
void llc_runtime_enable(int ap_index);
-#endif
+#if LLC_SRAM
+int llc_sram_enable(int ap_index, int size);
+void llc_sram_disable(int ap_index);
+int llc_sram_test(int ap_index, int size, char *msg);
+#endif /* LLC_SRAM */
+#endif /* __ASSEMBLY__ */
#endif /* CACHE_LLC_H */
diff --git a/include/drivers/marvell/ccu.h b/include/drivers/marvell/ccu.h
index b0d1ec9..413ffb9 100644
--- a/include/drivers/marvell/ccu.h
+++ b/include/drivers/marvell/ccu.h
@@ -46,6 +46,7 @@
void ccu_dram_target_set(int ap_index, uint32_t target);
void ccu_save_win_all(int ap_id);
void ccu_restore_win_all(int ap_id);
+int ccu_is_win_enabled(int ap_index, uint32_t win_id);
#endif
#endif /* CCU_H */
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/drivers/st/scmi-msg.h b/include/drivers/st/scmi-msg.h
new file mode 100644
index 0000000..a9a99cf
--- /dev/null
+++ b/include/drivers/st/scmi-msg.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#ifndef SCMI_MSG_H
+#define SCMI_MSG_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* Minimum size expected for SMT based shared memory message buffers */
+#define SMT_BUF_SLOT_SIZE 128U
+
+/* A channel abstract a communication path between agent and server */
+struct scmi_msg_channel;
+
+/*
+ * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel
+ *
+ * @shm_addr: Address of the shared memory for the SCMI channel
+ * @shm_size: Byte size of the shared memory for the SCMI channel
+ * @busy: True when channel is busy, flase when channel is free
+ * @agent_name: Agent name, SCMI protocol exposes 16 bytes max, or NULL
+ */
+struct scmi_msg_channel {
+ uintptr_t shm_addr;
+ size_t shm_size;
+ bool busy;
+ const char *agent_name;
+};
+
+/*
+ * Initialize SMT memory buffer, called by platform at init for each
+ * agent channel using the SMT header format.
+ *
+ * @chan: Pointer to the channel shared memory to be initialized
+ */
+void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan);
+
+/*
+ * Process SMT formatted message in a fastcall SMC execution context.
+ * Called by platform on SMC entry. When returning, output message is
+ * available in shared memory for agent to read the response.
+ *
+ * @agent_id: SCMI agent ID the SMT belongs to
+ */
+void scmi_smt_fastcall_smc_entry(unsigned int agent_id);
+
+/*
+ * Process SMT formatted message in a secure interrupt execution context.
+ * Called by platform interrupt handler. When returning, output message is
+ * available in shared memory for agent to read the response.
+ *
+ * @agent_id: SCMI agent ID the SMT belongs to
+ */
+void scmi_smt_interrupt_entry(unsigned int agent_id);
+
+/* Platform callback functions */
+
+/*
+ * Return the SCMI channel related to an agent
+ * @agent_id: SCMI agent ID
+ * Return a pointer to channel on success, NULL otherwise
+ */
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id);
+
+/*
+ * Return how many SCMI protocols supported by the platform
+ * According to the SCMI specification, this function does not target
+ * a specific agent ID and shall return all platform known capabilities.
+ */
+size_t plat_scmi_protocol_count(void);
+
+/*
+ * Get the count and list of SCMI protocols (but base) supported for an agent
+ *
+ * @agent_id: SCMI agent ID
+ * Return a pointer to a null terminated array supported protocol IDs.
+ */
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id);
+
+/* Get the name of the SCMI vendor for the platform */
+const char *plat_scmi_vendor_name(void);
+
+/* Get the name of the SCMI sub-vendor for the platform */
+const char *plat_scmi_sub_vendor_name(void);
+
+/* Handlers for SCMI Clock protocol services */
+
+/*
+ * Return number of clock controllers for an agent
+ * @agent_id: SCMI agent ID
+ * Return number of clock controllers
+ */
+size_t plat_scmi_clock_count(unsigned int agent_id);
+
+/*
+ * Get clock controller string ID (aka name)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return pointer to name or NULL
+ */
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id);
+
+/*
+ * Get clock possible rate as an array of frequencies in Hertz.
+ *
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @rates: If NULL, function returns, else output rates array
+ * @nb_elts: Array size of @rates.
+ * Return an SCMI compliant error code
+ */
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+ unsigned long *rates, size_t *nb_elts);
+
+/*
+ * Get clock possible rate as range with regular steps in Hertz
+ *
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @min_max_step: 3 cell array for min, max and step rate data
+ * Return an SCMI compliant error code
+ */
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long *min_max_step);
+
+/*
+ * Get clock rate in Hertz
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return clock rate or 0 if not supported
+ */
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id);
+
+/*
+ * Set clock rate in Hertz
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @rate: Target clock frequency in Hertz
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id,
+ unsigned long rate);
+
+/*
+ * Get clock state (enabled or disabled)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code
+ */
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id);
+
+/*
+ * Get clock state (enabled or disabled)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @enable_not_disable: Enable clock if true, disable clock otherwise
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool enable_not_disable);
+
+/* Handlers for SCMI Reset Domain protocol services */
+
+/*
+ * Return number of reset domains for the agent
+ * @agent_id: SCMI agent ID
+ * Return number of reset domains
+ */
+size_t plat_scmi_rstd_count(unsigned int agent_id);
+
+/*
+ * Get reset domain string ID (aka name)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI reset domain ID
+ * Return pointer to name or NULL
+ */
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id);
+
+/*
+ * Perform a reset cycle on a target reset domain
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI reset domain ID
+ * @state: Target reset state (see SCMI specification, 0 means context loss)
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+ unsigned int state);
+
+/*
+ * Assert or deassert target reset domain
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI reset domain ID
+ * @assert_not_deassert: Assert domain if true, otherwise deassert domain
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool assert_not_deassert);
+
+#endif /* SCMI_MSG_H */
diff --git a/include/drivers/st/scmi.h b/include/drivers/st/scmi.h
new file mode 100644
index 0000000..ac5dc38
--- /dev/null
+++ b/include/drivers/st/scmi.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ */
+#ifndef SCMI_MSG_SCMI_H
+#define SCMI_MSG_SCMI_H
+
+#define SCMI_PROTOCOL_ID_BASE 0x10U
+#define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11U
+#define SCMI_PROTOCOL_ID_SYS_POWER 0x12U
+#define SCMI_PROTOCOL_ID_PERF 0x13U
+#define SCMI_PROTOCOL_ID_CLOCK 0x14U
+#define SCMI_PROTOCOL_ID_SENSOR 0x15U
+#define SCMI_PROTOCOL_ID_RESET_DOMAIN 0x16U
+
+/* SCMI error codes reported to agent through server-to-agent messages */
+#define SCMI_SUCCESS 0
+#define SCMI_NOT_SUPPORTED (-1)
+#define SCMI_INVALID_PARAMETERS (-2)
+#define SCMI_DENIED (-3)
+#define SCMI_NOT_FOUND (-4)
+#define SCMI_OUT_OF_RANGE (-5)
+#define SCMI_BUSY (-6)
+#define SCMI_COMMS_ERROR (-7)
+#define SCMI_GENERIC_ERROR (-8)
+#define SCMI_HARDWARE_ERROR (-9)
+#define SCMI_PROTOCOL_ERROR (-10)
+
+#endif /* SCMI_MSG_SCMI_H */
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
index 1ebd39f..c46892b 100644
--- a/include/drivers/st/stm32mp1_clk.h
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -59,4 +59,7 @@
void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
+#ifdef STM32MP_SHARED_RESOURCES
+void stm32mp1_register_clock_parents_secure(unsigned long id);
+#endif
#endif /* STM32MP1_CLK_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/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index a98c1b4..18f0125 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -88,7 +88,10 @@
/* Encrypted image identifier */
#define ENC_IMAGE_ID U(30)
+/* FW_CONFIG */
+#define FW_CONFIG_ID U(31)
+
/* Max Images */
-#define MAX_IMAGE_IDS U(31)
+#define MAX_IMAGE_IDS U(32)
#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h
index 7dc7e06..b522e8e 100644
--- a/include/lib/cpus/aarch64/cortex_a76.h
+++ b/include/lib/cpus/aarch64/cortex_a76.h
@@ -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.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -20,6 +20,7 @@
#define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2 (ULL(3) << 24)
#define CORTEX_A76_CPUECTLR_EL1_BIT_51 (ULL(1) << 51)
+#define CORTEX_A76_CPUECTLR_EL1_BIT_53 (ULL(1) << 53)
/*******************************************************************************
* CPU Auxiliary Control register specific definitions.
@@ -32,6 +33,8 @@
#define CORTEX_A76_CPUACTLR2_EL1 S3_0_C15_C1_1
+#define CORTEX_A76_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2)
+
#define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE (ULL(1) << 16)
#define CORTEX_A76_CPUACTLR3_EL1 S3_0_C15_C1_2
diff --git a/include/lib/cpus/aarch64/cortex_a77.h b/include/lib/cpus/aarch64/cortex_a77.h
index 0467ef3..bbd647c 100644
--- a/include/lib/cpus/aarch64/cortex_a77.h
+++ b/include/lib/cpus/aarch64/cortex_a77.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,6 +16,7 @@
* CPU Extended Control register specific definitions.
******************************************************************************/
#define CORTEX_A77_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_A77_CPUECTLR_EL1_BIT_53 (ULL(1) << 53)
/*******************************************************************************
* CPU Power Control register specific definitions.
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
index 09d2b59..917e053 100644
--- a/include/lib/fconf/fconf.h
+++ b/include/lib/fconf/fconf.h
@@ -43,8 +43,8 @@
int (*populate)(uintptr_t config);
};
-/* Load firmware configuration dtb */
-void fconf_load_config(void);
+/* This function supports to load tb_fw_config and fw_config dtb */
+int fconf_load_config(unsigned int image_id);
/* Top level populate function
*
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
index 0fda8c9..6f8da0d 100644
--- a/include/lib/fconf/fconf_dyn_cfg_getter.h
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -14,11 +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 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/lib/libc/stdbool.h b/include/lib/libc/stdbool.h
index e39aef7..b58334c 100644
--- a/include/lib/libc/stdbool.h
+++ b/include/lib/libc/stdbool.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
*/
@@ -9,8 +9,8 @@
#define bool _Bool
-#define true 1
-#define false 0
+#define true (0 < 1)
+#define false (0 > 1)
#define __bool_true_false_are_defined 1
diff --git a/include/lib/libfdt/fdt.h b/include/lib/libfdt/fdt.h
index ef7c86b..eb9edb7 100644
--- a/include/lib/libfdt/fdt.h
+++ b/include/lib/libfdt/fdt.h
@@ -1,55 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef FDT_H
#define FDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ASSEMBLER__
@@ -90,7 +45,7 @@
char data[0];
};
-#endif /* !__ASSEMBLER__ */
+#endif /* !__ASSEMBLER__*/
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
#define FDT_TAGSIZE sizeof(fdt32_t)
diff --git a/include/lib/libfdt/libfdt.h b/include/lib/libfdt/libfdt.h
index c8c00fa..48f375c 100644
--- a/include/lib/libfdt/libfdt.h
+++ b/include/lib/libfdt/libfdt.h
@@ -1,54 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_H
#define LIBFDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <libfdt_env.h>
@@ -90,8 +45,9 @@
/* Error codes: codes for bad device tree blobs */
#define FDT_ERR_TRUNCATED 8
- /* FDT_ERR_TRUNCATED: Structure block of the given device tree
- * ends without an FDT_END tag. */
+ /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+ * terminated (overflows, goes outside allowed bounds, or
+ * isn't properly terminated). */
#define FDT_ERR_BADMAGIC 9
/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
* device tree at all - it is missing the flattened device
@@ -137,7 +93,15 @@
/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
* phandle available anymore without causing an overflow */
-#define FDT_ERR_MAX 17
+#define FDT_ERR_BADFLAGS 18
+ /* FDT_ERR_BADFLAGS: The function was passed a flags field that
+ * contains invalid flags or an invalid combination of flags. */
+
+#define FDT_ERR_MAX 18
+
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+ /* Valid values for phandles range from 1 to 2^32-2. */
/**********************************************************************/
/* Low-level functions (you probably don't need these) */
@@ -153,6 +117,61 @@
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+/*
+ * Alignment helpers:
+ * These helpers access words from a device tree blob. They're
+ * built to work even with unaligned pointers on platforms (ike
+ * ARM) that don't like unaligned loads and stores
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint32_t)bp[0] << 24)
+ | ((uint32_t)bp[1] << 16)
+ | ((uint32_t)bp[2] << 8)
+ | bp[3];
+}
+
+static inline void fdt32_st(void *property, uint32_t value)
+{
+ uint8_t *bp = (uint8_t *)property;
+
+ bp[0] = value >> 24;
+ bp[1] = (value >> 16) & 0xff;
+ bp[2] = (value >> 8) & 0xff;
+ bp[3] = value & 0xff;
+}
+
+static inline uint64_t fdt64_ld(const fdt64_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint64_t)bp[0] << 56)
+ | ((uint64_t)bp[1] << 48)
+ | ((uint64_t)bp[2] << 40)
+ | ((uint64_t)bp[3] << 32)
+ | ((uint64_t)bp[4] << 24)
+ | ((uint64_t)bp[5] << 16)
+ | ((uint64_t)bp[6] << 8)
+ | bp[7];
+}
+
+static inline void fdt64_st(void *property, uint64_t value)
+{
+ uint8_t *bp = (uint8_t *)property;
+
+ bp[0] = value >> 56;
+ bp[1] = (value >> 48) & 0xff;
+ bp[2] = (value >> 40) & 0xff;
+ bp[3] = (value >> 32) & 0xff;
+ bp[4] = (value >> 24) & 0xff;
+ bp[5] = (value >> 16) & 0xff;
+ bp[6] = (value >> 8) & 0xff;
+ bp[7] = value & 0xff;
+}
+
/**********************************************************************/
/* Traversal functions */
/**********************************************************************/
@@ -195,7 +214,7 @@
* ...
* }
*
- * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
* Error handling
* }
*
@@ -213,7 +232,7 @@
/* General functions */
/**********************************************************************/
#define fdt_get_header(fdt, field) \
- (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+ (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
@@ -244,18 +263,32 @@
#undef fdt_set_hdr_
/**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_header_size - return the size of the tree's header
+ * @fdt: pointer to a flattened device tree
+ */
+size_t fdt_header_size(const void *fdt);
+
+/**
+ * fdt_header_size_ - internal function which takes a version number
+ */
+size_t fdt_header_size_(uint32_t version);
+
+/**
+ * fdt_check_header - sanity check a device tree header
+
* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
*
* returns:
* 0, if the buffer appears to contain a valid device tree
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings, as above
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_TRUNCATED, standard meanings, as above
*/
int fdt_check_header(const void *fdt);
@@ -284,6 +317,24 @@
/* Read-only functions */
/**********************************************************************/
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ * a pointer to the string, on success
+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
/**
* fdt_string - retrieve a string from the strings block of a device tree
* @fdt: pointer to the device tree blob
@@ -294,11 +345,25 @@
*
* returns:
* a pointer to the string, on success
- * NULL, if stroffset is out of bounds
+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
*/
const char *fdt_string(const void *fdt, int stroffset);
/**
+ * fdt_find_max_phandle - find and return the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the highest phandle value found in the tree
+ *
+ * fdt_find_max_phandle() finds the highest phandle value in the given device
+ * tree. The value returned in @phandle is only valid if the function returns
+ * success.
+ *
+ * returns:
+ * 0 on success or a negative error code on failure
+ */
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
+
+/**
* fdt_get_max_phandle - retrieves the highest phandle in a tree
* @fdt: pointer to the device tree blob
*
@@ -306,12 +371,39 @@
* device tree. This will ignore badly formatted phandles, or phandles
* with a value of 0 or -1.
*
+ * This function is deprecated in favour of fdt_find_max_phandle().
+ *
* returns:
* the highest phandle on success
* 0, if no phandle was found in the device tree
* -1, if an error occurred
*/
-uint32_t fdt_get_max_phandle(const void *fdt);
+static inline uint32_t fdt_get_max_phandle(const void *fdt)
+{
+ uint32_t phandle;
+ int err;
+
+ err = fdt_find_max_phandle(fdt, &phandle);
+ if (err < 0)
+ return (uint32_t)-1;
+
+ return phandle;
+}
+
+/**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ * 0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
/**
* fdt_num_mem_rsv - retrieve the number of memory reserve map entries
@@ -503,7 +595,7 @@
* ...
* }
*
- * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
* Error handling
* }
*
@@ -606,7 +698,7 @@
/**
* fdt_getprop_by_offset - retrieve the value of a property at a given offset
* @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
+ * @offset: offset of the property to read
* @namep: pointer to a string variable (will be overwritten) or NULL
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
@@ -1090,7 +1182,7 @@
*
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
- * 2, if the node has no #address-cells property
+ * 1, if the node has no #size-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #size-cells property
* -FDT_ERR_BADMAGIC,
@@ -1297,7 +1389,45 @@
/* Sequential write functions */
/**********************************************************************/
+/* fdt_create_with_flags flags */
+#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
+ /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
+ * names in the fdt. This can result in faster creation times, but
+ * a larger fdt. */
+
+#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP)
+
+/**
+ * fdt_create_with_flags - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
+ *
+ * fdt_create_with_flags() begins the process of creating a new fdt with
+ * the sequential write interface.
+ *
+ * fdt creation process must end with fdt_finished() to produce a valid fdt.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ * -FDT_ERR_BADFLAGS, flags is not valid
+ */
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
+
+/**
+ * fdt_create - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ *
+ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ */
int fdt_create(void *buf, int bufsize);
+
int fdt_resize(void *fdt, void *buf, int bufsize);
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
int fdt_finish_reservemap(void *fdt);
@@ -1313,10 +1443,13 @@
fdt64_t tmp = cpu_to_fdt64(val);
return fdt_property(fdt, name, &tmp, sizeof(tmp));
}
+
+#ifndef SWIG /* Not available in Python */
static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
{
return fdt_property_u32(fdt, name, val);
}
+#endif
/**
* fdt_property_placeholder - add a new property and return a ptr to its value
@@ -1766,6 +1899,43 @@
fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
+ * fdt_appendprop_addrrange - append a address range property
+ * @fdt: pointer to the device tree blob
+ * @parent: offset of the parent node
+ * @nodeoffset: offset of the node to add a property at
+ * @name: name of property
+ * @addr: start address of a given range
+ * @size: size of a given range
+ *
+ * fdt_appendprop_addrrange() appends an address range value (start
+ * address and size) to the value of the named property in the given
+ * node, or creates a new property with that value if it does not
+ * already exist.
+ * If "name" is not specified, a default "reg" is used.
+ * Cell sizes are determined by parent's #address-cells and #size-cells.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ * #address-cells property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain a new property
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+ const char *name, uint64_t addr, uint64_t size);
+
+/**
* fdt_delprop - delete a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
diff --git a/include/lib/libfdt/libfdt_env.h b/include/lib/libfdt/libfdt_env.h
index bd24746..73b6d40 100644
--- a/include/lib/libfdt/libfdt_env.h
+++ b/include/lib/libfdt/libfdt_env.h
@@ -1,61 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#ifdef __CHECKER__
#define FDT_FORCE __attribute__((force))
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 89f7c61..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)
@@ -346,24 +353,25 @@
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
/*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
* and limit. Leave enough space of BL2 meminfo.
*/
-#define ARM_TB_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
+#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT ((ARM_BL_RAM_BASE + PAGE_SIZE) \
+ + (PAGE_SIZE / 2U))
/*
* Boot parameters passed from BL2 to BL31/BL32 are stored here
*/
-#define ARM_BL2_MEM_DESC_BASE ARM_TB_FW_CONFIG_LIMIT
-#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE + \
- (PAGE_SIZE / 2U))
+#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_TB_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
*/
-#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
/*******************************************************************************
* BL1 specific defines.
@@ -461,7 +469,7 @@
* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
* the page reserved for fw_configs) to BL32
*/
-# define BL32_BASE ARM_FW_CONFIG_LIMIT
+# define BL32_BASE ARM_FW_CONFIGS_LIMIT
# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
# else
/* Put BL32 below BL2 in the Trusted SRAM.*/
@@ -505,7 +513,7 @@
# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE
# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE
# define TSP_PROGBITS_LIMIT BL31_BASE
-# define BL32_BASE ARM_FW_CONFIG_LIMIT
+# define BL32_BASE ARM_FW_CONFIGS_LIMIT
# define BL32_LIMIT BL31_BASE
# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
index 38c30fb..236254b 100644
--- a/include/plat/arm/common/fconf_arm_sp_getter.h
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -13,7 +13,7 @@
/* arm_sp getter */
#define arm__sp_getter(prop) arm_sp.prop
-#define ARM_SP_MAX_SIZE U(0x10000)
+#define ARM_SP_MAX_SIZE U(0x80000)
struct arm_sp_t {
unsigned int number_of_sp;
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 1b59795..95fc18e 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -190,7 +190,7 @@
void arm_bl1_plat_arch_setup(void);
/* BL2 utility functions */
-void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, struct meminfo *mem_layout);
+void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout);
void arm_bl2_platform_setup(void);
void arm_bl2_plat_arch_setup(void);
uint32_t arm_get_spsr_for_bl32_entry(void);
@@ -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/include/plat/marvell/armada/a3700/common/armada_common.h b/include/plat/marvell/armada/a3k/common/armada_common.h
similarity index 100%
rename from include/plat/marvell/armada/a3700/common/armada_common.h
rename to include/plat/marvell/armada/a3k/common/armada_common.h
diff --git a/include/plat/marvell/armada/a3700/common/board_marvell_def.h b/include/plat/marvell/armada/a3k/common/board_marvell_def.h
similarity index 95%
rename from include/plat/marvell/armada/a3700/common/board_marvell_def.h
rename to include/plat/marvell/armada/a3k/common/board_marvell_def.h
index 1782596..bc3e04f 100644
--- a/include/plat/marvell/armada/a3700/common/board_marvell_def.h
+++ b/include/plat/marvell/armada/a3k/common/board_marvell_def.h
@@ -71,6 +71,4 @@
#define MAX_IO_DEVICES 3
#define MAX_IO_HANDLES 4
-#define PLAT_MARVELL_TRUSTED_SRAM_SIZE 0x80000 /* 512 KB */
-
#endif /* BOARD_MARVELL_DEF_H */
diff --git a/include/plat/marvell/armada/a3700/common/marvell_def.h b/include/plat/marvell/armada/a3k/common/marvell_def.h
similarity index 89%
rename from include/plat/marvell/armada/a3700/common/marvell_def.h
rename to include/plat/marvell/armada/a3k/common/marvell_def.h
index eb13ba8..1394c05 100644
--- a/include/plat/marvell/armada/a3700/common/marvell_def.h
+++ b/include/plat/marvell/armada/a3k/common/marvell_def.h
@@ -49,15 +49,17 @@
*/
#define MARVELL_LOCAL_STATE_OFF 2
+/* This leaves a gap between end of DRAM and start of ROM block */
+#define MARVELL_TRUSTED_DRAM_SIZE 0x80000 /* 512 KB */
+
/* The first 4KB of Trusted SRAM are used as shared memory */
-#define MARVELL_TRUSTED_SRAM_BASE PLAT_MARVELL_ATF_BASE
-#define MARVELL_SHARED_RAM_BASE MARVELL_TRUSTED_SRAM_BASE
+#define MARVELL_SHARED_RAM_BASE PLAT_MARVELL_ATF_BASE
#define MARVELL_SHARED_RAM_SIZE 0x00001000 /* 4 KB */
/* The remaining Trusted SRAM is used to load the BL images */
#define MARVELL_BL_RAM_BASE (MARVELL_SHARED_RAM_BASE + \
MARVELL_SHARED_RAM_SIZE)
-#define MARVELL_BL_RAM_SIZE (PLAT_MARVELL_TRUSTED_SRAM_SIZE - \
+#define MARVELL_BL_RAM_SIZE (MARVELL_TRUSTED_DRAM_SIZE - \
MARVELL_SHARED_RAM_SIZE)
#define MARVELL_DRAM_BASE ULL(0x0)
@@ -65,7 +67,7 @@
#define MARVELL_DRAM_END (MARVELL_DRAM_BASE + \
MARVELL_DRAM_SIZE - 1)
-#define MARVELL_IRQ_SEC_PHY_TIMER 29
+#define MARVELL_IRQ_SEC_PHY_TIMER 29
#define MARVELL_IRQ_SEC_SGI_0 8
#define MARVELL_IRQ_SEC_SGI_1 9
@@ -86,7 +88,6 @@
MARVELL_DRAM_SIZE, \
MT_MEMORY | MT_RW | MT_NS)
-
/*
* The number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
@@ -173,5 +174,15 @@
#define BL31_LIMIT (MARVELL_BL_RAM_BASE + \
MARVELL_BL_RAM_SIZE)
+/*****************************************************************************
+ * BL32 specific defines.
+ *****************************************************************************
+ */
+#define BL32_BASE PLAT_MARVELL_TRUSTED_RAM_BASE
+#define BL32_LIMIT (BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
#endif /* MARVELL_DEF_H */
diff --git a/include/plat/marvell/armada/a3700/common/plat_marvell.h b/include/plat/marvell/armada/a3k/common/plat_marvell.h
similarity index 100%
rename from include/plat/marvell/armada/a3700/common/plat_marvell.h
rename to include/plat/marvell/armada/a3k/common/plat_marvell.h
diff --git a/include/plat/marvell/armada/a8k/common/board_marvell_def.h b/include/plat/marvell/armada/a8k/common/board_marvell_def.h
index 0da56e7..7e90f5f 100644
--- a/include/plat/marvell/armada/a8k/common/board_marvell_def.h
+++ b/include/plat/marvell/armada/a8k/common/board_marvell_def.h
@@ -71,7 +71,4 @@
#define MAX_IO_DEVICES 3
#define MAX_IO_HANDLES 4
-#define PLAT_MARVELL_TRUSTED_SRAM_SIZE 0x80000 /* 512 KB */
-
-
#endif /* BOARD_MARVELL_DEF_H */
diff --git a/include/plat/marvell/armada/a8k/common/marvell_def.h b/include/plat/marvell/armada/a8k/common/marvell_def.h
index 4eda01f..1245b88 100644
--- a/include/plat/marvell/armada/a8k/common/marvell_def.h
+++ b/include/plat/marvell/armada/a8k/common/marvell_def.h
@@ -47,15 +47,17 @@
*/
#define MARVELL_LOCAL_STATE_OFF 2
+/* This leaves a gap between end of DRAM and start of ROM block */
+#define MARVELL_TRUSTED_DRAM_SIZE 0x80000 /* 512 KB */
+
/* The first 4KB of Trusted SRAM are used as shared memory */
-#define MARVELL_TRUSTED_SRAM_BASE PLAT_MARVELL_ATF_BASE
-#define MARVELL_SHARED_RAM_BASE MARVELL_TRUSTED_SRAM_BASE
+#define MARVELL_SHARED_RAM_BASE PLAT_MARVELL_ATF_BASE
#define MARVELL_SHARED_RAM_SIZE 0x00001000 /* 4 KB */
/* The remaining Trusted SRAM is used to load the BL images */
#define MARVELL_BL_RAM_BASE (MARVELL_SHARED_RAM_BASE + \
MARVELL_SHARED_RAM_SIZE)
-#define MARVELL_BL_RAM_SIZE (PLAT_MARVELL_TRUSTED_SRAM_SIZE - \
+#define MARVELL_BL_RAM_SIZE (MARVELL_TRUSTED_DRAM_SIZE - \
MARVELL_SHARED_RAM_SIZE)
/* Non-shared DRAM */
#define MARVELL_DRAM_BASE ULL(0x0)
@@ -75,9 +77,40 @@
#define MARVELL_IRQ_SEC_SGI_6 14
#define MARVELL_IRQ_SEC_SGI_7 15
-#define MARVELL_MAP_SHARED_RAM MAP_REGION_FLAT( \
- MARVELL_SHARED_RAM_BASE,\
- MARVELL_SHARED_RAM_SIZE,\
+#ifdef SPD_opteed
+/*
+ * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to
+ * load/authenticate the trusted os extra image. The first 512KB of
+ * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading
+ * for OPTEE is paged image which only include the paging part using
+ * virtual memory but without "init" data. OPTEE will copy the "init" data
+ * (from pager image) to the first 512KB of TZC_DRAM, and then copy the
+ * extra image behind the "init" data.
+ */
+#define MARVELL_OPTEE_PAGEABLE_LOAD_BASE \
+ (PLAT_MARVELL_TRUSTED_RAM_BASE + \
+ PLAT_MARVELL_TRUSTED_RAM_SIZE - \
+ MARVELL_OPTEE_PAGEABLE_LOAD_SIZE)
+#define MARVELL_OPTEE_PAGEABLE_LOAD_SIZE 0x400000
+#define MARVELL_OPTEE_PAGEABLE_LOAD_MEM \
+ MAP_REGION_FLAT( \
+ MARVELL_OPTEE_PAGEABLE_LOAD_BASE, \
+ MARVELL_OPTEE_PAGEABLE_LOAD_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Map the memory for the OP-TEE core (also known as OP-TEE pager when paging
+ * support is enabled).
+ */
+#define MARVELL_MAP_OPTEE_CORE_MEM MAP_REGION_FLAT( \
+ BL32_BASE, \
+ BL32_LIMIT - BL32_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif /* SPD_opteed */
+
+#define MARVELL_MAP_SECURE_RAM MAP_REGION_FLAT( \
+ MARVELL_SHARED_RAM_BASE, \
+ MARVELL_SHARED_RAM_SIZE, \
MT_MEMORY | MT_RW | MT_SECURE)
#define MARVELL_MAP_DRAM MAP_REGION_FLAT( \
@@ -85,7 +118,6 @@
MARVELL_DRAM_SIZE, \
MT_MEMORY | MT_RW | MT_NS)
-
/*
* The number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
@@ -177,5 +209,14 @@
#define BL31_LIMIT (MARVELL_BL_RAM_BASE + \
MARVELL_BL_RAM_SIZE)
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#define BL32_BASE PLAT_MARVELL_TRUSTED_RAM_BASE
+#define BL32_LIMIT (BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
#endif /* MARVELL_DEF_H */
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index fe32175..7285077 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -12,13 +12,13 @@
#include <tools_share/uuid.h>
/* FFA error codes. */
-#define FFA_ERROR_NOT_SUPPORTED -1
+#define FFA_ERROR_NOT_SUPPORTED -1
#define FFA_ERROR_INVALID_PARAMETER -2
#define FFA_ERROR_NO_MEMORY -3
#define FFA_ERROR_BUSY -4
#define FFA_ERROR_INTERRUPTED -5
#define FFA_ERROR_DENIED -6
-#define FFA_ERROR_RETRY -7
+#define FFA_ERROR_RETRY -7
/* The macros below are used to identify FFA calls from the SMC function ID */
#define FFA_FNUM_MIN_VALUE U(0x60)
@@ -30,13 +30,15 @@
/* FFA_VERSION helpers */
#define FFA_VERSION_MAJOR U(1)
-#define FFA_VERSION_MAJOR_SHIFT 16
+#define FFA_VERSION_MAJOR_SHIFT 16
#define FFA_VERSION_MAJOR_MASK U(0x7FFF)
#define FFA_VERSION_MINOR U(0)
-#define FFA_VERSION_MINOR_SHIFT 0
+#define FFA_VERSION_MINOR_SHIFT 0
#define FFA_VERSION_MINOR_MASK U(0xFFFF)
+#define FFA_VERSION_BIT31_MASK U(0x1u << 31)
-#define MAKE_FFA_VERSION(major, minor) \
+
+#define MAKE_FFA_VERSION(major, minor) \
((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \
(((minor) & FFA_VERSION_MINOR_MASK) << FFA_VERSION_MINOR_SHIFT))
#define FFA_VERSION_COMPILED MAKE_FFA_VERSION(FFA_VERSION_MAJOR, \
diff --git a/include/tools_share/firmware_image_package.h b/include/tools_share/firmware_image_package.h
index 75f3cc6..7342c0c 100644
--- a/include/tools_share/firmware_image_package.h
+++ b/include/tools_share/firmware_image_package.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -77,6 +77,8 @@
{{0x26, 0x25, 0x7c, 0x1a}, {0xdb, 0xc6}, {0x7f, 0x47}, 0x8d, 0x96, {0xc4, 0xc4, 0xb0, 0x24, 0x80, 0x21} }
#define UUID_NT_FW_CONFIG \
{{0x28, 0xda, 0x98, 0x15}, {0x93, 0xe8}, {0x7e, 0x44}, 0xac, 0x66, {0x1a, 0xaf, 0x80, 0x15, 0x50, 0xf9} }
+#define UUID_FW_CONFIG \
+ {{0x58, 0x07, 0xe1, 0x6a}, {0x84, 0x59}, {0x47, 0xbe}, 0x8e, 0xd5, {0x64, 0x8e, 0x8d, 0xdd, 0xab, 0x0e} }
typedef struct fip_toc_header {
uint32_t name;
diff --git a/include/tools_share/tbbr_oid.h b/include/tools_share/tbbr_oid.h
index 24a8f39..37d87d3 100644
--- a/include/tools_share/tbbr_oid.h
+++ b/include/tools_share/tbbr_oid.h
@@ -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
*/
@@ -43,6 +43,7 @@
#define TRUSTED_BOOT_FW_HASH_OID "1.3.6.1.4.1.4128.2100.201"
#define TRUSTED_BOOT_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.202"
#define HW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.203"
+#define FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.204"
/*
* Trusted Key Certificate
diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S
index 6d2ec1c..e9734ac 100644
--- a/lib/aarch32/misc_helpers.S
+++ b/lib/aarch32/misc_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -149,17 +149,16 @@
blo m_loop1
ldr r3, [r1], #4
str r3, [r0], #4
- sub r2, r2, #4
- b m_loop4
+ subs r2, r2, #4
+ bne m_loop4
+ bx lr
+
/* copy byte per byte */
m_loop1:
- cmp r2,#0
- beq m_end
ldrb r3, [r1], #1
strb r3, [r0], #1
subs r2, r2, #1
bne m_loop1
-m_end:
bx lr
endfunc memcpy4
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index baefa46..10011f7 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -392,6 +392,62 @@
#endif
endfunc check_errata_1286807
+ /* --------------------------------------------------
+ * Errata workaround for Cortex A76 Errata #1791580.
+ * This applies to revisions <= r4p0 of Cortex A76.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a76_1791580_wa
+ /* Compare x0 against revision r4p0 */
+ mov x17, x30
+ bl check_errata_1791580
+ cbz x0, 1f
+ mrs x1, CORTEX_A76_CPUACTLR2_EL1
+ orr x1, x1, CORTEX_A76_CPUACTLR2_EL1_BIT_2
+ msr CORTEX_A76_CPUACTLR2_EL1, x1
+ isb
+1:
+ ret x17
+endfunc errata_a76_1791580_wa
+
+func check_errata_1791580
+ /* Applies to everything <=r4p0. */
+ mov x1, #0x40
+ b cpu_rev_var_ls
+endfunc check_errata_1791580
+
+ /* --------------------------------------------------
+ * Errata Workaround for Cortex A76 Errata #1800710.
+ * This applies to revision <= r4p0 of Cortex A76.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a76_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, CORTEX_A76_CPUECTLR_EL1
+ orr x1, x1, CORTEX_A76_CPUECTLR_EL1_BIT_53
+ msr CORTEX_A76_CPUECTLR_EL1, x1
+ isb
+1:
+ ret x17
+endfunc errata_a76_1800710_wa
+
+func check_errata_1800710
+ /* Applies to everything <= r4p0 */
+ mov x1, #0x40
+ b cpu_rev_var_ls
+endfunc check_errata_1800710
+
func check_errata_cve_2018_3639
#if WORKAROUND_CVE_2018_3639
mov x0, #ERRATA_APPLIES
@@ -449,6 +505,16 @@
bl errata_a76_1262888_wa
#endif
+#if ERRATA_A76_1791580
+ mov x0, x18
+ bl errata_a76_1791580_wa
+#endif
+
+#if ERRATA_A76_1800710
+ mov x0, x18
+ bl errata_a76_1800710_wa
+#endif
+
#if WORKAROUND_CVE_2018_3639
/* If the PE implements SSBS, we don't need the dynamic workaround */
mrs x0, id_aa64pfr1_el1
@@ -529,6 +595,8 @@
report_errata ERRATA_A76_1262888, cortex_a76, 1262888
report_errata ERRATA_A76_1275112, cortex_a76, 1275112
report_errata ERRATA_A76_1286807, cortex_a76, 1286807
+ report_errata ERRATA_A76_1791580, cortex_a76, 1791580
+ report_errata ERRATA_A76_1800710, cortex_a76, 1800710
report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index f3fd5e1..0c30460 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,53 @@
#error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+ /* --------------------------------------------------
+ * Errata Workaround for Cortex A77 Errata #1800714.
+ * This applies to revision <= r1p1 of Cortex A77.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a77_1800714_wa
+ /* Compare x0 against revision <= r1p1 */
+ mov x17, x30
+ bl check_errata_1800714
+ cbz x0, 1f
+
+ /* Disable allocation of splintered pages in the L2 TLB */
+ mrs x1, CORTEX_A77_CPUECTLR_EL1
+ orr x1, x1, CORTEX_A77_CPUECTLR_EL1_BIT_53
+ msr CORTEX_A77_CPUECTLR_EL1, x1
+ isb
+1:
+ ret x17
+endfunc errata_a77_1800714_wa
+
+func check_errata_1800714
+ /* Applies to everything <= r1p1 */
+ mov x1, #0x11
+ b cpu_rev_var_ls
+endfunc check_errata_1800714
+
+ /* -------------------------------------------------
+ * The CPU Ops reset function for Cortex-A77.
+ * Shall clobber: x0-x19
+ * -------------------------------------------------
+ */
+func cortex_a77_reset_func
+ mov x19, x30
+ bl cpu_get_rev_var
+ mov x18, x0
+
+#if ERRATA_A77_1800714
+ mov x0, x18
+ bl errata_a77_1800714_wa
+#endif
+
+ ret x19
+endfunc cortex_a77_reset_func
+
/* ---------------------------------------------
* HW will do the cache maintenance while powering down
* ---------------------------------------------
@@ -42,6 +89,18 @@
* Errata printing function for Cortex-A77. Must follow AAPCS.
*/
func cortex_a77_errata_report
+ stp x8, x30, [sp, #-16]!
+
+ bl cpu_get_rev_var
+ mov x8, x0
+
+ /*
+ * Report all errata. The revision-variant information is passed to
+ * checking functions of each errata.
+ */
+ report_errata ERRATA_A77_1800714, cortex_a77, 1800714
+
+ ldp x8, x30, [sp], #16
ret
endfunc cortex_a77_errata_report
#endif
@@ -67,5 +126,5 @@
endfunc cortex_a77_cpu_reg_dump
declare_cpu_ops cortex_a77, CORTEX_A77_MIDR, \
- CPU_NO_RESET_FUNC, \
+ cortex_a77_reset_func, \
cortex_a77_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 1bc082d..e494375 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -250,6 +250,18 @@
# only to revision <= r3p0 of the Cortex A76 cpu.
ERRATA_A76_1286807 ?=0
+# Flag to apply erratum 1791580 workaround during reset. This erratum applies
+# only to revision <= r4p0 of the Cortex A76 cpu.
+ERRATA_A76_1791580 ?=0
+
+# Flag to apply erratum 1800710 workaround during reset. This erratum applies
+# only to revision <= r4p0 of the Cortex A76 cpu.
+ERRATA_A76_1800710 ?=0
+
+# Flag to apply erratum 1800714 workaround during reset. This erratum applies
+# only to revision <= r1p1 of the Cortex A77 cpu.
+ERRATA_A77_1800714 ?=0
+
# Flag to apply erratum 1688305 workaround during reset. This erratum applies
# to revisions r0p0 - r1p0 of the A78 cpu.
ERRATA_A78_1688305 ?=0
@@ -487,6 +499,18 @@
$(eval $(call assert_boolean,ERRATA_A76_1286807))
$(eval $(call add_define,ERRATA_A76_1286807))
+# Process ERRATA_A76_1791580 flag
+$(eval $(call assert_boolean,ERRATA_A76_1791580))
+$(eval $(call add_define,ERRATA_A76_1791580))
+
+# Process ERRATA_A76_1800710 flag
+$(eval $(call assert_boolean,ERRATA_A76_1800710))
+$(eval $(call add_define,ERRATA_A76_1800710))
+
+# Process ERRATA_A77_1800714 flag
+$(eval $(call assert_boolean,ERRATA_A77_1800714))
+$(eval $(call add_define,ERRATA_A77_1800714))
+
# Process ERRATA_A78_1688305 flag
$(eval $(call assert_boolean,ERRATA_A78_1688305))
$(eval $(call add_define,ERRATA_A78_1688305))
diff --git a/lib/debugfs/devfip.c b/lib/debugfs/devfip.c
index 70ac3bc..b0ee39a 100644
--- a/lib/debugfs/devfip.c
+++ b/lib/debugfs/devfip.c
@@ -73,6 +73,7 @@
{"soc-fw.cfg", UUID_SOC_FW_CONFIG},
{"tos-fw.cfg", UUID_TOS_FW_CONFIG},
{"nt-fw.cfg", UUID_NT_FW_CONFIG},
+ {"fw.cfg", UUID_FW_CONFIG},
{"rot-k.crt", UUID_ROT_KEY_CERT},
{"nt-k.crt", UUID_NON_TRUSTED_WORLD_KEY_CERT},
{"sip-sp.crt", UUID_SIP_SECURE_PARTITION_CONTENT_CERT}
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
index a5ec143..24b6bcc 100644
--- a/lib/fconf/fconf.c
+++ b/lib/fconf/fconf.c
@@ -9,48 +9,42 @@
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <libfdt.h>
#include <plat/common/platform.h>
#include <platform_def.h>
-struct fconf_dtb_info_t fconf_dtb_info;
-
-void fconf_load_config(void)
+int fconf_load_config(unsigned int image_id)
{
int err;
- /* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
- image_info_t arm_tb_fw_info = {
+ const struct dyn_cfg_dtb_info_t *config_info;
+
+ assert((image_id == FW_CONFIG_ID) || (image_id == TB_FW_CONFIG_ID));
+
+ image_info_t config_image_info = {
.h.type = (uint8_t)PARAM_IMAGE_BINARY,
.h.version = (uint8_t)VERSION_2,
.h.size = (uint16_t)sizeof(image_info_t),
- .h.attr = 0,
- .image_base = ARM_TB_FW_CONFIG_BASE,
- .image_max_size = (uint32_t)
- (ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE)
+ .h.attr = 0
};
- VERBOSE("FCONF: Loading FW_CONFIG\n");
- err = load_auth_image(TB_FW_CONFIG_ID, &arm_tb_fw_info);
+ config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_id);
+ assert(config_info != NULL);
+
+ config_image_info.image_base = config_info->config_addr;
+ 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);
if (err != 0) {
- /* Return if FW_CONFIG is not loaded */
- VERBOSE("FW_CONFIG not loaded, continuing without it\n");
- return;
+ VERBOSE("Failed to load config %d\n", image_id);
+ return err;
}
- /* At this point we know that a DTB is indeed available */
- fconf_dtb_info.base_addr = arm_tb_fw_info.image_base;
- fconf_dtb_info.size = (size_t)arm_tb_fw_info.image_size;
+ INFO("FCONF: Config file with image ID:%d loaded at address = 0x%lx\n",
+ image_id, config_image_info.image_base);
-#if !BL2_AT_EL3
- image_desc_t *desc;
-
- /* The BL2 ep_info arg0 is modified to point to FW_CONFIG */
- desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
- assert(desc != NULL);
- desc->ep_info.args.arg0 = arm_tb_fw_info.image_base;
-#endif
-
- INFO("FCONF: FW_CONFIG loaded at address = 0x%lx\n", arm_tb_fw_info.image_base);
+ return 0;
}
void fconf_populate(const char *config_type, uintptr_t config)
@@ -81,7 +75,4 @@
}
}
}
-
- /* save local pointer to the config dtb */
- fconf_dtb_info.base_addr = config;
}
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
index c087102..b01dc6f 100644
--- a/lib/fconf/fconf.mk
+++ b/lib/fconf/fconf.mk
@@ -8,5 +8,5 @@
FCONF_SOURCES := lib/fconf/fconf.c
FCONF_DYN_SOURCES := lib/fconf/fconf_dyn_cfg_getter.c
-BL1_SOURCES += ${FCONF_SOURCES}
+BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 7b5bd6e..25dd7f9 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -12,42 +12,72 @@
#include <lib/object_pool.h>
#include <libfdt.h>
-/* We currently use TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs */
-#define MAX_DTB_INFO U(5)
+/* 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 config information from
+ * global pool and set the configuration information.
+ */
+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 = 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;
+ /*
+ * 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
+ * fw_config information.
+ *
+ * Other BLs, satisfy below check and populate fw_config information
+ * in global dtb_infos array.
+ */
+ 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 */
const char *compatible_str = "fconf,dyn_cfg-dtb_registry";
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
@@ -57,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)) {
@@ -98,4 +127,4 @@
return 0;
}
-FCONF_REGISTER_POPULATOR(TB_FW, dyn_cfg, fconf_populate_dtb_registry);
+FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry);
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/libfdt/fdt.c b/lib/libfdt/fdt.c
index 7855a17..c28fcc1 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -55,22 +10,125 @@
#include "libfdt_internal.h"
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int32_t fdt_ro_probe_(const void *fdt)
{
+ uint32_t totalsize = fdt_totalsize(fdt);
+
+ if (can_assume(VALID_DTB))
+ return totalsize;
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
- if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
- return -FDT_ERR_BADVERSION;
- if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
- return -FDT_ERR_BADVERSION;
+ if (!can_assume(LATEST)) {
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ if (fdt_last_comp_version(fdt) >
+ FDT_LAST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ }
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
/* Unfinished sequential-write blob */
- if (fdt_size_dt_struct(fdt) == 0)
+ if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE;
} else {
return -FDT_ERR_BADMAGIC;
}
+ if (totalsize < INT32_MAX)
+ return totalsize;
+ else
+ return -FDT_ERR_TRUNCATED;
+}
+
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+ return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+ uint32_t base, uint32_t size)
+{
+ if (!check_off_(hdrsize, totalsize, base))
+ return 0; /* block start out of bounds */
+ if ((base + size) < base)
+ return 0; /* overflow */
+ if (!check_off_(hdrsize, totalsize, base + size))
+ return 0; /* block end out of bounds */
+ return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+ if (version <= 1)
+ return FDT_V1_SIZE;
+ else if (version <= 2)
+ return FDT_V2_SIZE;
+ else if (version <= 3)
+ return FDT_V3_SIZE;
+ else if (version <= 16)
+ return FDT_V16_SIZE;
+ else
+ return FDT_V17_SIZE;
+}
+
+size_t fdt_header_size(const void *fdt)
+{
+ return can_assume(LATEST) ? FDT_V17_SIZE :
+ fdt_header_size_(fdt_version(fdt));
+}
+
+int fdt_check_header(const void *fdt)
+{
+ size_t hdrsize;
+
+ if (fdt_magic(fdt) != FDT_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ if (!can_assume(LATEST)) {
+ if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ || (fdt_last_comp_version(fdt) >
+ FDT_LAST_SUPPORTED_VERSION))
+ return -FDT_ERR_BADVERSION;
+ if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+ return -FDT_ERR_BADVERSION;
+ }
+ hdrsize = fdt_header_size(fdt);
+ if (!can_assume(VALID_DTB)) {
+
+ if ((fdt_totalsize(fdt) < hdrsize)
+ || (fdt_totalsize(fdt) > INT_MAX))
+ return -FDT_ERR_TRUNCATED;
+
+ /* Bounds check memrsv block */
+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_mem_rsvmap(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ }
+
+ if (!can_assume(VALID_DTB)) {
+ /* Bounds check structure block */
+ if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_struct(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ } else {
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_struct(fdt),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ }
+
+ /* Bounds check strings block */
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
+ fdt_off_dt_strings(fdt),
+ fdt_size_dt_strings(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ }
+
return 0;
}
@@ -78,12 +136,13 @@
{
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
- if ((absoffset < offset)
- || ((absoffset + len) < absoffset)
- || (absoffset + len) > fdt_totalsize(fdt))
- return NULL;
+ if (!can_assume(VALID_INPUT))
+ if ((absoffset < offset)
+ || ((absoffset + len) < absoffset)
+ || (absoffset + len) > fdt_totalsize(fdt))
+ return NULL;
- if (fdt_version(fdt) >= 0x11)
+ if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@@ -100,7 +159,7 @@
*nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (!tagp)
+ if (!can_assume(VALID_DTB) && !tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
@@ -112,18 +171,19 @@
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
- if (!p)
+ if (!can_assume(VALID_DTB) && !p)
return FDT_END; /* premature end */
break;
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (!lenp)
+ if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
- if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+ if (!can_assume(LATEST) &&
+ fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
offset += 4;
break;
@@ -146,6 +206,8 @@
int fdt_check_node_offset_(const void *fdt, int offset)
{
+ if (can_assume(VALID_INPUT))
+ return offset;
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
return -FDT_ERR_BADOFFSET;
@@ -244,7 +306,7 @@
int fdt_move(const void *fdt, void *buf, int bufsize)
{
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
index eff4dbc..9a82cd0 100644
--- a/lib/libfdt/fdt_addresses.c
+++ b/lib/libfdt/fdt_addresses.c
@@ -1,52 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (C) 2018 embedded brains GmbH
*/
#include "libfdt_env.h"
@@ -55,42 +11,91 @@
#include "libfdt_internal.h"
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
- const fdt32_t *ac;
- int val;
+ const fdt32_t *c;
+ uint32_t val;
int len;
- ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
- if (!ac)
+ c = fdt_getprop(fdt, nodeoffset, name, &len);
+ if (!c)
+ return len;
+
+ if (len != sizeof(*c))
+ return -FDT_ERR_BADNCELLS;
+
+ val = fdt32_to_cpu(*c);
+ if (val > FDT_MAX_NCELLS)
+ return -FDT_ERR_BADNCELLS;
+
+ return (int)val;
+}
+
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+ int val;
+
+ val = fdt_cells(fdt, nodeoffset, "#address-cells");
+ if (val == 0)
+ return -FDT_ERR_BADNCELLS;
+ if (val == -FDT_ERR_NOTFOUND)
return 2;
-
- if (len != sizeof(*ac))
- return -FDT_ERR_BADNCELLS;
-
- val = fdt32_to_cpu(*ac);
- if ((val <= 0) || (val > FDT_MAX_NCELLS))
- return -FDT_ERR_BADNCELLS;
-
return val;
}
int fdt_size_cells(const void *fdt, int nodeoffset)
{
- const fdt32_t *sc;
int val;
- int len;
- sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
- if (!sc)
- return 2;
-
- if (len != sizeof(*sc))
- return -FDT_ERR_BADNCELLS;
-
- val = fdt32_to_cpu(*sc);
- if ((val < 0) || (val > FDT_MAX_NCELLS))
- return -FDT_ERR_BADNCELLS;
-
+ val = fdt_cells(fdt, nodeoffset, "#size-cells");
+ if (val == -FDT_ERR_NOTFOUND)
+ return 1;
return val;
}
+
+/* This function assumes that [address|size]_cells is 1 or 2 */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+ const char *name, uint64_t addr, uint64_t size)
+{
+ int addr_cells, size_cells, ret;
+ uint8_t data[sizeof(fdt64_t) * 2], *prop;
+
+ ret = fdt_address_cells(fdt, parent);
+ if (ret < 0)
+ return ret;
+ addr_cells = ret;
+
+ ret = fdt_size_cells(fdt, parent);
+ if (ret < 0)
+ return ret;
+ size_cells = ret;
+
+ /* check validity of address */
+ prop = data;
+ if (addr_cells == 1) {
+ if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+ return -FDT_ERR_BADVALUE;
+
+ fdt32_st(prop, (uint32_t)addr);
+ } else if (addr_cells == 2) {
+ fdt64_st(prop, addr);
+ } else {
+ return -FDT_ERR_BADNCELLS;
+ }
+
+ /* check validity of size */
+ prop += addr_cells * sizeof(fdt32_t);
+ if (size_cells == 1) {
+ if (size > UINT32_MAX)
+ return -FDT_ERR_BADVALUE;
+
+ fdt32_st(prop, (uint32_t)size);
+ } else if (size_cells == 2) {
+ fdt64_st(prop, size);
+ } else {
+ return -FDT_ERR_BADNCELLS;
+ }
+
+ return fdt_appendprop(fdt, nodeoffset, name, data,
+ (addr_cells + size_cells) * sizeof(fdt32_t));
+}
diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c
index f2ae9b7..49d54d4 100644
--- a/lib/libfdt/fdt_empty_tree.c
+++ b/lib/libfdt/fdt_empty_tree.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2012 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index bf75388..b310e49 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -1,53 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -93,11 +48,11 @@
* @pathp: pointer which receives the path of the target (or NULL)
*
* overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targetting is
+ * device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
- * the targetted node offset in the base device tree
+ * the targeted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
@@ -697,7 +652,7 @@
int len = 0, namelen;
const char *name;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
for (;;) {
name = fdt_get_name(fdt, nodeoffset, &namelen);
@@ -778,26 +733,36 @@
/* keep end marker to avoid strlen() */
e = path + path_len;
- /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
-
if (*path != '/')
return -FDT_ERR_BADVALUE;
/* get fragment name first */
s = strchr(path + 1, '/');
- if (!s)
- return -FDT_ERR_BADOVERLAY;
+ if (!s) {
+ /* Symbol refers to something that won't end
+ * up in the target tree */
+ continue;
+ }
frag_name = path + 1;
frag_name_len = s - path - 1;
/* verify format; safe since "s" lies in \0 terminated prop */
len = sizeof("/__overlay__/") - 1;
- if ((e - s) < len || memcmp(s, "/__overlay__/", len))
- return -FDT_ERR_BADOVERLAY;
-
- rel_path = s + len;
- rel_path_len = e - rel_path;
+ if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
+ /* /<fragment-name>/__overlay__/<relative-subnode-path> */
+ rel_path = s + len;
+ rel_path_len = e - rel_path - 1;
+ } else if ((e - s) == len
+ && (memcmp(s, "/__overlay__", len - 1) == 0)) {
+ /* /<fragment-name>/__overlay__ */
+ rel_path = "";
+ rel_path_len = 0;
+ } else {
+ /* Symbol refers to something that won't end
+ * up in the target tree */
+ continue;
+ }
/* find the fragment index in which the symbol lies */
ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
@@ -863,11 +828,15 @@
int fdt_overlay_apply(void *fdt, void *fdto)
{
- uint32_t delta = fdt_get_max_phandle(fdt);
+ uint32_t delta;
int ret;
- FDT_CHECK_HEADER(fdt);
- FDT_CHECK_HEADER(fdto);
+ FDT_RO_PROBE(fdt);
+ FDT_RO_PROBE(fdto);
+
+ ret = fdt_find_max_phandle(fdt, &delta);
+ if (ret)
+ goto err;
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index dfb3236..e03570a 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -76,60 +31,169 @@
return 0;
}
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+ int32_t totalsize;
+ uint32_t absoffset;
+ size_t len;
+ int err;
+ const char *s, *n;
+
+ if (can_assume(VALID_INPUT)) {
+ s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+
+ if (lenp)
+ *lenp = strlen(s);
+ return s;
+ }
+ totalsize = fdt_ro_probe_(fdt);
+ err = totalsize;
+ if (totalsize < 0)
+ goto fail;
+
+ err = -FDT_ERR_BADOFFSET;
+ absoffset = stroffset + fdt_off_dt_strings(fdt);
+ if (absoffset >= totalsize)
+ goto fail;
+ len = totalsize - absoffset;
+
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ if (stroffset < 0)
+ goto fail;
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
+ if (stroffset >= fdt_size_dt_strings(fdt))
+ goto fail;
+ if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+ len = fdt_size_dt_strings(fdt) - stroffset;
+ }
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ if ((stroffset >= 0)
+ || (stroffset < -fdt_size_dt_strings(fdt)))
+ goto fail;
+ if ((-stroffset) < len)
+ len = -stroffset;
+ } else {
+ err = -FDT_ERR_INTERNAL;
+ goto fail;
+ }
+
+ s = (const char *)fdt + absoffset;
+ n = memchr(s, '\0', len);
+ if (!n) {
+ /* missing terminating NULL */
+ err = -FDT_ERR_TRUNCATED;
+ goto fail;
+ }
+
+ if (lenp)
+ *lenp = n - s;
+ return s;
+
+fail:
+ if (lenp)
+ *lenp = err;
+ return NULL;
+}
+
const char *fdt_string(const void *fdt, int stroffset)
{
- return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+ return fdt_get_string(fdt, stroffset, NULL);
}
static int fdt_string_eq_(const void *fdt, int stroffset,
const char *s, int len)
{
- const char *p = fdt_string(fdt, stroffset);
+ int slen;
+ const char *p = fdt_get_string(fdt, stroffset, &slen);
- return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+ return p && (slen == len) && (memcmp(p, s, len) == 0);
}
-uint32_t fdt_get_max_phandle(const void *fdt)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
{
- uint32_t max_phandle = 0;
- int offset;
+ uint32_t max = 0;
+ int offset = -1;
- for (offset = fdt_next_node(fdt, -1, NULL);;
- offset = fdt_next_node(fdt, offset, NULL)) {
- uint32_t phandle;
+ while (true) {
+ uint32_t value;
- if (offset == -FDT_ERR_NOTFOUND)
- return max_phandle;
+ offset = fdt_next_node(fdt, offset, NULL);
+ if (offset < 0) {
+ if (offset == -FDT_ERR_NOTFOUND)
+ break;
- if (offset < 0)
- return (uint32_t)-1;
+ return offset;
+ }
- phandle = fdt_get_phandle(fdt, offset);
- if (phandle == (uint32_t)-1)
- continue;
+ value = fdt_get_phandle(fdt, offset);
- if (phandle > max_phandle)
- max_phandle = phandle;
+ if (value > max)
+ max = value;
}
+ if (phandle)
+ *phandle = max;
+
return 0;
}
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+ uint32_t max;
+ int err;
+
+ err = fdt_find_max_phandle(fdt, &max);
+ if (err < 0)
+ return err;
+
+ if (max == FDT_MAX_PHANDLE)
+ return -FDT_ERR_NOPHANDLES;
+
+ if (phandle)
+ *phandle = max + 1;
+
+ return 0;
+}
+
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+ int offset = n * sizeof(struct fdt_reserve_entry);
+ int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+ if (!can_assume(VALID_INPUT)) {
+ if (absoffset < fdt_off_mem_rsvmap(fdt))
+ return NULL;
+ if (absoffset > fdt_totalsize(fdt) -
+ sizeof(struct fdt_reserve_entry))
+ return NULL;
+ }
+ return fdt_mem_rsv_(fdt, n);
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
- FDT_CHECK_HEADER(fdt);
- *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
- *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
+ const struct fdt_reserve_entry *re;
+
+ FDT_RO_PROBE(fdt);
+ re = fdt_mem_rsv(fdt, n);
+ if (!can_assume(VALID_INPUT) && !re)
+ return -FDT_ERR_BADOFFSET;
+
+ *address = fdt64_ld(&re->address);
+ *size = fdt64_ld(&re->size);
return 0;
}
int fdt_num_mem_rsv(const void *fdt)
{
- int i = 0;
+ int i;
+ const struct fdt_reserve_entry *re;
- while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
- i++;
- return i;
+ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+ if (fdt64_ld(&re->size) == 0)
+ return i;
+ }
+ return -FDT_ERR_TRUNCATED;
}
static int nextprop_(const void *fdt, int offset)
@@ -161,7 +225,7 @@
{
int depth;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
for (depth = 0;
(offset >= 0) && (depth >= 0);
@@ -187,7 +251,7 @@
const char *p = path;
int offset = 0;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* see if we have an alias */
if (*path != '/') {
@@ -237,13 +301,13 @@
const char *nameptr;
int err;
- if (((err = fdt_check_header(fdt)) != 0)
+ if (((err = fdt_ro_probe_(fdt)) < 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
nameptr = nh->name;
- if (fdt_version(fdt) < 0x10) {
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
/*
* For old FDT versions, match the naming conventions of V16:
* give only the leaf name (after all /). The actual tree
@@ -294,7 +358,8 @@
int err;
const struct fdt_property *prop;
- if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+ if (!can_assume(VALID_INPUT) &&
+ (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (lenp)
*lenp = err;
return NULL;
@@ -303,7 +368,7 @@
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_to_cpu(prop->len);
+ *lenp = fdt32_ld(&prop->len);
return prop;
}
@@ -315,7 +380,7 @@
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
- if (fdt_version(fdt) < 0x10) {
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
@@ -336,11 +401,12 @@
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;
- if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+ if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
offset = -FDT_ERR_INTERNAL;
break;
}
- if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+ if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@@ -361,7 +427,7 @@
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
- if (fdt_version(fdt) < 0x10) {
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
@@ -392,8 +458,8 @@
return NULL;
/* Handle realignment */
- if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
- fdt32_to_cpu(prop->len) >= 8)
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -406,12 +472,27 @@
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!prop)
return NULL;
- if (namep)
- *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ if (namep) {
+ const char *name;
+ int namelen;
+
+ if (!can_assume(VALID_INPUT)) {
+ name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ &namelen);
+ if (!name) {
+ if (lenp)
+ *lenp = namelen;
+ return NULL;
+ }
+ *namep = name;
+ } else {
+ *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ }
+ }
/* Handle realignment */
- if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
- fdt32_to_cpu(prop->len) >= 8)
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+ (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -436,7 +517,7 @@
return 0;
}
- return fdt32_to_cpu(*php);
+ return fdt32_ld(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
@@ -462,7 +543,7 @@
int offset, depth, namelen;
const char *name;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (buflen < 2)
return -FDT_ERR_NOSPACE;
@@ -514,7 +595,7 @@
int offset, depth;
int supernodeoffset = -FDT_ERR_INTERNAL;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND;
@@ -536,10 +617,12 @@
}
}
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
- return -FDT_ERR_BADOFFSET;
- else if (offset == -FDT_ERR_BADOFFSET)
- return -FDT_ERR_BADSTRUCTURE;
+ if (!can_assume(VALID_INPUT)) {
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+ }
return offset; /* error from fdt_next_node() */
}
@@ -551,7 +634,8 @@
err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
if (err)
- return (err < 0) ? err : -FDT_ERR_INTERNAL;
+ return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
+ -FDT_ERR_INTERNAL;
return nodedepth;
}
@@ -573,7 +657,7 @@
const void *val;
int len;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't
@@ -599,7 +683,7 @@
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we
* potentially scan each property of a node in
@@ -752,7 +836,7 @@
{
int offset, err;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 9b82905..93e4a2b 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -67,29 +22,31 @@
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
}
-static int fdt_rw_check_header_(void *fdt)
+static int fdt_rw_probe_(void *fdt)
{
- FDT_CHECK_HEADER(fdt);
+ if (can_assume(VALID_DTB))
+ return 0;
+ FDT_RO_PROBE(fdt);
- if (fdt_version(fdt) < 17)
+ if (!can_assume(LATEST) && fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION;
if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
fdt_size_dt_struct(fdt)))
return -FDT_ERR_BADLAYOUT;
- if (fdt_version(fdt) > 17)
+ if (!can_assume(LATEST) && fdt_version(fdt) > 17)
fdt_set_version(fdt, 17);
return 0;
}
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
{ \
int err_; \
- if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
+ if ((err_ = fdt_rw_probe_(fdt)) != 0) \
return err_; \
}
-static inline int fdt_data_size_(void *fdt)
+static inline unsigned int fdt_data_size_(void *fdt)
{
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
}
@@ -97,15 +54,16 @@
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
{
char *p = splicepoint;
- char *end = (char *)fdt + fdt_data_size_(fdt);
+ unsigned int dsize = fdt_data_size_(fdt);
+ size_t soff = p - (char *)fdt;
- if (((p + oldlen) < p) || ((p + oldlen) > end))
+ if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
return -FDT_ERR_BADOFFSET;
- if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+ if ((p < (char *)fdt) || (dsize + newlen < oldlen))
return -FDT_ERR_BADOFFSET;
- if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+ if (dsize - oldlen + newlen > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
- memmove(p + newlen, p + oldlen, end - p - oldlen);
+ memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
return 0;
}
@@ -136,6 +94,14 @@
return 0;
}
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+ int newlen = strlen(s) + 1;
+
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
+}
+
static int fdt_splice_string_(void *fdt, int newlen)
{
void *p = (char *)fdt
@@ -149,7 +115,16 @@
return 0;
}
-static int fdt_find_add_string_(void *fdt, const char *s)
+/**
+ * fdt_find_add_string_() - Find or allocate a string
+ *
+ * @fdt: pointer to the device tree to check/adjust
+ * @s: string to find/add
+ * @allocated: Set to 0 if the string was found, 1 if not found and so
+ * allocated. Ignored if can_assume(NO_ROLLBACK)
+ * @return offset of string in the string table (whether found or added)
+ */
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p;
@@ -157,6 +132,9 @@
int len = strlen(s) + 1;
int err;
+ if (!can_assume(NO_ROLLBACK))
+ *allocated = 0;
+
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
if (p)
/* found it */
@@ -167,6 +145,9 @@
if (err)
return err;
+ if (!can_assume(NO_ROLLBACK))
+ *allocated = 1;
+
memcpy(new, s, len);
return (new - strtab);
}
@@ -176,7 +157,7 @@
struct fdt_reserve_entry *re;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@@ -192,7 +173,7 @@
{
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND;
@@ -225,11 +206,12 @@
int nextoffset;
int namestroff;
int err;
+ int allocated;
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return nextoffset;
- namestroff = fdt_find_add_string_(fdt, name);
+ namestroff = fdt_find_add_string_(fdt, name, &allocated);
if (namestroff < 0)
return namestroff;
@@ -237,8 +219,12 @@
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
- if (err)
+ if (err) {
+ /* Delete the string if we failed to add it */
+ if (!can_assume(NO_ROLLBACK) && allocated)
+ fdt_del_last_string_(fdt, name);
return err;
+ }
(*prop)->tag = cpu_to_fdt32(FDT_PROP);
(*prop)->nameoff = cpu_to_fdt32(namestroff);
@@ -252,7 +238,7 @@
int oldlen, newlen;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep)
@@ -275,7 +261,7 @@
struct fdt_property *prop;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND)
@@ -308,7 +294,7 @@
struct fdt_property *prop;
int err, oldlen, newlen;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (prop) {
@@ -334,7 +320,7 @@
struct fdt_property *prop;
int len, proplen;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (!prop)
@@ -354,7 +340,7 @@
uint32_t tag;
fdt32_t *endtag;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
if (offset >= 0)
@@ -394,7 +380,7 @@
{
int endoffset;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
@@ -435,12 +421,12 @@
const char *fdtend = fdtstart + fdt_totalsize(fdt);
char *tmp;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
- if (fdt_version(fdt) >= 17) {
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
} else {
struct_size = 0;
@@ -450,7 +436,8 @@
return struct_size;
}
- if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
+ if (can_assume(LIBFDT_ORDER) ||
+ !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */
err = fdt_move(fdt, buf, bufsize);
if (err)
@@ -494,7 +481,7 @@
{
int mem_rsv_size;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
index 9677a18..768db66 100644
--- a/lib/libfdt/fdt_strerror.c
+++ b/lib/libfdt/fdt_strerror.c
@@ -1,51 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -82,6 +38,7 @@
FDT_ERRTABENT(FDT_ERR_BADVALUE),
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
+ FDT_ERRTABENT(FDT_ERR_BADFLAGS),
};
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 6d33cc2..26759d5 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@@ -55,21 +10,87 @@
#include "libfdt_internal.h"
-static int fdt_sw_check_header_(void *fdt)
+static int fdt_sw_probe_(void *fdt)
{
- if (fdt_magic(fdt) != FDT_SW_MAGIC)
- return -FDT_ERR_BADMAGIC;
- /* FIXME: should check more details about the header state */
+ if (!can_assume(VALID_INPUT)) {
+ if (fdt_magic(fdt) == FDT_MAGIC)
+ return -FDT_ERR_BADSTATE;
+ else if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ }
+
return 0;
}
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE(fdt) \
{ \
int err; \
- if ((err = fdt_sw_check_header_(fdt)) != 0) \
+ if ((err = fdt_sw_probe_(fdt)) != 0) \
return err; \
}
+/* 'memrsv' state: Initial state after fdt_create()
+ *
+ * Allowed functions:
+ * fdt_add_reservmap_entry()
+ * fdt_finish_reservemap() [moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+ int err = fdt_sw_probe_(fdt);
+ if (err)
+ return err;
+
+ if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
+ return -FDT_ERR_BADSTATE;
+ return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+ return err; \
+ }
+
+/* 'struct' state: Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ * fdt_begin_node()
+ * fdt_end_node()
+ * fdt_property*()
+ * fdt_finish() [moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
+{
+ int err = fdt_sw_probe_(fdt);
+ if (err)
+ return err;
+
+ if (!can_assume(VALID_INPUT) &&
+ fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+ return -FDT_ERR_BADSTATE;
+ return 0;
+}
+
+#define FDT_SW_PROBE_STRUCT(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
+ return err; \
+ }
+
+static inline uint32_t sw_flags(void *fdt)
+{
+ /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
+ return fdt_last_comp_version(fdt);
+}
+
+/* 'complete' state: Enter this state after fdt_finish()
+ *
+ * Allowed functions: none
+ */
+
static void *fdt_grab_space_(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
@@ -85,38 +106,59 @@
return fdt_offset_ptr_w_(fdt, offset);
}
-int fdt_create(void *buf, int bufsize)
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
{
+ const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry));
void *fdt = buf;
- if (bufsize < sizeof(struct fdt_header))
+ if (bufsize < hdrsize)
return -FDT_ERR_NOSPACE;
+ if (flags & ~FDT_CREATE_FLAGS_ALL)
+ return -FDT_ERR_BADFLAGS;
+
memset(buf, 0, bufsize);
+ /*
+ * magic and last_comp_version keep intermediate state during the fdt
+ * creation process, which is replaced with the proper FDT format by
+ * fdt_finish().
+ *
+ * flags should be accessed with sw_flags().
+ */
fdt_set_magic(fdt, FDT_SW_MAGIC);
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, flags);
+
fdt_set_totalsize(fdt, bufsize);
- fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
- sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_mem_rsvmap(fdt, hdrsize);
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
- fdt_set_off_dt_strings(fdt, bufsize);
+ fdt_set_off_dt_strings(fdt, 0);
return 0;
}
+int fdt_create(void *buf, int bufsize)
+{
+ return fdt_create_with_flags(buf, bufsize, 0);
+}
+
int fdt_resize(void *fdt, void *buf, int bufsize)
{
size_t headsize, tailsize;
char *oldtail, *newtail;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE(fdt);
- headsize = fdt_off_dt_struct(fdt);
+ headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
+ if (!can_assume(VALID_DTB) &&
+ headsize + tailsize > fdt_totalsize(fdt))
+ return -FDT_ERR_INTERNAL;
+
if ((headsize + tailsize) > bufsize)
return -FDT_ERR_NOSPACE;
@@ -133,8 +175,9 @@
memmove(buf, fdt, headsize);
}
- fdt_set_off_dt_strings(buf, bufsize);
fdt_set_totalsize(buf, bufsize);
+ if (fdt_off_dt_strings(buf))
+ fdt_set_off_dt_strings(buf, bufsize);
return 0;
}
@@ -144,10 +187,7 @@
struct fdt_reserve_entry *re;
int offset;
- FDT_SW_CHECK_HEADER(fdt);
-
- if (fdt_size_dt_struct(fdt))
- return -FDT_ERR_BADSTATE;
+ FDT_SW_PROBE_MEMRSV(fdt);
offset = fdt_off_dt_struct(fdt);
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,16 +204,23 @@
int fdt_finish_reservemap(void *fdt)
{
- return fdt_add_reservemap_entry(fdt, 0, 0);
+ int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+ if (err)
+ return err;
+
+ fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+ return 0;
}
int fdt_begin_node(void *fdt, const char *name)
{
struct fdt_node_header *nh;
- int namelen = strlen(name) + 1;
+ int namelen;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
+ namelen = strlen(name) + 1;
nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh)
return -FDT_ERR_NOSPACE;
@@ -187,7 +234,7 @@
{
fdt32_t *en;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
en = fdt_grab_space_(fdt, FDT_TAGSIZE);
if (! en)
@@ -197,19 +244,13 @@
return 0;
}
-static int fdt_find_add_string_(void *fdt, const char *s)
+static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
- const char *p;
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;
int struct_top, offset;
- p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
- if (p)
- return p - strtab;
-
- /* Add it */
offset = -strtabsize - len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) + offset < struct_top)
@@ -220,20 +261,56 @@
return offset;
}
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+ int strtabsize = fdt_size_dt_strings(fdt);
+ int len = strlen(s) + 1;
+
+ fdt_set_size_dt_strings(fdt, strtabsize - len);
+}
+
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
+{
+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
+ int strtabsize = fdt_size_dt_strings(fdt);
+ const char *p;
+
+ *allocated = 0;
+
+ p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
+ if (p)
+ return p - strtab;
+
+ *allocated = 1;
+
+ return fdt_add_string_(fdt, s);
+}
+
int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
{
struct fdt_property *prop;
int nameoff;
+ int allocated;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
- nameoff = fdt_find_add_string_(fdt, name);
+ /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
+ if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
+ allocated = 1;
+ nameoff = fdt_add_string_(fdt, name);
+ } else {
+ nameoff = fdt_find_add_string_(fdt, name, &allocated);
+ }
if (nameoff == 0)
return -FDT_ERR_NOSPACE;
prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
- if (! prop)
+ if (! prop) {
+ if (allocated)
+ fdt_del_last_string_(fdt, name);
return -FDT_ERR_NOSPACE;
+ }
prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
@@ -262,7 +339,7 @@
uint32_t tag;
int offset, nextoffset;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
/* Add terminator */
end = fdt_grab_space_(fdt, sizeof(*end));
@@ -295,6 +372,10 @@
/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+
+ /* And fix up fields that were keeping intermediate state. */
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
+
return 0;
}
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 534c1cb..f64139e 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 7681e19..d4e0bd4 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -1,65 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_INTERNAL_H
#define LIBFDT_INTERNAL_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <fdt.h>
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
-#define FDT_CHECK_HEADER(fdt) \
- { \
- int err_; \
- if ((err_ = fdt_check_header(fdt)) != 0) \
- return err_; \
+int32_t fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt) \
+ { \
+ int32_t totalsize_; \
+ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
+ return totalsize_; \
}
int fdt_check_node_offset_(const void *fdt, int offset);
@@ -92,4 +48,126 @@
#define FDT_SW_MAGIC (~FDT_MAGIC)
+/**********************************************************************/
+/* Checking controls */
+/**********************************************************************/
+
+#ifndef FDT_ASSUME_MASK
+#define FDT_ASSUME_MASK 0
+#endif
+
+/*
+ * Defines assumptions which can be enabled. Each of these can be enabled
+ * individually. For maximum safety, don't enable any assumptions!
+ *
+ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
+ * You should have another method of validating the device tree, such as a
+ * signature or hash check before using libfdt.
+ *
+ * For situations where security is not a concern it may be safe to enable
+ * ASSUME_SANE.
+ */
+enum {
+ /*
+ * This does essentially no checks. Only the latest device-tree
+ * version is correctly handled. Inconsistencies or errors in the device
+ * tree may cause undefined behaviour or crashes. Invalid parameters
+ * passed to libfdt may do the same.
+ *
+ * If an error occurs when modifying the tree it may leave the tree in
+ * an intermediate (but valid) state. As an example, adding a property
+ * where there is insufficient space may result in the property name
+ * being added to the string table even though the property itself is
+ * not added to the struct section.
+ *
+ * Only use this if you have a fully validated device tree with
+ * the latest supported version and wish to minimise code size.
+ */
+ ASSUME_PERFECT = 0xff,
+
+ /*
+ * This assumes that the device tree is sane. i.e. header metadata
+ * and basic hierarchy are correct.
+ *
+ * With this assumption enabled, normal device trees produced by libfdt
+ * and the compiler should be handled safely. Malicious device trees and
+ * complete garbage may cause libfdt to behave badly or crash. Truncated
+ * device trees (e.g. those only partially loaded) can also cause
+ * problems.
+ *
+ * Note: Only checks that relate exclusively to the device tree itself
+ * (not the parameters passed to libfdt) are disabled by this
+ * assumption. This includes checking headers, tags and the like.
+ */
+ ASSUME_VALID_DTB = 1 << 0,
+
+ /*
+ * This builds on ASSUME_VALID_DTB and further assumes that libfdt
+ * functions are called with valid parameters, i.e. not trigger
+ * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
+ * extensive checking of parameters and the device tree, making various
+ * assumptions about correctness.
+ *
+ * It doesn't make sense to enable this assumption unless
+ * ASSUME_VALID_DTB is also enabled.
+ */
+ ASSUME_VALID_INPUT = 1 << 1,
+
+ /*
+ * This disables checks for device-tree version and removes all code
+ * which handles older versions.
+ *
+ * Only enable this if you know you have a device tree with the latest
+ * version.
+ */
+ ASSUME_LATEST = 1 << 2,
+
+ /*
+ * This assumes that it is OK for a failed addition to the device tree,
+ * due to lack of space or some other problem, to skip any rollback
+ * steps (such as dropping the property name from the string table).
+ * This is safe to enable in most circumstances, even though it may
+ * leave the tree in a sub-optimal state.
+ */
+ ASSUME_NO_ROLLBACK = 1 << 3,
+
+ /*
+ * This assumes that the device tree components appear in a 'convenient'
+ * order, i.e. the memory reservation block first, then the structure
+ * block and finally the string block.
+ *
+ * This order is not specified by the device-tree specification,
+ * but is expected by libfdt. The device-tree compiler always created
+ * device trees with this order.
+ *
+ * This assumption disables a check in fdt_open_into() and removes the
+ * ability to fix the problem there. This is safe if you know that the
+ * device tree is correctly ordered. See fdt_blocks_misordered_().
+ */
+ ASSUME_LIBFDT_ORDER = 1 << 4,
+
+ /*
+ * This assumes that libfdt itself does not have any internal bugs. It
+ * drops certain checks that should never be needed unless libfdt has an
+ * undiscovered bug.
+ *
+ * This can generally be considered safe to enable.
+ */
+ ASSUME_LIBFDT_FLAWLESS = 1 << 5,
+};
+
+/**
+ * can_assume_() - check if a particular assumption is enabled
+ *
+ * @mask: Mask to check (ASSUME_...)
+ * @return true if that assumption is enabled, else false
+ */
+static inline bool can_assume_(int mask)
+{
+ return FDT_ASSUME_MASK & mask;
+}
+
+/** helper macros for checking assumptions */
+#define can_assume(_assume) can_assume_(ASSUME_ ## _assume)
+
#endif /* LIBFDT_INTERNAL_H */
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index cec9404..2ff480b 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -10,14 +10,14 @@
OC = $(CROSS_COMPILE)objcopy
CPP = $(CROSS_COMPILE)cpp
ROMLIB_GEN = ./romlib_generator.py
-BUILD_DIR = ../../$(BUILD_PLAT)/romlib
-LIB_DIR = ../../$(BUILD_PLAT)/lib
-WRAPPER_DIR = ../../$(BUILD_PLAT)/libwrapper
+BUILD_DIR = $(BUILD_PLAT)/romlib
+LIB_DIR = $(BUILD_PLAT)/lib
+WRAPPER_DIR = $(BUILD_PLAT)/libwrapper
LIBS = -lmbedtls -lfdt -lc
INC = $(INCLUDES:-I%=-I../../%)
PPFLAGS = $(INC) $(DEFINES) -P -x assembler-with-cpp -D__LINKER__ -MD -MP -MT $(BUILD_DIR)/romlib.ld
OBJS = $(BUILD_DIR)/jmptbl.o $(BUILD_DIR)/init.o
-MAPFILE = ../../$(BUILD_PLAT)/romlib/romlib.map
+MAPFILE = $(BUILD_PLAT)/romlib/romlib.map
ifneq ($(PLAT_DIR),)
WRAPPER_SOURCES = $(shell $(ROMLIB_GEN) genwrappers -b $(WRAPPER_DIR) --list ../../$(PLAT_DIR)/jmptbl.i)
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 6db228f..caf5990 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -305,3 +305,9 @@
# Trap RAS error record access from lower EL
RAS_TRAP_LOWER_EL_ERR_ACCESS := 0
+
+# 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/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index 1f16a0b..92c83b0 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -39,8 +39,8 @@
/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
- /* set R_PRCM clocks to non-secure */
- mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x7);
+ /* Set R_PRCM bus clocks to non-secure */
+ mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x1);
/* Set all DMA channels (16 max.) to non-secure */
mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
diff --git a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
index b9d9053..b9ff8bf 100644
--- a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
+++ b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained in this dtb */
tb_fw-config {
- load-address = <0x0 0x2001010>;
+ load-address = <0x0 0x2001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,11 +24,4 @@
id = <HW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
- };
};
diff --git a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
new file mode 100644
index 0000000..c66186f
--- /dev/null
+++ b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ };
+};
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index ab0ff58..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)
@@ -188,11 +196,17 @@
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
/*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
* and limit. Leave enough space of BL2 meminfo.
*/
-#define ARM_TB_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
+#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.
@@ -220,7 +234,9 @@
#define BL2_LIMIT BL1_RW_BASE
/* Put BL32 below BL2 in NS DRAM.*/
-#define ARM_BL2_MEM_DESC_BASE ARM_TB_FW_CONFIG_LIMIT
+#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/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index 3a4d5e5..5d610f4 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -14,9 +14,10 @@
plat/arm/common/arm_dyn_cfg_helpers.c \
common/fdt_wrappers.c
-A5DS_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+A5DS_GIC_SOURCES := ${GICV2_SOURCES} \
plat/common/plat_gicv2.c \
plat/arm/common/arm_gicv2.c
@@ -72,10 +73,13 @@
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
ifdef UNIX_MK
-FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
+FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \
fdts/$(notdir ${FVP_HW_CONFIG_DTS})))
@@ -83,6 +87,7 @@
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config))
FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
+ plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
${FVP_HW_CONFIG_DTS}
endif
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 0378729..2884ea6 100644
--- a/plat/arm/board/arm_fpga/fpga_def.h
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -18,7 +18,8 @@
* 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 2
+
+#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 a705429..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;
+ 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,38 +53,25 @@
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
- unsigned int cluster_id, cpu_id, thread_id;
+ unsigned int core_pos;
- mpidr &= MPIDR_AFFINITY_MASK;
- if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
- return -1;
- }
-
- if (mpidr & MPIDR_MT_MASK) {
- thread_id = MPIDR_AFFLVL0_VAL(mpidr);
- } else {
- thread_id = 0;
- }
-
- cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
- cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
-
- if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) {
- return -1;
- } else if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
- return -1;
- } else if (thread_id >= FPGA_MAX_PE_PER_CPU) {
- return -1;
- }
-
- /*
- * 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);
- /* Calculate the correct core, catering for multi-threaded images */
- return (int) plat_fpga_calc_core_pos(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();
+ }
+
+ /* 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;
+ }
+
+ 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 34e50ea..1e7badf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -24,15 +24,13 @@
$(error "TRUSTED_BOARD_BOOT must be disabled")
endif
-ifndef PRELOADED_BL33_BASE
-$(error "PRELOADED_BL33_BASE is not set")
-endif
+PRELOADED_BL33_BASE := 0x80080000
-ifndef FPGA_PRELOADED_DTB_BASE
-$(error "FPGA_PRELOADED_DTB_BASE is not set")
-else
+FPGA_PRELOADED_DTB_BASE := 0x80070000
$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
-endif
+
+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
@@ -64,7 +62,10 @@
lib/cpus/aarch64/neoverse_zeus.S \
lib/cpus/aarch64/cortex_hercules_ae.S \
lib/cpus/aarch64/cortex_a65.S \
- lib/cpus/aarch64/cortex_a65ae.S
+ lib/cpus/aarch64/cortex_a65ae.S \
+ lib/cpus/aarch64/cortex_klein.S \
+ lib/cpus/aarch64/cortex_matterhorn.S
+
# AArch64/AArch32 cores
FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \
lib/cpus/aarch64/cortex_a75.S
diff --git a/plat/arm/board/corstone700/corstone700_helpers.S b/plat/arm/board/corstone700/common/corstone700_helpers.S
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_helpers.S
rename to plat/arm/board/corstone700/common/corstone700_helpers.S
diff --git a/plat/arm/board/corstone700/corstone700_plat.c b/plat/arm/board/corstone700/common/corstone700_plat.c
similarity index 86%
rename from plat/arm/board/corstone700/corstone700_plat.c
rename to plat/arm/board/corstone700/common/corstone700_plat.c
index e2ade70..629f076 100644
--- a/plat/arm/board/corstone700/corstone700_plat.c
+++ b/plat/arm/board/corstone700/common/corstone700_plat.c
@@ -18,6 +18,7 @@
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
+ ARM_MAP_NS_SHARED_RAM,
ARM_MAP_NS_DRAM1,
CORSTONE700_MAP_DEVICE,
{0}
@@ -33,5 +34,6 @@
unsigned int plat_get_syscnt_freq2(void)
{
- return CORSTONE700_TIMER_BASE_FREQUENCY;
+ /* Returning the Generic Timer Frequency */
+ return SYS_COUNTER_FREQ_IN_TICKS;
}
diff --git a/plat/arm/board/corstone700/corstone700_pm.c b/plat/arm/board/corstone700/common/corstone700_pm.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_pm.c
rename to plat/arm/board/corstone700/common/corstone700_pm.c
diff --git a/plat/arm/board/corstone700/corstone700_security.c b/plat/arm/board/corstone700/common/corstone700_security.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_security.c
rename to plat/arm/board/corstone700/common/corstone700_security.c
diff --git a/plat/arm/board/corstone700/corstone700_stack_protector.c b/plat/arm/board/corstone700/common/corstone700_stack_protector.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_stack_protector.c
rename to plat/arm/board/corstone700/common/corstone700_stack_protector.c
diff --git a/plat/arm/board/corstone700/corstone700_topology.c b/plat/arm/board/corstone700/common/corstone700_topology.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_topology.c
rename to plat/arm/board/corstone700/common/corstone700_topology.c
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.c b/plat/arm/board/corstone700/common/drivers/mhu/mhu.c
similarity index 100%
rename from plat/arm/board/corstone700/drivers/mhu/mhu.c
rename to plat/arm/board/corstone700/common/drivers/mhu/mhu.c
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.h b/plat/arm/board/corstone700/common/drivers/mhu/mhu.h
similarity index 100%
rename from plat/arm/board/corstone700/drivers/mhu/mhu.h
rename to plat/arm/board/corstone700/common/drivers/mhu/mhu.h
diff --git a/plat/arm/board/corstone700/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h
similarity index 84%
rename from plat/arm/board/corstone700/include/platform_def.h
rename to plat/arm/board/corstone700/common/include/platform_def.h
index cc4dc3a..57b0551 100644
--- a/plat/arm/board/corstone700/include/platform_def.h
+++ b/plat/arm/board/corstone700/common/include/platform_def.h
@@ -67,6 +67,9 @@
#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
ARM_SHARED_RAM_SIZE)
+#define ARM_NS_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + UL(0x00100000)
+#define ARM_NS_SHARED_RAM_SIZE 0x00300000
+
/*
* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
* the page reserved for fw_configs) to BL32
@@ -83,17 +86,30 @@
#define ARM_CACHE_WRITEBACK_SHIFT 6
/*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
* and limit. Leave enough space for BL2 meminfo.
*/
-#define ARM_TB_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
+#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#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 + \
@@ -111,7 +127,13 @@
#define ARM_SYS_CNTCTL_BASE UL(0x1a200000)
#define ARM_SYS_CNTREAD_BASE UL(0x1a210000)
#define ARM_SYS_TIMCTL_BASE UL(0x1a220000)
-#define CORSTONE700_TIMER_BASE_FREQUENCY UL(24000000)
+
+#ifdef TARGET_PLATFORM_FVP
+#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */
+#else
+#define SYS_COUNTER_FREQ_IN_TICKS UL(32000000) /* 32MHz */
+#endif
+
#define CORSTONE700_IRQ_TZ_WDOG 32
#define CORSTONE700_IRQ_SEC_SYS_TIMER 34
@@ -140,7 +162,7 @@
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
-#define PLAT_ARM_NS_IMAGE_OFFSET (ARM_DRAM1_BASE + UL(0x8000000))
+#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
@@ -162,7 +184,12 @@
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
ARM_SHARED_RAM_BASE, \
ARM_SHARED_RAM_SIZE, \
- MT_DEVICE | MT_RW | MT_SECURE)
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \
+ ARM_NS_SHARED_RAM_BASE, \
+ ARM_NS_SHARED_RAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
ARM_NS_DRAM1_BASE, \
@@ -187,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/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index a4d4f22..513af3c 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -4,6 +4,11 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+# Making sure the corstone700 platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+ $(error TARGET_PLATFORM must be fpga or fvp)
+endif
+
CORSTONE700_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S
BL32_SOURCES += plat/arm/common/aarch32/arm_helpers.S \
@@ -12,17 +17,18 @@
lib/xlat_tables/aarch32/xlat_tables.c \
lib/xlat_tables/xlat_tables_common.c \
${CORSTONE700_CPU_LIBS} \
- plat/arm/board/corstone700/drivers/mhu/mhu.c
+ plat/arm/board/corstone700/common/drivers/mhu/mhu.c
-PLAT_INCLUDES := -Iplat/arm/board/corstone700/include \
+PLAT_INCLUDES := -Iplat/arm/board/corstone700/common/include \
-Iinclude/plat/arm/common \
- -Iplat/arm/board/corstone700/drivers/mhu
+ -Iplat/arm/board/corstone700/common/drivers/mhu
NEED_BL32 := yes
-CORSTONE700_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+CORSTONE700_GIC_SOURCES := ${GICV2_SOURCES} \
plat/common/plat_gicv2.c \
plat/arm/common/arm_gicv2.c
@@ -30,13 +36,14 @@
override NEED_BL1 := no
override NEED_BL2 := no
override NEED_BL2U := no
+override NEED_BL33 := yes
#TFA for Corstone700 starts from BL32
override RESET_TO_SP_MIN := 1
#Device tree
-CORSTONE700_HW_CONFIG_DTS := fdts/corstone700.dts
-CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb
+CORSTONE700_HW_CONFIG_DTS := fdts/corstone700_${TARGET_PLATFORM}.dts
+CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb
FDT_SOURCES += ${CORSTONE700_HW_CONFIG_DTS}
$(eval CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS)))
@@ -49,4 +56,8 @@
$(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
endif
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
+# Adding TARGET_PLATFORM as a GCC define (-D option)
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
index acee6c3..75dc0f1 100644
--- a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -7,17 +7,17 @@
# SP_MIN source files specific to FVP platform
BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \
lib/utils/mem_region.c \
- plat/arm/board/corstone700/corstone700_helpers.S \
- plat/arm/board/corstone700/corstone700_topology.c \
- plat/arm/board/corstone700/corstone700_security.c \
- plat/arm/board/corstone700/corstone700_plat.c \
- plat/arm/board/corstone700/corstone700_pm.c \
+ plat/arm/board/corstone700/common/corstone700_helpers.S \
+ plat/arm/board/corstone700/common/corstone700_topology.c \
+ plat/arm/board/corstone700/common/corstone700_security.c \
+ plat/arm/board/corstone700/common/corstone700_plat.c \
+ plat/arm/board/corstone700/common/corstone700_pm.c \
plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c \
${CORSTONE700_GIC_SOURCES}
ifneq (${ENABLE_STACK_PROTECTOR},0)
ifneq (${ENABLE_STACK_PROTECTOR},none)
- BL32_SOURCES += plat/arm/board/corstone700/corstone700_stack_protector.c
+ BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c
endif
endif
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index 8172a6e..35a777b 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -14,6 +14,7 @@
struct gicv3_config_t gicv3_config;
struct hw_topology_t soc_topology;
struct uart_serial_config_t uart_serial_config;
+struct cpu_timer_t cpu_timer;
#define ILLEGAL_ADDR ULL(~0)
@@ -260,9 +261,36 @@
VERBOSE("FCONF: UART serial device clk frequency: %x\n",
uart_serial_config.uart_clk);
+
+ return 0;
+}
+
+int fconf_populate_cpu_timer(uintptr_t config)
+{
+ int err, node;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /* Find the node offset point to "arm,armv8-timer" compatible property,
+ * a per-core architected timer attached to a GIC to deliver its per-processor
+ * interrupts via PPIs */
+ node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,armv8-timer");
+ if (node < 0) {
+ ERROR("FCONF: Unrecognized hardware configuration dtb (%d)\n", node);
+ return node;
+ }
+
+ /* Locate the cell holding the clock-frequency, an optional field */
+ err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", &cpu_timer.clock_freq);
+ if (err < 0) {
+ WARN("FCONF failed to read clock-frequency property\n");
+ }
+
return 0;
}
FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
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_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index 5f89284..9fb566b 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -12,10 +12,9 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
- max-size = <0x200>;
+ load-address = <0x0 0x4001300>;
+ max-size = <0x1800>;
id = <TB_FW_CONFIG_ID>;
};
@@ -32,14 +31,14 @@
* is loaded at base of DRAM.
*/
soc_fw-config {
- load-address = <0x0 0x04001000>;
+ load-address = <0x0 0x04001300>;
max-size = <0x200>;
id = <SOC_FW_CONFIG_ID>;
};
tos_fw-config {
- load-address = <0x0 0x04001200>;
- max-size = <0x1000>;
+ load-address = <0x0 0x04001500>;
+ max-size = <0xB00>;
id = <TOS_FW_CONFIG_ID>;
};
@@ -49,83 +48,4 @@
id = <NT_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
-
-#if MEASURED_BOOT
- /* BL2 image hash calculated by BL1 */
- bl2_hash_data = [
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#if BL2_HASH_SIZE > 32
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#if BL2_HASH_SIZE > 48
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#endif /* > 48 */
-#endif /* > 32 */
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00];
-#endif /* MEASURED_BOOT */
- };
-
- /*
- * Though TF-A is UUID RFC 4122 compliant meaning fields are stored in
- * network order (big endian), UUID's mentioned in this file are are
- * stored in machine order (little endian).
- * This will be fixed in future.
- */
-#if ARM_IO_IN_DTB
- arm-io_policies {
- fip-handles {
- compatible = "arm,io-fip-handle";
- scp_bl2_uuid = <0x3dfd6697 0x49e8be89 0xa1785dae 0x13826040>;
- bl31_uuid = <0x6d08d447 0x4698fe4c 0x5029959b 0x005abdcb>;
- bl32_uuid = <0x89e1d005 0x4713dc53 0xa502b8d 0x383e7a4b>;
- bl32_extra1_uuid = <0x9bc2700b 0x40785a2a 0x560a659f 0x88827382>;
- bl32_extra2_uuid = <0xb17ba88e 0x4d3fa2cf 0xbbe7fd85 0xd92002a5>;
- bl33_uuid = <0xa7eed0d6 0x4bd5eafc 0x34998297 0xe4b634f2>;
- hw_cfg_uuid = <0xd9f1b808 0x4993cfc9 0xbc6f62a9 0xcc65726b>;
- soc_fw_cfg_uuid = <0x4b817999 0x46fb7603 0x268d8e8c 0xe059787f>;
- tos_fw_cfg_uuid = <0x1a7c2526 0x477fc6db 0xc4c4968d 0x218024b0>;
- nt_fw_cfg_uuid = <0x1598da28 0x447ee893 0xaf1a66ac 0xf9501580>;
- t_key_cert_uuid = <0x90e87e82 0x11e460f8 0x7a77b4a1 0x4cf9b421>;
- scp_fw_key_uuid = <0xa1214202 0x11e460f8 0x3cf39b8d 0x14a0150e>;
- soc_fw_key_uuid = <0xccbeb88a 0x11e460f9 0x48ebd09a 0xf8dcd822>;
- tos_fw_key_cert_uuid = <0x3d67794 0x11e460fb 0x10b7dd85 0x4ee8c5b>;
- nt_fw_key_cert_uuid = <0x2a83d58a 0x11e460fb 0x30dfaf8a 0x5998c4bb>;
- scp_fw_content_cert_uuid = <0x046fbe44 0x11e4635e 0xd8738bb2 0x5696aeea>;
- soc_fw_content_cert_uuid = <0x200cb2e2 0x11e4635e 0xccabe89c 0x66b62bf9>;
- tos_fw_content_cert_uuid = <0x11449fa4 0x11e4635e 0x53f2887 0x3df32a72>;
- nt_fw_content_cert_uuid = <0xf3c1c48e 0x11e4635d 0xee87a9a7 0xa73fb240>;
- sp_content_cert_uuid = <0x44fd6d77 0x3b4c9786 0x3ec1eb91 0x6f2a5a02>;
- };
- };
-#endif /* ARM_IO_IN_DTB */
-
- secure-partitions {
- compatible = "arm,sp";
- cactus-primary {
- uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
- load-address = <0x7000000>;
- };
-
- cactus-secondary {
- uuid = <0x092358d1 0xb94723f0 0x64447c82 0xc88f57f5>;
- load-address = <0x7100000>;
- };
- };
};
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_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..f5b31b4
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define AFF 00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define POST \
+ };
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x0>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x6000000>;
+ entrypoint = <0x0 0x6000000>;
+ binary_size = <0x80000>;
+ };
+
+ chosen {
+ linux,initrd-start = <0>;
+ linux,initrd-end = <0>;
+ };
+
+ hypervisor {
+ compatible = "hafnium,hafnium";
+ vm1 {
+ is_ffa_partition;
+ debug_name = "op-tee";
+ load_address = <0x6280000>;
+ smc_whitelist = <0xbe000000>;
+ };
+ };
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ CPU_0
+
+ /*
+ * SPMC(Hafnium) requires secondary core nodes are declared
+ * in descending order.
+ */
+ CPU_7
+ CPU_6
+ CPU_5
+ CPU_4
+ CPU_3
+ CPU_2
+ CPU_1
+ };
+
+ memory@60000000 {
+ device_type = "memory";
+ reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
+ };
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
new file mode 100644
index 0000000..280a64a
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+
+#if MEASURED_BOOT
+ /* BL2 image hash calculated by BL1 */
+ bl2_hash_data = [
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#if BL2_HASH_SIZE > 32
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#if BL2_HASH_SIZE > 48
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#endif /* > 48 */
+#endif /* > 32 */
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00];
+#endif /* MEASURED_BOOT */
+ };
+
+ /*
+ * Though TF-A is UUID RFC 4122 compliant meaning fields are stored in
+ * network order (big endian), UUID's mentioned in this file are are
+ * stored in machine order (little endian).
+ * This will be fixed in future.
+ */
+#if ARM_IO_IN_DTB
+ arm-io_policies {
+ fip-handles {
+ compatible = "arm,io-fip-handle";
+ scp_bl2_uuid = <0x3dfd6697 0x49e8be89 0xa1785dae 0x13826040>;
+ bl31_uuid = <0x6d08d447 0x4698fe4c 0x5029959b 0x005abdcb>;
+ bl32_uuid = <0x89e1d005 0x4713dc53 0xa502b8d 0x383e7a4b>;
+ bl32_extra1_uuid = <0x9bc2700b 0x40785a2a 0x560a659f 0x88827382>;
+ bl32_extra2_uuid = <0xb17ba88e 0x4d3fa2cf 0xbbe7fd85 0xd92002a5>;
+ bl33_uuid = <0xa7eed0d6 0x4bd5eafc 0x34998297 0xe4b634f2>;
+ hw_cfg_uuid = <0xd9f1b808 0x4993cfc9 0xbc6f62a9 0xcc65726b>;
+ soc_fw_cfg_uuid = <0x4b817999 0x46fb7603 0x268d8e8c 0xe059787f>;
+ tos_fw_cfg_uuid = <0x1a7c2526 0x477fc6db 0xc4c4968d 0x218024b0>;
+ nt_fw_cfg_uuid = <0x1598da28 0x447ee893 0xaf1a66ac 0xf9501580>;
+ t_key_cert_uuid = <0x90e87e82 0x11e460f8 0x7a77b4a1 0x4cf9b421>;
+ scp_fw_key_uuid = <0xa1214202 0x11e460f8 0x3cf39b8d 0x14a0150e>;
+ soc_fw_key_uuid = <0xccbeb88a 0x11e460f9 0x48ebd09a 0xf8dcd822>;
+ tos_fw_key_cert_uuid = <0x3d67794 0x11e460fb 0x10b7dd85 0x4ee8c5b>;
+ nt_fw_key_cert_uuid = <0x2a83d58a 0x11e460fb 0x30dfaf8a 0x5998c4bb>;
+ scp_fw_content_cert_uuid = <0x046fbe44 0x11e4635e 0xd8738bb2 0x5696aeea>;
+ soc_fw_content_cert_uuid = <0x200cb2e2 0x11e4635e 0xccabe89c 0x66b62bf9>;
+ tos_fw_content_cert_uuid = <0x11449fa4 0x11e4635e 0x53f2887 0x3df32a72>;
+ nt_fw_content_cert_uuid = <0xf3c1c48e 0x11e4635d 0xee87a9a7 0xa73fb240>;
+ sp_content_cert_uuid = <0x44fd6d77 0x3b4c9786 0x3ec1eb91 0x6f2a5a02>;
+ };
+ };
+#endif /* ARM_IO_IN_DTB */
+
+ secure-partitions {
+ compatible = "arm,sp";
+#ifdef OPTEE_SP_FW_CONFIG
+ op-tee {
+ uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
+ load-address = <0x6280000>;
+ };
+#else
+ cactus-primary {
+ uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
+ load-address = <0x7000000>;
+ };
+
+ cactus-secondary {
+ uuid = <0x092358d1 0xb94723f0 0x64447c82 0xc88f57f5>;
+ load-address = <0x7100000>;
+ };
+#endif
+ };
+
+#if COT_DESC_IN_DTB
+ #include "cot_descriptors.dtsi"
+#endif
+
+};
+
+#if COT_DESC_IN_DTB
+
+#include "../fvp_def.h"
+
+&trusted_nv_counter {
+ reg = <TFW_NVCTR_BASE>;
+};
+
+&non_trusted_nv_counter {
+ reg = <NTFW_CTR_BASE>;
+};
+#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 43b1374..f2f2143 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -4,7 +4,17 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#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>
+
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
#include <platform_def.h>
@@ -26,3 +36,82 @@
/* Initialize System level generic or SP804 timer */
fvp_timer_init();
}
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ struct bl_params *arm_bl_params;
+
+ arm_bl_params = arm_get_next_bl_params();
+
+#if __aarch64__ && !BL2_AT_EL3
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ bl_mem_params_node_t *param_node;
+ uintptr_t fw_config_base = 0U;
+ entry_point_info_t *ep_info;
+
+ /* Get BL31 image node */
+ param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+ assert(param_node != NULL);
+
+ /* get fw_config load address */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ assert(fw_config_info != NULL);
+
+ fw_config_base = fw_config_info->config_addr;
+ assert(fw_config_base != 0U);
+
+ /*
+ * Get the entry point info of BL31 image and override
+ * arg1 of entry point info with fw_config base address
+ */
+ ep_info = ¶m_node->ep_info;
+ ep_info->args.arg1 = (uint32_t)fw_config_base;
+#endif /* __aarch64__ && !BL2_AT_EL3 */
+
+ 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_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index dc7bfa2..f9ee449 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -7,18 +7,32 @@
#include <assert.h>
#include <common/debug.h>
#include <drivers/arm/smmu_v3.h>
+#include <fconf_hw_config_getter.h>
#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/mmio.h>
#include <plat/arm/common/arm_config.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
#include "fvp_private.h"
-uintptr_t hw_config_dtb;
-
void __init bl31_early_platform_setup2(u_register_t arg0,
u_register_t arg1, u_register_t arg2, u_register_t arg3)
{
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+ const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
+
+ INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
+
+ soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
+ if (soc_fw_config_info != NULL) {
+ arg1 = soc_fw_config_info->config_addr;
+ }
+#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 */
+
arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
/* Initialize the platform config for future decision making */
@@ -45,8 +59,6 @@
/* On FVP RevC, initialize SMMUv3 */
if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
smmuv3_init(PLAT_FVP_SMMUV3_BASE);
-
- hw_config_dtb = arg2;
}
void __init bl31_plat_arch_setup(void)
@@ -59,9 +71,35 @@
* control is passed to BL31.
*/
#if !RESET_TO_BL31 && !BL2_AT_EL3
- assert(hw_config_dtb != 0U);
+ /* HW_CONFIG was also loaded by BL2 */
+ const struct dyn_cfg_dtb_info_t *hw_config_info;
- INFO("BL31 FCONF: HW_CONFIG address = %p\n", (void *)hw_config_dtb);
- fconf_populate("HW_CONFIG", hw_config_dtb);
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
#endif
}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+ /* Get the frequency through FCONF API for HW_CONFIG */
+ counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq);
+ if (counter_base_frequency > 0U) {
+ return counter_base_frequency;
+ }
+#endif
+
+ /* Read the frequency from Frequency modes table */
+ counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+ /* The first entry of the frequency modes table must not be 0 */
+ if (counter_base_frequency == 0U) {
+ panic();
+ }
+
+ return counter_base_frequency;
+}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index c5fae56..cb717e0 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -18,7 +18,10 @@
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
#include <platform_def.h>
+
+#if SPM_MM
#include <services/spm_mm_partition.h>
+#endif
#include "fvp_private.h"
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_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
index b53e00a..ca85f7a 100644
--- a/plat/arm/board/fvp/include/fconf_hw_config_getter.h
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -11,10 +11,9 @@
/* Hardware Config related getter */
#define hw_config__gicv3_config_getter(prop) gicv3_config.prop
-
#define hw_config__topology_getter(prop) soc_topology.prop
-
#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop
+#define hw_config__cpu_timer_getter(prop) cpu_timer.prop
struct gicv3_config_t {
uint64_t gicd_base;
@@ -33,12 +32,17 @@
uint32_t uart_clk;
};
+struct cpu_timer_t {
+ uint32_t clock_freq;
+};
+
int fconf_populate_gicv3_config(uintptr_t config);
int fconf_populate_topology(uintptr_t config);
int fconf_populate_uart_config(uintptr_t config);
+int fconf_populate_cpu_timer(uintptr_t config);
extern struct gicv3_config_t gicv3_config;
extern struct hw_topology_t soc_topology;
extern struct uart_serial_config_t uart_serial_config;
-
+extern struct cpu_timer_t cpu_timer;
#endif /* FCONF_HW_CONFIG_GETTER_H */
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 62ede9a..a986017 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -120,7 +120,7 @@
#if TRUSTED_BOARD_BOOT
# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION)
#else
-# define PLAT_ARM_MAX_BL2_SIZE (UL(0x12000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION)
#endif
#if RESET_TO_BL31
@@ -133,7 +133,7 @@
* calculated using the current BL31 PROGBITS debug size plus the sizes of
* BL2 and BL1-RW
*/
-#define PLAT_ARM_MAX_BL31_SIZE UL(0x3E000)
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000)
#endif /* RESET_TO_BL31 */
#ifndef __aarch64__
@@ -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 7d670ac..f75f556 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -72,13 +72,10 @@
GIC_ENABLE_V4_EXTN := 0
$(eval $(call add_define,GIC_ENABLE_V4_EXTN))
-# No support for extended PPI and SPI range
-GIC_EXT_INTID := 0
-$(eval $(call add_define,GIC_EXT_INTID))
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
-FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
+FVP_GIC_SOURCES := ${GICV2_SOURCES} \
plat/common/plat_gicv2.c \
plat/arm/common/arm_gicv2.c
@@ -217,6 +214,7 @@
ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),)
BL31_SOURCES += common/fdt_wrappers.c \
lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
ifeq (${SEC_INT_DESC_IN_FCONF},1)
@@ -236,11 +234,13 @@
FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts
FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \
${PLAT}_fw_config.dts \
+ ${PLAT}_tb_fw_config.dts \
${PLAT}_soc_fw_config.dts \
${PLAT}_nt_fw_config.dts \
)
-FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
FVP_SOC_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb
FVP_NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
@@ -253,13 +253,20 @@
endif
ifeq (${SPD},spmd)
-FDT_SOURCES += plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
-FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb
+
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS := plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS}
+FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
endif
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
# Add the SOC_FW_CONFIG to FIP and specify the same to certtool
@@ -352,6 +359,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/fdts/fvp_ve_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
index d4f98d9..6e5691b 100644
--- a/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x80001010>;
+ load-address = <0x0 0x80001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,11 +24,4 @@
id = <HW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
- };
};
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
new file mode 100644
index 0000000..c66186f
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ };
+};
diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h
index 70a12ea..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)
@@ -169,11 +178,18 @@
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
/*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
* and limit. Leave enough space of BL2 meminfo.
*/
-#define ARM_TB_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#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.
@@ -204,7 +220,9 @@
/* Put BL32 below BL2 in NS DRAM.*/
-#define ARM_BL2_MEM_DESC_BASE ARM_TB_FW_CONFIG_LIMIT
+#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/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 9ada86b..f8e38ff 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -11,10 +11,11 @@
BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
endif
-FVP_VE_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
- plat/common/plat_gicv2.c \
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+FVP_VE_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
plat/arm/common/arm_gicv2.c
FVP_VE_SECURITY_SOURCES := plat/arm/board/fvp_ve/fvp_ve_security.c
@@ -74,10 +75,14 @@
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
ifdef UNIX_MK
-FDT_SOURCES += plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
+FDT_SOURCES += plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts \
+ plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
-FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
+FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
+FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts
index 60ca60d..c0538f8 100644
--- a/plat/arm/board/juno/fdts/juno_fw_config.dts
+++ b/plat/arm/board/juno/fdts/juno_fw_config.dts
@@ -12,29 +12,10 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- /* Platform Config */
- compatible = "arm,tb_fw";
- /* Disable authentication for development */
- disable_auth = <0x0>;
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
new file mode 100644
index 0000000..80cfa3e
--- /dev/null
+++ b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 67802d4..91c3ae7 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -139,7 +139,7 @@
# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
#endif
#else
-# define PLAT_ARM_MAX_BL2_SIZE (UL(0x11000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
#endif
/*
@@ -148,7 +148,7 @@
* BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL31 -> BL2_BASE.
* Hence the BL31 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
*/
-#define PLAT_ARM_MAX_BL31_SIZE UL(0x3E000)
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000)
#if JUNO_AARCH32_EL3_RUNTIME
/*
@@ -157,7 +157,7 @@
* BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL32 -> BL2_BASE.
* Hence the BL32 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
*/
-#define PLAT_ARM_MAX_BL32_SIZE UL(0x3E000)
+#define PLAT_ARM_MAX_BL32_SIZE UL(0x3D000)
#endif
/*
@@ -254,7 +254,7 @@
* BL31 is loaded over the top.
*/
#define PLAT_CSS_MAX_SCP_BL2_SIZE \
- ((SCP_BL2_LIMIT - ARM_TB_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
+ ((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
#define PLAT_CSS_MAX_SCP_BL2U_SIZE PLAT_CSS_MAX_SCP_BL2_SIZE
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 20ed2c7..393a648 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -29,6 +29,8 @@
fdt fdt_get_alias_namelen
fdt fdt_path_offset
fdt fdt_path_offset_namelen
+fdt fdt_address_cells
+fdt fdt_size_cells
fdt fdt_get_name
fdt fdt_get_alias
fdt fdt_node_offset_by_phandle
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index a871e81..196d3c0 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -4,9 +4,10 @@
# SPDX-License-Identifier: BSD-3-Clause
#
-JUNO_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+JUNO_GIC_SOURCES := ${GICV2_SOURCES} \
plat/common/plat_gicv2.c \
plat/arm/common/arm_gicv2.c
@@ -164,9 +165,14 @@
endif
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts \
+ plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
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/board/rddaniel/fdts/rddaniel_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
index b9265ad..9c9cefe 100644
--- a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,23 +24,4 @@
id = <NT_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index 94a3928..81632a5 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -32,10 +32,19 @@
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
-# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+BL2_SOURCES += ${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+endif
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDDANIEL_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/rddaniel/rddaniel_trusted_boot.c b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
index b9265ad..9c9cefe 100644
--- a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
+++ b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,23 +24,4 @@
id = <NT_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rddanielxlr/platform.mk
index 36a0099..93967ad 100644
--- a/plat/arm/board/rddanielxlr/platform.mk
+++ b/plat/arm/board/rddanielxlr/platform.mk
@@ -32,13 +32,22 @@
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+BL2_SOURCES += ${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+endif
+
# Enable dynamic addition of MMAP regions in BL31
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${RDDANIELXLR_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += ${RDDANIELXLR_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDDANIELXLR_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
index 09b9867..69fb0d4 100644
--- a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,23 +24,4 @@
id = <NT_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
new file mode 100644
index 0000000..dba91e5
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index 1a4dd17..e09afca 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -35,9 +35,13 @@
endif
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
index c9dee60..d3b7fba 100644
--- a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
@@ -11,9 +11,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -24,24 +23,5 @@
id = <NT_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
new file mode 100644
index 0000000..257ef4a
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index e436542..3f0cc7f 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -41,9 +41,13 @@
BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
index 94d0e39..84fc1ad 100644
--- a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
+++ b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,23 +24,4 @@
id = <NT_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index d91f829..f5d547d 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -35,9 +35,14 @@
endif
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
index c92c1d0..5d478e9 100644
--- a/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
+++ b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
@@ -12,30 +12,10 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained on this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
-
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/sgm775/platform.mk b/plat/arm/board/sgm775/platform.mk
index 57edb92..26bc25d 100644
--- a/plat/arm/board/sgm775/platform.mk
+++ b/plat/arm/board/sgm775/platform.mk
@@ -9,9 +9,13 @@
SGM775_BASE= plat/arm/board/sgm775
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${SGM775_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += ${SGM775_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${SGM775_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/tc0/fdts/tc0_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_fw_config.dts
index 8458e08..381ce1f 100644
--- a/plat/arm/board/tc0/fdts/tc0_fw_config.dts
+++ b/plat/arm/board/tc0/fdts/tc0_fw_config.dts
@@ -12,9 +12,8 @@
dtb-registry {
compatible = "fconf,dyn_cfg-dtb_registry";
- /* tb_fw_config is temporarily contained in this dtb */
tb_fw-config {
- load-address = <0x0 0x4001010>;
+ load-address = <0x0 0x4001300>;
max-size = <0x200>;
id = <TB_FW_CONFIG_ID>;
};
@@ -25,22 +24,4 @@
id = <HW_CONFIG_ID>;
};
};
-
- tb_fw-config {
- compatible = "arm,tb_fw";
-
- /* Disable authentication for development */
- disable_auth = <0x0>;
- /*
- * The following two entries are placeholders for Mbed TLS
- * heap information. The default values don't matter since
- * they will be overwritten by BL1.
- * In case of having shared Mbed TLS heap between BL1 and BL2,
- * BL1 will populate these two properties with the respective
- * info about the shared heap. This info will be available for
- * BL2 in order to locate and re-use the heap.
- */
- mbedtls_heap_addr = <0x0 0x0>;
- mbedtls_heap_size = <0x0>;
- };
};
diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
new file mode 100644
index 0000000..2fd25d9
--- /dev/null
+++ b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
index 7f514cc..0bf18e4 100644
--- a/plat/arm/board/tc0/platform.mk
+++ b/plat/arm/board/tc0/platform.mk
@@ -73,9 +73,13 @@
plat/arm/common/arm_nor_psci_mem_protect.c
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${TC0_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES += ${TC0_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${TC0_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc0/tc0_plat.c
index b1ec39b..0546192 100644
--- a/plat/arm/board/tc0/tc0_plat.c
+++ b/plat/arm/board/tc0/tc0_plat.c
@@ -15,7 +15,10 @@
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
#include <drivers/arm/sbsa.h>
+
+#if SPM_MM
#include <services/spm_mm_partition.h>
+#endif
/*
* Table of regions for different BL stages to map using the MMU.
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index c2f49c2..4b2a062 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -12,6 +12,7 @@
#include <bl1/bl1.h>
#include <common/bl_common.h>
#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
#include <plat/arm/common/plat_arm.h>
@@ -53,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;
@@ -142,11 +146,58 @@
*/
void arm_bl1_platform_setup(void)
{
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ image_desc_t *desc;
+ uint32_t fw_config_max_size;
+ int err = -1;
+
/* Initialise the IO layer and register platform IO devices */
plat_arm_io_setup();
- /* Load fw config */
- fconf_load_config();
+ /* Check if we need FWU before further processing */
+ 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_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);
+ if (err < 0) {
+ ERROR("Loading of FW_CONFIG failed %d\n", err);
+ plat_error_handler(err);
+ }
+
+ /*
+ * FW_CONFIG loaded successfully. If FW_CONFIG device tree parsing
+ * is successful then load TB_FW_CONFIG device tree.
+ */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ if (fw_config_info != NULL) {
+ err = fconf_populate_dtb_registry(fw_config_info->config_addr);
+ if (err < 0) {
+ ERROR("Parsing of FW_CONFIG failed %d\n", err);
+ plat_error_handler(err);
+ }
+ /* load TB_FW_CONFIG */
+ err = fconf_load_config(TB_FW_CONFIG_ID);
+ if (err < 0) {
+ ERROR("Loading of TB_FW_CONFIG failed %d\n", err);
+ plat_error_handler(err);
+ }
+ } else {
+ ERROR("Invalid FW_CONFIG address\n");
+ plat_error_handler(err);
+ }
+
+ /* The BL2 ep_info arg0 is modified to point to FW_CONFIG */
+ desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(desc != NULL);
+ desc->ep_info.args.arg0 = fw_config_info->config_addr;
#if TRUSTED_BOARD_BOOT
/* Share the Mbed TLS heap info with other images */
@@ -199,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 6c3f64f..60d8f6e 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -15,6 +15,7 @@
#include <common/desc_image_load.h>
#include <drivers/generic_delay_timer.h>
#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
#ifdef SPD_opteed
#include <lib/optee_utils.h>
#endif
@@ -25,17 +26,23 @@
/* 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_TB_FW_CONFIG_LIMIT. This reserved page is
+ * 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.
*/
-CASSERT(BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
+CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
/* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak bl2_early_platform_setup2
#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, \
@@ -50,7 +57,7 @@
* in x0. This memory layout is sitting at the base of the free trusted SRAM.
* Copy it to a safe location before its reclaimed by later BL2 functionality.
******************************************************************************/
-void arm_bl2_early_platform_setup(uintptr_t tb_fw_config,
+void arm_bl2_early_platform_setup(uintptr_t fw_config,
struct meminfo *mem_layout)
{
/* Initialize the console to provide early debug support */
@@ -59,10 +66,7 @@
/* Setup the BL2 memory layout */
bl2_tzram_layout = *mem_layout;
- /* Fill the properties struct with the info from the config dtb */
- if (tb_fw_config != 0U) {
- fconf_populate("TB_FW", tb_fw_config);
- }
+ fw_config_base = fw_config;
/* Initialise the IO layer and register platform IO devices */
plat_arm_io_setup();
@@ -126,6 +130,7 @@
#if ARM_CRYPTOCELL_INTEG
ARM_MAP_BL_COHERENT_RAM,
#endif
+ ARM_MAP_BL_CONFIG_REGION,
{0}
};
@@ -142,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)
@@ -219,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 85535c1..58ccf0e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -28,10 +28,10 @@
#if !RESET_TO_BL31
/*
- * Check that BL31_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
+ * Check that BL31_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
* is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
*/
-CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
+CASSERT(BL31_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
#endif
/* Weak definitions may be overridden in specific ARM standard platform */
@@ -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 ffa2a64..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>
@@ -77,6 +78,7 @@
{
int err;
uintptr_t tb_fw_cfg_dtb;
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
/*
* If tb_fw_cfg_dtb==NULL then DTB is not present for the current
@@ -91,17 +93,20 @@
* the default heap's address and size.
*/
- /* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
- tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr);
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ 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
@@ -121,18 +126,21 @@
#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;
- /* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
- tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr);
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
/*
* If tb_fw_cfg_dtb==NULL then DTB is not present for the current
@@ -148,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();
}
@@ -165,20 +175,35 @@
*/
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 */
/*
* BL2 utility function to initialize dynamic configuration specified by
- * TB_FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
- * specified in TB_FW_CONFIG.
+ * FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
+ * specified in FW_CONFIG.
*/
void arm_bl2_dyn_cfg_init(void)
{
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,
@@ -196,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;
}
@@ -217,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 68cd9fb..350ecd1 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -25,6 +25,7 @@
const io_uuid_spec_t arm_uuid_spec[MAX_NUMBER_IDS] = {
[BL2_IMAGE_ID] = {UUID_TRUSTED_BOOT_FIRMWARE_BL2},
[TB_FW_CONFIG_ID] = {UUID_TB_FW_CONFIG},
+ [FW_CONFIG_ID] = {UUID_FW_CONFIG},
#if !ARM_IO_IN_DTB
[SCP_BL2_IMAGE_ID] = {UUID_SCP_FIRMWARE_SCP_BL2},
[BL31_IMAGE_ID] = {UUID_EL3_RUNTIME_FIRMWARE_BL31},
@@ -50,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 */
@@ -73,6 +74,11 @@
(uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID],
open_fip
},
+ [FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[FW_CONFIG_ID],
+ open_fip
+ },
#if !ARM_IO_IN_DTB
[SCP_BL2_IMAGE_ID] = {
&fip_dev_handle,
@@ -178,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
@@ -227,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/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 2904ad9..6100b78 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -29,10 +29,10 @@
MT_MEMORY | MT_RW | MT_SECURE)
/*
- * Check that BL32_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
+ * Check that BL32_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
* is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
*/
-CASSERT(BL32_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
+CASSERT(BL32_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
/*******************************************************************************
* Return a pointer to the 'entry_point_info' structure of the next image for the
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index b611eaf..a2117f6 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,7 +15,10 @@
#include <plat/common/platform.h>
#include <drivers/arm/sbsa.h>
#include <sgi_base_platform_def.h>
+
+#if SPM_MM
#include <services/spm_mm_partition.h>
+#endif
#define SGI_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\
V2M_FLASH0_SIZE, \
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 d481018..54b2423 100644
--- a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
+++ b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -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/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index 8be0b34..2d8e677 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -138,7 +138,7 @@
* BL31 is loaded over the top.
*/
#define PLAT_CSS_MAX_SCP_BL2_SIZE \
- ((SCP_BL2_LIMIT - ARM_TB_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
+ ((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
#define PLAT_CSS_MAX_SCP_BL2U_SIZE PLAT_CSS_MAX_SCP_BL2_SIZE
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index 808a107..3069f91 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -133,6 +133,12 @@
plat/brcm/board/common/sbl_util.c \
drivers/arm/sp805/sp805.c
+# Add RNG driver
+DRIVER_RNG_ENABLE := 1
+ifeq (${DRIVER_RNG_ENABLE},1)
+PLAT_BL_COMMON_SOURCES += drivers/brcm/rng.c
+endif
+
# Add eMMC driver
ifeq (${DRIVER_EMMC_ENABLE},1)
$(eval $(call add_define,DRIVER_EMMC_ENABLE))
diff --git a/plat/brcm/board/stingray/include/sr_def.h b/plat/brcm/board/stingray/include/sr_def.h
index ac3ee78..be0dee1 100644
--- a/plat/brcm/board/stingray/include/sr_def.h
+++ b/plat/brcm/board/stingray/include/sr_def.h
@@ -292,6 +292,11 @@
#define ICFG_PKA_MEM_PWR_CTRL__ISO BIT(8)
/*******************************************************************************
+ * RNG constants
+ ******************************************************************************/
+#define RNG_BASE_ADDR 0x68b20000
+
+/*******************************************************************************
* Trusted Watchdog constants
******************************************************************************/
#define ARM_SP805_TWDG_BASE 0x68b30000
diff --git a/plat/brcm/board/stingray/src/bl31_setup.c b/plat/brcm/board/stingray/src/bl31_setup.c
index d947551..a2a274d 100644
--- a/plat/brcm/board/stingray/src/bl31_setup.c
+++ b/plat/brcm/board/stingray/src/bl31_setup.c
@@ -923,7 +923,7 @@
scp_image_info.image_base = PRELOADED_SCP_BASE;
scp_image_info.image_size = PRELOADED_SCP_SIZE;
- bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
+ plat_bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
#endif
/*
* In BL31, logs are saved to DDR and we have much larger space to
diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S
index e2d71da..ee0dbb4 100644
--- a/plat/common/aarch64/platform_mp_stack.S
+++ b/plat/common/aarch64/platform_mp_stack.S
@@ -59,7 +59,8 @@
bic x0, x0, #(CACHE_WRITEBACK_GRANULE - 1)
ret x10
#endif
- .word platform_normal_stacks
+ /* Prevent linker from removal of stack section */
+ .quad platform_normal_stacks
#else /* !(IMAGE_BL31 && RECLAIM_INIT_CODE) */
mov x10, x30
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/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index 455b980..e65980b 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -128,7 +128,13 @@
*/
pm_base = (uintptr_t)pm_addr;
pm_base_align = page_align(pm_base, UP);
- mapped_size = pm_base_align - pm_base;
+
+ if (pm_base == pm_base_align) {
+ /* Page aligned */
+ mapped_size = PAGE_SIZE;
+ } else {
+ mapped_size = pm_base_align - pm_base;
+ }
/* Check space within the page at least maps the FDT header */
if (mapped_size < sizeof(struct fdt_header)) {
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/imx/imx8m/imx8mm/include/gpc_reg.h b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
new file mode 100644
index 0000000..c697af2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+#define NOC_PDN_SLT_CTRL BIT(10)
+#define NOC_PUP_SLT_CTRL BIT(11)
+#define NOC_PGC_PDN_ACK BIT(3)
+#define NOC_PGC_PUP_ACK BIT(19)
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define MIPI_PWR_REQ BIT(0)
+#define PCIE_PWR_REQ BIT(1)
+#define OTG1_PWR_REQ BIT(2)
+#define OTG2_PWR_REQ BIT(3)
+#define HSIOMIX_PWR_REQ BIT(4)
+#define DDRMIX_PWR_REQ BIT(5)
+#define GPU2D_PWR_REQ BIT(6)
+#define GPUMIX_PWR_REQ BIT(7)
+#define VPUMIX_PWR_REQ BIT(8)
+#define GPU3D_PWR_REQ BIT(9)
+#define DISPMIX_PWR_REQ BIT(10)
+#define VPU_G1_PWR_REQ BIT(11)
+#define VPU_G2_PWR_REQ BIT(12)
+#define VPU_H1_PWR_REQ BIT(13)
+
+#define DDRMIX_ADB400_SYNC BIT(2)
+#define HSIOMIX_ADB400_SYNC (0x3 << 5)
+#define DISPMIX_ADB400_SYNC BIT(7)
+#define VPUMIX_ADB400_SYNC BIT(8)
+#define GPU3D_ADB400_SYNC BIT(9)
+#define GPU2D_ADB400_SYNC BIT(10)
+#define GPUMIX_ADB400_SYNC BIT(11)
+#define DDRMIX_ADB400_ACK BIT(20)
+#define HSIOMIX_ADB400_ACK (0x3 << 23)
+#define DISPMIX_ADB400_ACK BIT(25)
+#define VPUMIX_ADB400_ACK BIT(26)
+#define GPU3D_ADB400_ACK BIT(27)
+#define GPU2D_ADB400_ACK BIT(28)
+#define GPUMIX_ADB400_ACK BIT(29)
+
+#define MIPI_PGC 0xc00
+#define PCIE_PGC 0xc40
+#define OTG1_PGC 0xc80
+#define OTG2_PGC 0xcc0
+#define HSIOMIX_PGC 0xd00
+#define DDRMIX_PGC 0xd40
+#define GPU2D_PGC 0xd80
+#define GPUMIX_PGC 0xdc0
+#define VPUMIX_PGC 0xe00
+#define GPU3D_PGC 0xe40
+#define DISPMIX_PGC 0xe80
+#define VPU_G1_PGC 0xec0
+#define VPU_G2_PGC 0xf00
+#define VPU_H1_PGC 0xf40
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
new file mode 100644
index 0000000..fd10438
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+#define NOC_PDN_SLT_CTRL BIT(10)
+#define NOC_PUP_SLT_CTRL BIT(11)
+#define NOC_PGC_PDN_ACK BIT(3)
+#define NOC_PGC_PUP_ACK BIT(19)
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define TMR_TCD2_SHIFT 0
+#define TMC_TMR_SHIFT 10
+#define TRC1_TMC_SHIFT 20
+
+#define MIPI_PWR_REQ BIT(0)
+#define OTG1_PWR_REQ BIT(2)
+#define HSIOMIX_PWR_REQ BIT(4)
+#define DDRMIX_PWR_REQ BIT(5)
+#define GPUMIX_PWR_REQ BIT(7)
+#define DISPMIX_PWR_REQ BIT(10)
+
+#define DDRMIX_ADB400_SYNC BIT(2)
+#define HSIOMIX_ADB400_SYNC BIT(5)
+#define DISPMIX_ADB400_SYNC BIT(7)
+#define GPUMIX_ADB400_SYNC (0x5 << 9)
+#define DDRMIX_ADB400_ACK BIT(20)
+#define HSIOMIX_ADB400_ACK BIT(23)
+#define DISPMIX_ADB400_ACK BIT(25)
+#define GPUMIX_ADB400_ACK (0x5 << 27)
+
+#define MIPI_PGC 0xc00
+#define OTG1_PGC 0xc80
+#define HSIOMIX_PGC 0xd00
+#define DDRMIX_PGC 0xd40
+#define GPUMIX_PGC 0xdc0
+#define DISPMIX_PGC 0xe80
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
new file mode 100644
index 0000000..d660e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x) (0x4000 + (x) * 0x10)
+#define IMR_NUM U(5)
+
+struct imx_noc_setting {
+ uint32_t domain_id;
+ uint32_t start;
+ uint32_t end;
+ uint32_t prioriy;
+ uint32_t mode;
+ uint32_t socket_qos_en;
+};
+
+enum clk_type {
+ CCM_ROOT_SLICE,
+ CCM_CCGR,
+};
+
+struct clk_setting {
+ uint32_t offset;
+ uint32_t val;
+ enum clk_type type;
+};
+
+enum pu_domain_id {
+ /* hsio ss */
+ HSIOMIX,
+ PCIE_PHY,
+ USB1_PHY,
+ USB2_PHY,
+ MLMIX,
+ AUDIOMIX,
+ /* gpu ss */
+ GPUMIX,
+ GPU2D,
+ GPU3D,
+ /* vpu ss */
+ VPUMIX,
+ VPU_G1,
+ VPU_G2,
+ VPU_H1,
+ /* media ss */
+ MEDIAMIX,
+ MEDIAMIX_ISPDWP,
+ MIPI_PHY1,
+ MIPI_PHY2,
+ /* HDMI ss */
+ HDMIMIX,
+ HDMI_PHY,
+ DDRMIX,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[20] = {
+ [MIPI_PHY1] = IMX_PD_DOMAIN(MIPI_PHY1, false),
+ [PCIE_PHY] = IMX_PD_DOMAIN(PCIE_PHY, false),
+ [USB1_PHY] = IMX_PD_DOMAIN(USB1_PHY, true),
+ [USB2_PHY] = IMX_PD_DOMAIN(USB2_PHY, true),
+ [MLMIX] = IMX_MIX_DOMAIN(MLMIX, false),
+ [AUDIOMIX] = IMX_MIX_DOMAIN(AUDIOMIX, false),
+ [GPU2D] = IMX_PD_DOMAIN(GPU2D, false),
+ [GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+ [VPUMIX] = IMX_MIX_DOMAIN(VPUMIX, false),
+ [GPU3D] = IMX_PD_DOMAIN(GPU3D, false),
+ [MEDIAMIX] = IMX_MIX_DOMAIN(MEDIAMIX, false),
+ [VPU_G1] = IMX_PD_DOMAIN(VPU_G1, false),
+ [VPU_G2] = IMX_PD_DOMAIN(VPU_G2, false),
+ [VPU_H1] = IMX_PD_DOMAIN(VPU_H1, false),
+ [HDMIMIX] = IMX_MIX_DOMAIN(HDMIMIX, false),
+ [HDMI_PHY] = IMX_PD_DOMAIN(HDMI_PHY, false),
+ [MIPI_PHY2] = IMX_PD_DOMAIN(MIPI_PHY2, false),
+ [HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+ [MEDIAMIX_ISPDWP] = IMX_PD_DOMAIN(MEDIAMIX_ISPDWP, false),
+};
+
+static struct imx_noc_setting noc_setting[] = {
+ {MLMIX, 0x180, 0x180, 0x80000303, 0x0, 0x0},
+ {AUDIOMIX, 0x200, 0x200, 0x80000303, 0x0, 0x0},
+ {AUDIOMIX, 0x280, 0x480, 0x80000404, 0x0, 0x0},
+ {GPUMIX, 0x500, 0x580, 0x80000303, 0x0, 0x0},
+ {HDMIMIX, 0x600, 0x680, 0x80000202, 0x0, 0x1},
+ {HDMIMIX, 0x700, 0x700, 0x80000505, 0x0, 0x0},
+ {HSIOMIX, 0x780, 0x900, 0x80000303, 0x0, 0x0},
+ {MEDIAMIX, 0x980, 0xb80, 0x80000202, 0x0, 0x1},
+ {MEDIAMIX_ISPDWP, 0xc00, 0xd00, 0x80000505, 0x0, 0x0},
+ {VPU_G1, 0xd80, 0xd80, 0x80000303, 0x0, 0x0},
+ {VPU_G2, 0xe00, 0xe00, 0x80000303, 0x0, 0x0},
+ {VPU_H1, 0xe80, 0xe80, 0x80000303, 0x0, 0x0}
+};
+
+static struct clk_setting hsiomix_clk[] = {
+ { 0x8380, 0x0, CCM_ROOT_SLICE },
+ { 0x44d0, 0x0, CCM_CCGR },
+ { 0x45c0, 0x0, CCM_CCGR },
+};
+
+static struct aipstz_cfg aipstz5[] = {
+ {IMX_AIPSTZ5, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static unsigned int pu_domain_status;
+
+static void imx_noc_qos(unsigned int domain_id)
+{
+ unsigned int i;
+ uint32_t hurry;
+
+ if (domain_id == HDMIMIX) {
+ mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22018);
+ mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22010);
+
+ /* set GPR to make lcdif read hurry level 0x7 */
+ hurry = mmio_read_32(IMX_HDMI_CTL_BASE + TX_CONTROL0);
+ hurry |= 0x00077000;
+ mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL0, hurry);
+ }
+
+ if (domain_id == MEDIAMIX) {
+ /* handle mediamix special */
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RSTn_CSR, 0x1FFFFFF);
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + CLK_EN_CSR, 0x1FFFFFF);
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RST_DIV, 0x40030000);
+
+ /* set GPR to make lcdif read hurry level 0x7 */
+ hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL);
+ hurry |= 0xfc00;
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL, hurry);
+ /* set GPR to make isi write hurry level 0x7 */
+ hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL);
+ hurry |= 0x1ff00000;
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL, hurry);
+ }
+
+ /* set MIX NoC */
+ for (i = 0; i < ARRAY_SIZE(noc_setting); i++) {
+ if (noc_setting[i].domain_id == domain_id) {
+ udelay(50);
+ uint32_t offset = noc_setting[i].start;
+
+ while (offset <= noc_setting[i].end) {
+ mmio_write_32(IMX_NOC_BASE + offset + 0x8, noc_setting[i].prioriy);
+ mmio_write_32(IMX_NOC_BASE + offset + 0xc, noc_setting[i].mode);
+ mmio_write_32(IMX_NOC_BASE + offset + 0x18, noc_setting[i].socket_qos_en);
+ offset += 0x80;
+ }
+ }
+ }
+}
+
+static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+ struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+ unsigned int i;
+
+ if (domain_id == HSIOMIX) {
+ for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+ hsiomix_clk[i].val = mmio_read_32(IMX_CCM_BASE + hsiomix_clk[i].offset);
+ mmio_setbits_32(IMX_CCM_BASE + hsiomix_clk[i].offset,
+ hsiomix_clk[i].type == CCM_ROOT_SLICE ? BIT(28) : 0x3);
+ }
+ }
+
+ if (on) {
+ if (pwr_domain->need_sync) {
+ pu_domain_status |= (1 << domain_id);
+ }
+
+ if (domain_id == HDMIMIX) {
+ /* assert the reset */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0x0);
+ /* enable all th function clock */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+ }
+
+ /* clear the PGC bit */
+ mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /* power up the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req)
+ ;
+
+ if (domain_id == HDMIMIX) {
+ /* wait for memory repair done for HDMIMIX */
+ while (!(mmio_read_32(IMX_SRC_BASE + 0x94) & BIT(8)))
+ ;
+ /* disable all the function clock */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0x0);
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x0);
+ /* deassert the reset */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0xffffffff);
+ /* enable all the clock again */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+ }
+
+ if (domain_id == HSIOMIX) {
+ /* enable HSIOMIX clock */
+ mmio_write_32(IMX_HSIOMIX_CTL_BASE, 0x2);
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* clear adb power down request */
+ mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+ ;
+ }
+
+ imx_noc_qos(domain_id);
+
+ /* AIPS5 config is lost when audiomix is off, so need to re-init it */
+ if (domain_id == AUDIOMIX) {
+ imx_aipstz_init(aipstz5);
+ }
+ } else {
+ if (pwr_domain->always_on) {
+ return;
+ }
+
+ if (pwr_domain->need_sync) {
+ pu_domain_status &= ~(1 << domain_id);
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* set adb power down request */
+ mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+ ;
+ }
+
+ /* set the PGC bit */
+ mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /*
+ * leave the G1, G2, H1 power domain on until VPUMIX power off,
+ * otherwise system will hang due to VPUMIX ACK
+ */
+ if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) {
+ return;
+ }
+
+ if (domain_id == VPUMIX) {
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ |
+ VPU_G2_PWR_REQ | VPU_H1_PWR_REQ);
+
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ |
+ VPU_G2_PWR_REQ | VPU_H1_PWR_REQ))
+ ;
+ }
+
+ /* power down the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req)
+ ;
+
+ if (domain_id == HDMIMIX) {
+ /* disable all the clocks of HDMIMIX */
+ mmio_write_32(IMX_HDMI_CTL_BASE + 0x40, 0x0);
+ mmio_write_32(IMX_HDMI_CTL_BASE + 0x50, 0x0);
+ }
+ }
+
+ if (domain_id == HSIOMIX) {
+ for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+ mmio_write_32(IMX_CCM_BASE + hsiomix_clk[i].offset, hsiomix_clk[i].val);
+ }
+ }
+}
+
+void imx_gpc_init(void)
+{
+ uint32_t val;
+ unsigned int i;
+
+ /* mask all the wakeup irq by default */
+ for (i = 0; i < IMR_NUM; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ /* use GIC wake_request to wakeup C0~C3 from LPM */
+ val |= CORE_WKUP_FROM_GIC;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~MASTER0_LPM_HSK;
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+ mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+ MASTER2_MAPPING));
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0x3fffff);
+
+ /*
+ * Set the CORE & SCU power up timing:
+ * SW = 0x1, SW2ISO = 0x1;
+ * the CPU CORE and SCU power up timming counter
+ * is drived by 32K OSC, each domain's power up
+ * latency is (SW + SW2ISO) / 32768
+ */
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+ A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+ /* clear DSM by default */
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~SLPCR_EN_DSM;
+ /* enable the fast wakeup wait/stop mode */
+ val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+ val |= SLPCR_A53_FASTWUP_STOP_MODE;
+ /* clear the RBC */
+ val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+ /* set the STBY_COUNT to 0x5, (128 * 30)us */
+ val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+ val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+ /* enable all the power domain by default */
+ for (i = 0; i < 101; i++) {
+ mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
+ }
+
+ for (i = 0; i < 20; i++) {
+ imx_gpc_pm_domain_enable(i, true);
+ }
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
new file mode 100644
index 0000000..22fbd5e
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+static const mmap_region_t imx_mmap[] = {
+ GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+ NOC_MAP, {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+ {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+ /* Master domain assignment */
+ RDC_MDAn(0x1, DID1),
+
+ /* peripherals domain permission */
+
+ /* memory region */
+
+ /* Sentinel */
+ {0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+ if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+ return;
+
+ tzc380_init(IMX_TZASC_BASE);
+
+ /*
+ * Need to substact offset 0x40000000 from CPU address when
+ * programming tzasc region for i.mx8mp.
+ */
+
+ /* Enable 1G-5G S/NS RW */
+ tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+ TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+ unsigned int i;
+
+ /* Enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+ }
+
+ imx_aipstz_init(aipstz);
+
+ imx_rdc_init(rdc);
+
+ imx8m_caam_init();
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+ /* This console is only used for boot stage */
+ console_set_scope(&console, CONSOLE_FLAG_BOOT);
+
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef SPD_opteed
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = 0;
+
+ /* Pass TEE base and size to bl33 */
+ bl33_image_ep_info.args.arg1 = BL32_BASE;
+ bl33_image_ep_info.args.arg2 = BL32_SIZE;
+#endif
+
+ bl31_tzc380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+ mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+ MT_MEMORY | MT_RO | MT_SECURE);
+#if USE_COHERENT_MEM
+ mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+ (BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE),
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+ mmap_add(imx_mmap);
+
+ init_xlat_tables();
+
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ /* select the CKIL source to 32K OSC */
+ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE) {
+ return &bl33_image_ep_info;
+ }
+
+ if (type == SECURE) {
+ return &bl32_image_ep_info;
+ }
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
new file mode 100644
index 0000000..bc7b246
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .system_reset = imx_system_reset,
+ .system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ /* sec_entrypoint is used for warm reset */
+ imx_mailbox_init(sec_entrypoint);
+
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
new file mode 100644
index 0000000..12da6ac
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x180
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x44
+#define IMR1_CORE2_A53 0x194
+#define IMR1_CORE3_A53 0x1A8
+#define IMR1_CORE0_M4 0x58
+
+#define SLT0_CFG 0x200
+#define GPC_PU_PWRHSK 0x190
+#define PGC_CPU_0_1_MAPPING 0x1CC
+#define CPU_PGC_UP_TRG 0xD0
+#define PU_PGC_UP_TRG 0xD8
+#define CPU_PGC_DN_TRG 0xDC
+#define PU_PGC_DN_TRG 0xE4
+#define LPS_CPU1 0xEC
+
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(30)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(8)
+#define A53_PLAT_PUP_ACK BIT(9)
+
+#define NOC_PDN_SLT_CTRL BIT(12)
+#define NOC_PUP_SLT_CTRL BIT(13)
+#define NOC_PGC_PDN_ACK BIT(12)
+#define NOC_PGC_PUP_ACK BIT(13)
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define TMR_TCD2_SHIFT 0
+#define TMC_TMR_SHIFT 10
+#define TRC1_TMC_SHIFT 20
+
+#define MIPI_PHY1_PWR_REQ BIT(0)
+#define PCIE_PHY_PWR_REQ BIT(1)
+#define USB1_PHY_PWR_REQ BIT(2)
+#define USB2_PHY_PWR_REQ BIT(3)
+#define MLMIX_PWR_REQ BIT(4)
+#define AUDIOMIX_PWR_REQ BIT(5)
+#define GPU2D_PWR_REQ BIT(6)
+#define GPUMIX_PWR_REQ BIT(7)
+#define VPUMIX_PWR_REQ BIT(8)
+#define GPU3D_PWR_REQ BIT(9)
+#define MEDIAMIX_PWR_REQ BIT(10)
+#define VPU_G1_PWR_REQ BIT(11)
+#define VPU_G2_PWR_REQ BIT(12)
+#define VPU_H1_PWR_REQ BIT(13)
+#define HDMIMIX_PWR_REQ BIT(14)
+#define HDMI_PHY_PWR_REQ BIT(15)
+#define MIPI_PHY2_PWR_REQ BIT(16)
+#define HSIOMIX_PWR_REQ BIT(17)
+#define MEDIAMIX_ISPDWP_PWR_REQ BIT(18)
+#define DDRMIX_PWR_REQ BIT(19)
+
+#define AUDIOMIX_ADB400_SYNC (BIT(4) | BIT(15))
+#define MLMIX_ADB400_SYNC (BIT(7) | BIT(8))
+#define GPUMIX_ADB400_SYNC BIT(9)
+#define VPUMIX_ADB400_SYNC BIT(10)
+#define DDRMIX_ADB400_SYNC BIT(11)
+#define HSIOMIX_ADB400_SYNC BIT(12)
+#define HDMIMIX_ADB400_SYNC BIT(13)
+#define MEDIAMIX_ADB400_SYNC BIT(14)
+
+#define AUDIOMIX_ADB400_ACK (BIT(20) | BIT(31))
+#define MLMIX_ADB400_ACK (BIT(23) | BIT(24))
+#define GPUMIX_ADB400_ACK BIT(25)
+#define VPUMIX_ADB400_ACK BIT(26)
+#define DDRMIX_ADB400_ACK BIT(27)
+#define HSIOMIX_ADB400_ACK BIT(28)
+#define HDMIMIX_ADB400_ACK BIT(29)
+#define MEDIAMIX_ADB400_ACK BIT(30)
+
+#define MIPI_PHY1_PGC 0xb00
+#define PCIE_PHY_PGC 0xb40
+#define USB1_PHY_PGC 0xb80
+#define USB2_PHY_PGC 0xbc0
+#define MLMIX_PGC 0xc00
+#define AUDIOMIX_PGC 0xc40
+#define GPU2D_PGC 0xc80
+#define GPUMIX_PGC 0xcc0
+#define VPUMIX_PGC 0xd00
+#define GPU3D_PGC 0xd40
+#define MEDIAMIX_PGC 0xd80
+#define VPU_G1_PGC 0xdc0
+#define VPU_G2_PGC 0xe00
+#define VPU_H1_PGC 0xe40
+#define HDMIMIX_PGC 0xe80
+#define HDMI_PHY_PGC 0xec0
+#define MIPI_PHY2_PGC 0xf00
+#define HSIOMIX_PGC 0xf40
+#define MEDIAMIX_ISPDWP_PGC 0xf80
+#define DDRMIX_PGC 0xfc0
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
new file mode 100644
index 0000000..644adc7
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0xB00
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(4)
+#define PLAT_MAX_RET_STATE U(2)
+
+#define PLAT_WAIT_RET_STATE U(1)
+#define PLAT_STOP_OFF_STATE U(3)
+
+#define BL31_BASE U(0x960000)
+#define BL31_LIMIT U(0x980000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE U(0x38800000)
+#define PLAT_GICR_BASE U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ 24000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_AIPSTZ1 U(0x301f0000)
+#define IMX_AIPSTZ2 U(0x305f0000)
+#define IMX_AIPSTZ3 U(0x309f0000)
+#define IMX_AIPSTZ4 U(0x32df0000)
+#define IMX_AIPSTZ5 U(0x30df0000)
+
+#define IMX_AIPS_BASE U(0x30000000)
+#define IMX_AIPS_SIZE U(0x3000000)
+#define IMX_GPV_BASE U(0x32000000)
+#define IMX_GPV_SIZE U(0x800000)
+#define IMX_AIPS1_BASE U(0x30200000)
+#define IMX_AIPS4_BASE U(0x32c00000)
+#define IMX_ANAMIX_BASE U(0x30360000)
+#define IMX_CCM_BASE U(0x30380000)
+#define IMX_SRC_BASE U(0x30390000)
+#define IMX_GPC_BASE U(0x303a0000)
+#define IMX_RDC_BASE U(0x303d0000)
+#define IMX_CSU_BASE U(0x303e0000)
+#define IMX_WDOG_BASE U(0x30280000)
+#define IMX_SNVS_BASE U(0x30370000)
+#define IMX_NOC_BASE U(0x32700000)
+#define IMX_NOC_SIZE U(0x100000)
+#define IMX_TZASC_BASE U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE U(0x30340000)
+#define IMX_CAAM_BASE U(0x30900000)
+#define IMX_DDRC_BASE U(0x3d400000)
+#define IMX_DDRPHY_BASE U(0x3c000000)
+#define IMX_DDR_IPS_BASE U(0x3d000000)
+#define IMX_DDR_IPS_SIZE U(0x1800000)
+#define IMX_ROM_BASE U(0x0)
+
+#define IMX_GIC_BASE PLAT_GICD_BASE
+#define IMX_GIC_SIZE U(0x200000)
+
+#define IMX_HSIOMIX_CTL_BASE U(0x32f10000)
+#define IMX_HDMI_CTL_BASE U(0x32fc0000)
+#define RTX_RESET_CTL0 U(0x20)
+#define RTX_CLK_CTL0 U(0x40)
+#define RTX_CLK_CTL1 U(0x50)
+#define TX_CONTROL0 U(0x200)
+#define TX_CONTROL1 U(0x220)
+
+#define IMX_MEDIAMIX_CTL_BASE U(0x32ec0000)
+#define RSTn_CSR U(0x0)
+#define CLK_EN_CSR U(0x4)
+#define RST_DIV U(0x8)
+#define LCDIF_ARCACHE_CTRL U(0x4c)
+#define ISI_CACHE_CTRL U(0x50)
+
+#define WDOG_WSR U(0x2)
+#define WDOG_WCR_WDZST BIT(0)
+#define WDOG_WCR_WDBG BIT(1)
+#define WDOG_WCR_WDE BIT(2)
+#define WDOG_WCR_WDT BIT(3)
+#define WDOG_WCR_SRS BIT(4)
+#define WDOG_WCR_WDA BIT(5)
+#define WDOG_WCR_SRE BIT(6)
+#define WDOG_WCR_WDW BIT(7)
+
+#define SRC_A53RCR0 U(0x4)
+#define SRC_A53RCR1 U(0x8)
+#define SRC_OTG1PHY_SCR U(0x20)
+#define SRC_OTG2PHY_SCR U(0x24)
+#define SRC_GPR1_OFFSET U(0x74)
+
+#define SNVS_LPCR U(0x38)
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define SNVS_LPCR_DP_EN BIT(5)
+#define SNVS_LPCR_TOP BIT(6)
+
+#define IOMUXC_GPR10 U(0x28)
+#define GPR_TZASC_EN BIT(0)
+#define GPR_TZASC_EN_LOCK BIT(16)
+
+#define ANAMIX_MISC_CTL U(0x124)
+#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM U(64)
+
+#define OCRAM_S_BASE U(0x00180000)
+#define OCRAM_S_SIZE U(0x8000)
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define GIC_MAP MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
+#define DDRC_MAP MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define NOC_MAP MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
new file mode 100644
index 0000000..1d11e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -0,0 +1,56 @@
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iplat/imx/common/include \
+ -Iplat/imx/imx8m/include \
+ -Iplat/imx/imx8m/imx8mp/include
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8m/gpc_common.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/imx/imx8m/imx_rdc.c \
+ plat/imx/imx8m/imx8m_caam.c \
+ plat/imx/imx8m/imx8m_psci_common.c \
+ plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c \
+ plat/imx/imx8m/imx8mp/imx8mp_psci.c \
+ plat/imx/imx8m/imx8mp/gpc.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx_sip_handler.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_uart_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/tzc/tzc380.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${IMX_GIC_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS}
+
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+BL32_BASE ?= 0x56000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE ?= 0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE ?= 0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
new file mode 100644
index 0000000..9f472d6
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+#define NOC_PDN_SLT_CTRL BIT(10)
+#define NOC_PUP_SLT_CTRL BIT(11)
+#define NOC_PGC_PDN_ACK BIT(3)
+#define NOC_PGC_PUP_ACK BIT(19)
+
+#define DDRMIX_PWR_REQ BIT(5)
+#define DDRMIX_ADB400_SYNC BIT(1)
+#define DDRMIX_ADB400_ACK BIT(18)
+#define DDRMIX_PGC 0xd40
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 6033b0d..89a0b9d 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -7,74 +7,7 @@
#ifndef IMX8M_GPC_H
#define IMX8M_GPC_H
-#define LPCR_A53_BSC 0x0
-#define LPCR_A53_BSC2 0x108
-#define LPCR_A53_AD 0x4
-#define LPCR_M4 0x8
-#define SLPCR 0x14
-#define MST_CPU_MAPPING 0x18
-#define MLPCR 0x20
-#define PGC_ACK_SEL_A53 0x24
-#define IMR1_CORE0_A53 0x30
-#define IMR1_CORE1_A53 0x40
-#define IMR1_CORE2_A53 0x1C0
-#define IMR1_CORE3_A53 0x1D0
-#define IMR1_CORE0_M4 0x50
-#define SLT0_CFG 0xB0
-#define GPC_PU_PWRHSK 0x1FC
-#define PGC_CPU_0_1_MAPPING 0xEC
-#define CPU_PGC_UP_TRG 0xF0
-#define PU_PGC_UP_TRG 0xF8
-#define CPU_PGC_DN_TRG 0xFC
-#define PU_PGC_DN_TRG 0x104
-#define A53_CORE0_PGC 0x800
-#define A53_PLAT_PGC 0x900
-#define PLAT_PGC_PCR 0x900
-#define PGC_SCU_TIMING 0x910
-
-#define MASK_DSM_TRIGGER_A53 BIT(31)
-#define IRQ_SRC_A53_WUP BIT(30)
-#define IRQ_SRC_A53_WUP_SHIFT 30
-#define IRQ_SRC_C1 BIT(29)
-#define IRQ_SRC_C0 BIT(28)
-#define IRQ_SRC_C3 BIT(23)
-#define IRQ_SRC_C2 BIT(22)
-#define CORE_WKUP_FROM_GIC (IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
-#define CPU_CLOCK_ON_LPM BIT(14)
-#define A53_CLK_ON_LPM BIT(14)
-#define MASTER0_LPM_HSK BIT(6)
-
-#define L2PGE BIT(31)
-#define EN_L2_WFI_PDN BIT(5)
-#define EN_PLAT_PDN BIT(4)
-
-#define SLPCR_EN_DSM BIT(31)
-#define SLPCR_RBC_EN BIT(30)
-#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
-#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
-#define SLPCR_VSTBY BIT(2)
-#define SLPCR_SBYOS BIT(1)
-#define SLPCR_BYPASS_PMIC_READY BIT(0)
-#define SLPCR_RBC_COUNT_SHIFT 24
-#define SLPCR_STBY_COUNT_SHFT 3
-
-#define A53_DUMMY_PDN_ACK BIT(15)
-#define A53_DUMMY_PUP_ACK BIT(31)
-#define A53_PLAT_PDN_ACK BIT(2)
-#define A53_PLAT_PUP_ACK BIT(18)
-
-#define PLAT_PUP_SLT_CTRL BIT(9)
-#define PLAT_PDN_SLT_CTRL BIT(8)
-
-#define SLT_PLAT_PDN BIT(8)
-#define SLT_PLAT_PUP BIT(9)
-
-#define MASTER1_MAPPING BIT(1)
-#define MASTER2_MAPPING BIT(2)
-
-#define TMR_TCD2_SHIFT 0
-#define TMC_TMR_SHIFT 10
-#define TRC1_TMC_SHIFT 20
+#include <gpc_reg.h>
/* helper macro */
#define A53_LPM_MASK U(0xF)
@@ -83,7 +16,7 @@
#define LPM_MODE(local_state) ((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP)
#define DSM_MODE_MASK BIT(31)
-
+#define CORE_WKUP_FROM_GIC (IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
#define A53_CORE_WUP_SRC(core_id) (1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
#define COREx_PGC_PCR(core_id) (0x800 + (core_id) * 0x40)
#define COREx_WFI_PDN(core_id) (1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
@@ -95,6 +28,33 @@
#define IRQ_IMR_NUM 4
#define IMR_MASK_ALL 0xffffffff
+#define IMX_PD_DOMAIN(name, on) \
+ { \
+ .pwr_req = name##_PWR_REQ, \
+ .pgc_offset = name##_PGC, \
+ .need_sync = false, \
+ .always_on = true, \
+ }
+
+#define IMX_MIX_DOMAIN(name, on) \
+ { \
+ .pwr_req = name##_PWR_REQ, \
+ .pgc_offset = name##_PGC, \
+ .adb400_sync = name##_ADB400_SYNC, \
+ .adb400_ack = name##_ADB400_ACK, \
+ .need_sync = true, \
+ .always_on = true, \
+ }
+
+struct imx_pwr_domain {
+ uint32_t pwr_req;
+ uint32_t adb400_sync;
+ uint32_t adb400_ack;
+ uint32_t pgc_offset;
+ bool need_sync;
+ bool always_on;
+};
+
/* function declare */
void imx_gpc_init(void);
void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
diff --git a/plat/marvell/armada/a3700/a3700/board/pm_src.c b/plat/marvell/armada/a3k/a3700/board/pm_src.c
similarity index 100%
rename from plat/marvell/armada/a3700/a3700/board/pm_src.c
rename to plat/marvell/armada/a3k/a3700/board/pm_src.c
diff --git a/plat/marvell/armada/a3700/a3700/mvebu_def.h b/plat/marvell/armada/a3k/a3700/mvebu_def.h
similarity index 100%
rename from plat/marvell/armada/a3700/a3700/mvebu_def.h
rename to plat/marvell/armada/a3k/a3700/mvebu_def.h
diff --git a/plat/marvell/armada/a3700/a3700/plat_bl31_setup.c b/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c
similarity index 100%
rename from plat/marvell/armada/a3700/a3700/plat_bl31_setup.c
rename to plat/marvell/armada/a3k/a3700/plat_bl31_setup.c
diff --git a/plat/marvell/armada/a3700/a3700/platform.mk b/plat/marvell/armada/a3k/a3700/platform.mk
similarity index 75%
rename from plat/marvell/armada/a3700/a3700/platform.mk
rename to plat/marvell/armada/a3k/a3700/platform.mk
index bd9464a..050af41 100644
--- a/plat/marvell/armada/a3700/a3700/platform.mk
+++ b/plat/marvell/armada/a3k/a3700/platform.mk
@@ -5,6 +5,6 @@
# https://spdx.org/licenses
#
-include plat/marvell/armada/a3700/common/a3700_common.mk
+include plat/marvell/armada/a3k/common/a3700_common.mk
include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a3700/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
similarity index 99%
rename from plat/marvell/armada/a3700/common/a3700_common.mk
rename to plat/marvell/armada/a3k/common/a3700_common.mk
index 36865a8..9965567 100644
--- a/plat/marvell/armada/a3700/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -7,7 +7,7 @@
MARVELL_PLAT_BASE := plat/marvell/armada
MARVELL_PLAT_INCLUDE_BASE := include/plat/marvell/armada
-PLAT_FAMILY := a3700
+PLAT_FAMILY := a3k
PLAT_FAMILY_BASE := $(MARVELL_PLAT_BASE)/$(PLAT_FAMILY)
PLAT_INCLUDE_BASE := $(MARVELL_PLAT_INCLUDE_BASE)/$(PLAT_FAMILY)
PLAT_COMMON_BASE := $(PLAT_FAMILY_BASE)/common
diff --git a/plat/marvell/armada/a3700/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/a3700_ea.c
rename to plat/marvell/armada/a3k/common/a3700_ea.c
diff --git a/plat/marvell/armada/a3700/common/a3700_sip_svc.c b/plat/marvell/armada/a3k/common/a3700_sip_svc.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/a3700_sip_svc.c
rename to plat/marvell/armada/a3k/common/a3700_sip_svc.c
diff --git a/plat/marvell/armada/a3700/common/aarch64/a3700_common.c b/plat/marvell/armada/a3k/common/aarch64/a3700_common.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/aarch64/a3700_common.c
rename to plat/marvell/armada/a3k/common/aarch64/a3700_common.c
diff --git a/plat/marvell/armada/a3700/common/aarch64/plat_helpers.S b/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S
similarity index 100%
rename from plat/marvell/armada/a3700/common/aarch64/plat_helpers.S
rename to plat/marvell/armada/a3k/common/aarch64/plat_helpers.S
diff --git a/plat/marvell/armada/a3700/common/dram_win.c b/plat/marvell/armada/a3k/common/dram_win.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/dram_win.c
rename to plat/marvell/armada/a3k/common/dram_win.c
diff --git a/plat/marvell/armada/a3700/common/include/a3700_plat_def.h b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
similarity index 100%
rename from plat/marvell/armada/a3700/common/include/a3700_plat_def.h
rename to plat/marvell/armada/a3k/common/include/a3700_plat_def.h
diff --git a/plat/marvell/armada/a3700/common/include/a3700_pm.h b/plat/marvell/armada/a3k/common/include/a3700_pm.h
similarity index 100%
rename from plat/marvell/armada/a3700/common/include/a3700_pm.h
rename to plat/marvell/armada/a3k/common/include/a3700_pm.h
diff --git a/plat/marvell/armada/a3700/common/include/ddr_info.h b/plat/marvell/armada/a3k/common/include/ddr_info.h
similarity index 100%
rename from plat/marvell/armada/a3700/common/include/ddr_info.h
rename to plat/marvell/armada/a3k/common/include/ddr_info.h
diff --git a/plat/marvell/armada/a3700/common/include/dram_win.h b/plat/marvell/armada/a3k/common/include/dram_win.h
similarity index 100%
rename from plat/marvell/armada/a3700/common/include/dram_win.h
rename to plat/marvell/armada/a3k/common/include/dram_win.h
diff --git a/plat/marvell/armada/a3700/common/include/io_addr_dec.h b/plat/marvell/armada/a3k/common/include/io_addr_dec.h
similarity index 100%
rename from plat/marvell/armada/a3700/common/include/io_addr_dec.h
rename to plat/marvell/armada/a3k/common/include/io_addr_dec.h
diff --git a/plat/marvell/armada/a3700/common/include/plat_macros.S b/plat/marvell/armada/a3k/common/include/plat_macros.S
similarity index 100%
rename from plat/marvell/armada/a3700/common/include/plat_macros.S
rename to plat/marvell/armada/a3k/common/include/plat_macros.S
diff --git a/plat/marvell/armada/a3700/common/include/platform_def.h b/plat/marvell/armada/a3k/common/include/platform_def.h
similarity index 92%
rename from plat/marvell/armada/a3700/common/include/platform_def.h
rename to plat/marvell/armada/a3k/common/include/platform_def.h
index e6660d4..61c7dfe 100644
--- a/plat/marvell/armada/a3700/common/include/platform_def.h
+++ b/plat/marvell/armada/a3k/common/include/platform_def.h
@@ -81,11 +81,13 @@
#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2)
/* DRAM[2MB..66MB] is used as Trusted ROM */
#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
-/* 64 MB TODO: reduce this to minimum needed according to fip image size*/
-#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x04000000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
-#define PLAT_MARVELL_TRUSTED_DRAM_BASE 0x04400000
-#define PLAT_MARVELL_TRUSTED_DRAM_SIZE 0x01000000 /* 16 MB */
+/* 4 MB for FIP image */
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000
+/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE SHMEM follows this region
+ */
+#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */
/*
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
@@ -169,8 +171,7 @@
#define PLAT_MARVELL_NSTIMER_FRAME_ID 1
/* Mailbox base address */
-#define PLAT_MARVELL_MAILBOX_BASE \
- (MARVELL_TRUSTED_SRAM_BASE + 0x400)
+#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE + 0x400)
#define PLAT_MARVELL_MAILBOX_SIZE 0x100
#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */
@@ -221,12 +222,4 @@
/* Securities */
#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
-#define TRUSTED_DRAM_BASE PLAT_MARVELL_TRUSTED_DRAM_BASE
-#define TRUSTED_DRAM_SIZE PLAT_MARVELL_TRUSTED_DRAM_SIZE
-
-#ifdef BL32
-#define BL32_BASE TRUSTED_DRAM_BASE
-#define BL32_LIMIT TRUSTED_DRAM_SIZE
-#endif
-
#endif /* PLATFORM_DEF_H */
diff --git a/plat/marvell/armada/a3700/common/io_addr_dec.c b/plat/marvell/armada/a3k/common/io_addr_dec.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/io_addr_dec.c
rename to plat/marvell/armada/a3k/common/io_addr_dec.c
diff --git a/plat/marvell/armada/a3700/common/marvell_plat_config.c b/plat/marvell/armada/a3k/common/marvell_plat_config.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/marvell_plat_config.c
rename to plat/marvell/armada/a3k/common/marvell_plat_config.c
diff --git a/plat/marvell/armada/a3700/common/plat_pm.c b/plat/marvell/armada/a3k/common/plat_pm.c
similarity index 100%
rename from plat/marvell/armada/a3700/common/plat_pm.c
rename to plat/marvell/armada/a3k/common/plat_pm.c
diff --git a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
index d126f55..a409261 100644
--- a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
@@ -102,6 +102,12 @@
#ifdef IMAGE_BLE
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
{0x00000000f2000000, 0xe000000, IO_0_TID},
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
index f8a1c40..3b68e91 100644
--- a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
@@ -93,6 +93,12 @@
#ifdef IMAGE_BLE
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
{0x00000000f2000000, 0xe000000, IO_0_TID},
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
{0x0000000800000000, 0x200000000, IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
index 7901dd2..4ccda14 100644
--- a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
@@ -131,6 +131,12 @@
#ifdef IMAGE_BLE
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
{0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
index fa4e144..75a1b0c 100644
--- a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
@@ -78,12 +78,8 @@
/* CP1 (MCI0) internal regs */
{0x00000000f4000000, 0x2000000, MCI_0_TID},
#ifndef IMAGE_BLE
- /* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
- {0x00000000f9000000, 0x2000000, MCI_0_TID},
- /* PCIe1 on CP1*/
- {0x00000000fb000000, 0x1000000, MCI_0_TID},
- /* PCIe2 on CP1*/
- {0x00000000fc000000, 0x1000000, MCI_0_TID},
+ /* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/
+ {0x00000000f9000000, 0x4000000, MCI_0_TID},
/* MCI 0 indirect window */
{MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
/* MCI 1 indirect window */
@@ -165,6 +161,12 @@
#ifdef IMAGE_BLE
{0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
{0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
{0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
{0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
new file mode 100644
index 0000000..46a9a26
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/mentor/mi2cv.h>
+#include <lib/mmio.h>
+
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0)
+#define MVEBU_AP_MPP_CTRL4_OFFS 16
+#define MVEBU_AP_MPP_CTRL5_OFFS 20
+#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3
+#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3
+
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
+#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
+
+#define MVEBU_MPP_CTRL_MASK 0xf
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+ /* Board with 1CS 8Gb x4 devices of Micron 2400T */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0} },
+ /* TODO: double check if the speed bin is 2400T */
+ SPEED_BIN_DDR_2400T, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ MV_DDR_64BIT_BUS_MASK, /* subphys mask */
+ MV_DDR_CFG_SPD, /* ddr configuration data source */
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
+
+static void mpp_config(void)
+{
+ uint32_t val;
+ uintptr_t reg;
+
+ /* configure ap mmps 4, 5 to I2C */
+ reg = MVEBU_AP_MPP_CTRL0_7_REG;
+
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL4_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL5_OFFS));
+ val |= ((MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA << MVEBU_AP_MPP_CTRL4_OFFS) |
+ (MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA << MVEBU_AP_MPP_CTRL5_OFFS));
+
+ mmio_write_32(reg, val);
+}
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ INFO("Gathering DRAM information\n");
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ /* configure MPPs to enable i2c */
+ mpp_config();
+ /* initialize the MVEBU_AP_I2C_BASE I2C bus */
+ i2c_init((void *)MVEBU_AP_I2C_BASE);
+ /* select SPD memory page 0 to access DRAM configuration */
+ i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
+ /* read data from spd */
+ i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
+ sizeof(tm->spd_data.all_bytes));
+ }
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
new file mode 100644
index 0000000..0edc977
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * GPIO Configuration
+ *****************************************************************************
+ */
+#define MPP_CONTROL_REGISTER 0xf2440018
+#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000
+#define GPIO_DATA_OUT1_REGISTER 0xf2440140
+#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144
+#define GPIO52_MASK 0x100000
+
+/* Reset PCIe via GPIO number 52 */
+int marvell_gpio_config(void)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(MPP_CONTROL_REGISTER);
+ reg |= MPP_CONTROL_MPP_SEL_52_MASK;
+ mmio_write_32(MPP_CONTROL_REGISTER, reg);
+
+ reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER);
+ reg |= GPIO52_MASK;
+ mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg);
+
+ reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER);
+ reg &= ~GPIO52_MASK;
+ mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg);
+ udelay(100);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP1 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+ /* CP1 (MCI0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+#ifndef IMAGE_BLE
+ /* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
+ {0x00000000f9000000, 0x2000000, MCI_0_TID},
+ /* PCIe1 on CP1*/
+ {0x00000000fb000000, 0x1000000, MCI_0_TID},
+ /* PCIe2 on CP1*/
+ {0x00000000fc000000, 0x1000000, MCI_0_TID},
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* CP0 */
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ {0x00000000c0000000, 0x30000000, PEX0_TID},
+ {0x0000000800000000, 0x100000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+ /* CP1 */
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+ /* PEX1_X1 window */
+ {0x00000000fb000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000fc000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000fa000000, 0x1000000, PEX0_TID}
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
+
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* No recovery button on A8k-MCBIN board */
+ return NULL;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
new file mode 100644
index 0000000..5147dd5
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Sartura Ltd.
+ * Author: Luka Kovacic <luka.kovacic@sartura.hr>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <drivers/console.h>
+#include <plat_marvell.h>
+
+/*****************************************************************************
+ * Platform specific power off functions
+ * Power off PSU / Send command to power management MCU / ...
+ *****************************************************************************
+ */
+
+unsigned char add_xor_checksum(unsigned char *buf, unsigned char xor_len)
+{
+ unsigned char xor_sum = 0;
+ unsigned int i;
+
+ for (i = 0; i < xor_len; i++)
+ xor_sum ^= buf[i];
+
+ return xor_sum;
+}
+
+int system_power_off(void)
+{
+ static console_t console;
+
+ /* WT61P803 MCU system_off_now command */
+ unsigned char system_off_now[4] = { '@', 'C', '0' };
+ int i, len;
+
+ len = sizeof(system_off_now);
+ system_off_now[len - 1] = add_xor_checksum(system_off_now, len);
+
+ console_16550_register(PLAT_MARVELL_BOOT_UART_BASE + 0x100,
+ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ, 115200, &console);
+
+ /* Send system_off_now to console */
+ for (i = 0; i < len; i++) {
+ console.putc(system_off_now[i], &console);
+ udelay(1000);
+ }
+
+ console.flush(&console);
+ (void)console_unregister(&console);
+
+ mdelay(100);
+
+ return 0;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
new file mode 100644
index 0000000..3fa119a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
+#define I2C_SPD_ADDR 0x53 /* Access SPD data */
+#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
new file mode 100644
index 0000000..3378d53
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 2
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index 8731aa6..02f1553 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -37,7 +37,7 @@
DOIMAGE_FLAGS += -b $(ROM_BIN_EXT) $(NAND_DOIMAGE_FLAGS) $(DOIMAGE_SEC_FLAGS)
# Check whether to build system_power.c for the platform
-ifneq ("$(wildcard $(PLAT_FAMILY_BASE)/$(PLAT)/board/system_power.c)","")
+ifneq ("$(wildcard $(BOARD_DIR)/board/system_power.c)","")
SYSTEM_POWER_SUPPORT = 1
else
SYSTEM_POWER_SUPPORT = 0
@@ -52,6 +52,7 @@
plat/common/plat_gicv2.c
PLAT_INCLUDES := -I$(BOARD_DIR) \
+ -I$(BOARD_DIR)/board \
-I$(PLAT_COMMON_BASE)/include \
-I$(PLAT_INCLUDE_BASE)/common
@@ -84,12 +85,13 @@
$(MARVELL_DRV_BASE)/ccu.c \
$(MARVELL_DRV_BASE)/cache_llc.c \
$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
- $(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c
+ $(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
+ $(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
BL31_PORTING_SOURCES := $(BOARD_DIR)/board/marvell_plat_config.c
ifeq ($(SYSTEM_POWER_SUPPORT),1)
-BL31_PORTING_SOURCES += $(PLAT_FAMILY_BASE)/$(PLAT)/board/system_power.c
+BL31_PORTING_SOURCES += $(BOARD_DIR)/board/system_power.c
endif
BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
diff --git a/plat/marvell/armada/a8k/common/aarch64/a8k_common.c b/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
index 7c2bf31..4332a76 100644
--- a/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
+++ b/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
@@ -18,22 +18,27 @@
*/
#if IMAGE_BL1
const mmap_region_t plat_marvell_mmap[] = {
- MARVELL_MAP_SHARED_RAM,
+ MARVELL_MAP_SECURE_RAM,
MAP_DEVICE0,
{0}
};
#endif
#if IMAGE_BL2
const mmap_region_t plat_marvell_mmap[] = {
- MARVELL_MAP_SHARED_RAM,
+ MARVELL_MAP_SECURE_RAM,
MAP_DEVICE0,
MARVELL_MAP_DRAM,
+#ifdef SPD_opteed
+ MARVELL_MAP_OPTEE_CORE_MEM,
+ MARVELL_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
{0}
};
#endif
#if IMAGE_BL2U
const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
MAP_DEVICE0,
{0}
};
@@ -48,7 +53,7 @@
#if IMAGE_BL31
const mmap_region_t plat_marvell_mmap[] = {
- MARVELL_MAP_SHARED_RAM,
+ MARVELL_MAP_SECURE_RAM,
MAP_DEVICE0,
MARVELL_MAP_DRAM,
{0}
@@ -56,6 +61,7 @@
#endif
#if IMAGE_BL32
const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
MAP_DEVICE0,
{0}
};
diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
index 82ac098..60fbf5f 100644
--- a/plat/marvell/armada/a8k/common/ble/ble.mk
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
@@ -5,9 +5,9 @@
MV_DDR_PATH ?= drivers/marvell/mv_ddr
-MV_DDR_LIB = $(CURDIR)/$(BUILD_PLAT)/ble/mv_ddr_lib.a
-LIBC_LIB = $(CURDIR)/$(BUILD_PLAT)/lib/libc.a
-BLE_LIBS = $(MV_DDR_LIB) $(LIBC_LIB)
+MV_DDR_LIB = $(BUILD_PLAT)/ble/mv_ddr_lib.a
+LIBC_LIB = $(BUILD_PLAT)/lib/libc.a
+BLE_LIBS = $(MV_DDR_LIB) $(LIBC_LIB)
PLAT_MARVELL = plat/marvell/armada
BLE_SOURCES += $(BLE_PATH)/ble_main.c \
@@ -29,4 +29,4 @@
FORCE:
$(MV_DDR_LIB): FORCE
- @+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(PLAT_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(CURDIR)/$(BUILD_PLAT)/ble
+ @+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(PLAT_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
diff --git a/plat/marvell/armada/a8k/common/include/platform_def.h b/plat/marvell/armada/a8k/common/include/platform_def.h
index ec1c903..944a151 100644
--- a/plat/marvell/armada/a8k/common/include/platform_def.h
+++ b/plat/marvell/armada/a8k/common/include/platform_def.h
@@ -92,13 +92,18 @@
#define PLAT_MARVELL_CORE_COUNT (PLAT_MARVELL_CLUSTER_COUNT * \
PLAT_MARVELL_CLUSTER_CORE_COUNT)
-/* DRAM[2MB..66MB] is used as Trusted ROM */
+/* Part of DRAM that is used as Trusted ROM */
#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
-/* 64 MB TODO: reduce this to minimum needed according to fip image size */
-#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x04000000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
-#define PLAT_MARVELL_TRUSTED_DRAM_BASE 0x04400000
-#define PLAT_MARVELL_TRUSTED_DRAM_SIZE 0x01000000 /* 16 MB */
+/* 4 MB for FIP image */
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000
+/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE 4MB SHMEM follows this region
+ */
+#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */
+
+#define PLAT_MARVELL_LLC_SRAM_BASE 0x05400000
+#define PLAT_MARVELL_LLC_SRAM_SIZE 0x00100000 /* 1 MB SRAM */
/*
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
@@ -182,22 +187,14 @@
/* Mailbox base address (note the lower memory space
* is reserved for BLE data)
*/
-#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_TRUSTED_SRAM_BASE \
- + 0x400)
+#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE \
+ + 0x400)
#define PLAT_MARVELL_MAILBOX_SIZE 0x100
#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */
/* Securities */
#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
-#define TRUSTED_DRAM_BASE PLAT_MARVELL_TRUSTED_DRAM_BASE
-#define TRUSTED_DRAM_SIZE PLAT_MARVELL_TRUSTED_DRAM_SIZE
-
-#ifdef BL32
-#define BL32_BASE TRUSTED_DRAM_BASE
-#define BL32_LIMIT TRUSTED_DRAM_SIZE
-#endif
-
#define MVEBU_PMU_IRQ_WA
#endif /* PLATFORM_DEF_H */
diff --git a/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
index 09b8446..c2cd933 100644
--- a/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
+++ b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
@@ -10,6 +10,7 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/marvell/ccu.h>
+#include <drivers/marvell/mochi/ap_setup.h>
#include <drivers/marvell/mochi/cp110_setup.h>
#include <lib/mmio.h>
@@ -18,9 +19,6 @@
#include "mss_scp_bootloader.h"
-/* IO windows configuration */
-#define IOW_GCR_OFFSET (0x70)
-
/* MSS windows configuration */
#define MSS_AEBR(base) (base + 0x160)
#define MSS_AIBR(base) (base + 0x164)
@@ -51,7 +49,7 @@
*/
static int bl2_plat_mmap_init(void)
{
- int cfg_num, win_id, cfg_idx;
+ int cfg_num, win_id, cfg_idx, cp;
cfg_num = ARRAY_SIZE(ccu_mem_map);
@@ -65,20 +63,29 @@
* Do not touch CCU window 0,
* it's used for the internal registers access
*/
- for (cfg_idx = 0, win_id = 1; cfg_idx < cfg_num; cfg_idx++, win_id++) {
+ for (cfg_idx = 0, win_id = 1;
+ (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
+ /* Skip already enabled CCU windows */
+ if (ccu_is_win_enabled(MVEBU_AP0, win_id))
+ continue;
/* Enable required CCU windows */
ccu_win_check(&ccu_mem_map[cfg_idx]);
ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
+ cfg_idx++;
}
- /* Set the default target id to PIDI */
- mmio_write_32(MVEBU_IO_WIN_BASE(MVEBU_AP0) + IOW_GCR_OFFSET, PIDI_TID);
+ /* Config address for each cp other than cp0 */
+ for (cp = 1; cp < CP_COUNT; cp++)
+ update_cp110_default_win(cp);
+
+ /* There is need to configure IO_WIN windows again to overwrite
+ * temporary configuration done during update_cp110_default_win
+ */
+ init_io_win(MVEBU_AP0);
/* Open AMB bridge required for MG access */
- cp110_amb_init(MVEBU_CP_REGS_BASE(0));
-
- if (CP_COUNT == 2)
- cp110_amb_init(MVEBU_CP_REGS_BASE(1));
+ for (cp = 0; cp < CP_COUNT; cp++)
+ cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
return 0;
}
diff --git a/plat/marvell/armada/a8k/common/plat_bl31_setup.c b/plat/marvell/armada/a8k/common/plat_bl31_setup.c
index 621f43c..552c9b2 100644
--- a/plat/marvell/armada/a8k/common/plat_bl31_setup.c
+++ b/plat/marvell/armada/a8k/common/plat_bl31_setup.c
@@ -116,21 +116,12 @@
marvell_bl31_plat_arch_setup();
for (cp = 0; cp < CP_COUNT; cp++) {
- if (cp >= 1)
- update_cp110_default_win(cp);
-
cp110_init(MVEBU_CP_REGS_BASE(cp),
STREAM_ID_BASE + (cp * MAX_STREAM_ID_PER_CP));
marvell_bl31_mpp_init(cp);
}
- /*
- * There is need to configure IO_WIN windows again to overwrite
- * temporary configuration done during update_cp110_default_win
- */
- init_io_win(MVEBU_AP0);
-
for (cp = 1; cp < CP_COUNT; cp++)
mci_link_tune(cp - 1);
diff --git a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
index 6a8e11c..8d909dc 100644
--- a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
+++ b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
@@ -100,6 +100,45 @@
.next_handoff_image_id = BL33_IMAGE_ID,
},
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE
+ * where it is the pager image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE,
+ * where it is the paged image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = MARVELL_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = MARVELL_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
# endif /* BL32_BASE */
/* Fill BL33 related information */
diff --git a/plat/marvell/armada/common/aarch64/marvell_helpers.S b/plat/marvell/armada/common/aarch64/marvell_helpers.S
index 6f625b9..4ddc73d 100644
--- a/plat/marvell/armada/common/aarch64/marvell_helpers.S
+++ b/plat/marvell/armada/common/aarch64/marvell_helpers.S
@@ -185,7 +185,7 @@
/* Invalidate all ways */
ldr w1, =LLC_WAY_MASK
- ldr x0, =MASTER_L2X0_INV_WAY
+ ldr x0, =MASTER_LLC_INV_WAY
str w1, [x0]
/* Finally disable LLC */
diff --git a/plat/marvell/armada/common/marvell_bl2_setup.c b/plat/marvell/armada/common/marvell_bl2_setup.c
index 3c1c391..3dfa82e 100644
--- a/plat/marvell/armada/common/marvell_bl2_setup.c
+++ b/plat/marvell/armada/common/marvell_bl2_setup.c
@@ -17,6 +17,9 @@
#include <drivers/console.h>
#include <lib/utils.h>
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
#include <marvell_def.h>
#include <plat_marvell.h>
@@ -97,9 +100,29 @@
int err = 0;
bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif /* SPD_opteed */
assert(bl_mem_params);
switch (image_id) {
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0)
+ WARN("OPTEE header parse error.\n");
+#endif /* SPD_opteed */
+ bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl32_entry();
+ break;
case BL33_IMAGE_ID:
/* BL33 expects to receive the primary CPU MPID (through r0) */
diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
index f5f0c41..2e96e2f 100644
--- a/plat/marvell/armada/common/marvell_common.mk
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -16,6 +16,11 @@
# flag to switch from PLL to ARO
ARO_ENABLE := 0
$(eval $(call add_define,ARO_ENABLE))
+
+# Convert LLC to secure SRAM
+LLC_SRAM := 0
+$(eval $(call add_define,LLC_SRAM))
+
# Enable/Disable LLC
LLC_ENABLE := 1
$(eval $(call add_define,LLC_ENABLE))
@@ -53,6 +58,10 @@
$(MARVELL_PLAT_BASE)/common/aarch64/marvell_bl2_mem_params_desc.c \
$(MARVELL_PLAT_BASE)/common/marvell_image_load.c
+ifeq (${SPD},opteed)
+PLAT_INCLUDES += -Iinclude/lib
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
BL31_SOURCES += $(MARVELL_PLAT_BASE)/common/marvell_bl31_setup.c \
$(MARVELL_PLAT_BASE)/common/marvell_pm.c \
@@ -64,6 +73,15 @@
# PSCI functionality
$(eval $(call add_define,CONFIG_ARM64))
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
# MSS (SCP) build
ifeq (${MSS_SUPPORT}, 1)
include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk
diff --git a/plat/marvell/armada/common/marvell_io_storage.c b/plat/marvell/armada/common/marvell_io_storage.c
index 065f956..2627ba4 100644
--- a/plat/marvell/armada/common/marvell_io_storage.c
+++ b/plat/marvell/armada/common/marvell_io_storage.c
@@ -43,6 +43,15 @@
static const io_uuid_spec_t bl32_uuid_spec = {
.uuid = UUID_SECURE_PAYLOAD_BL32,
};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
static const io_uuid_spec_t bl33_uuid_spec = {
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
};
@@ -83,6 +92,16 @@
(uintptr_t)&bl32_uuid_spec,
open_fip
},
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
[BL33_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
index 7150f0a..74dddc6 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
@@ -13,7 +13,6 @@
#define HEADER_VERSION 0x1
#define MSS_IDRAM_SIZE 0x10000 /* 64KB */
-#define MG_SRAM_SIZE 0x20000 /* 128KB */
/* Types definitions */
typedef struct file_header {
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
index 4473d81..adf570e 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
@@ -12,6 +12,7 @@
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
#include <lib/mmio.h>
#include <plat_pm_trace.h>
@@ -42,8 +43,6 @@
#define MSS_HANDSHAKE_TIMEOUT 50
-#define MG_CM3_SRAM_BASE(CP) (MVEBU_CP_REGS_BASE(CP) + 0x100000)
-
static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
{
int timeout = MSS_HANDSHAKE_TIMEOUT;
@@ -61,28 +60,6 @@
return 0;
}
-static int mg_image_load(uintptr_t src_addr, uint32_t size, uintptr_t mg_regs)
-{
- if (size > MG_SRAM_SIZE) {
- ERROR("image is too big to fit into MG CM3 memory\n");
- return 1;
- }
-
- NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
- src_addr, size, mg_regs);
-
- /* Copy image to MG CM3 SRAM */
- memcpy((void *)mg_regs, (void *)src_addr, size);
-
- /*
- * Don't release MG CM3 from reset - it will be done by next step
- * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
- * has enabeld 802.3. auto-neg) will be choosen.
- */
-
- return 0;
-}
-
static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
{
uint32_t i, loop_num, timeout;
@@ -258,8 +235,7 @@
break;
}
NOTICE("Load image to CP%d MG\n", cp_index);
- ret = mg_image_load(single_img, image_size,
- MG_CM3_SRAM_BASE(cp_index));
+ ret = mg_image_load(single_img, image_size, cp_index);
if (ret != 0) {
ERROR("SCP Image load failed\n");
return -1;
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index 5555f5d..4d69ccc 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -280,57 +280,33 @@
{
int ret;
+ INFO("Cleaning previous Video Memory Carveout\n");
+
/*
* Map the NS memory first, clean it and then unmap it.
*/
ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
non_overlap_area_start, /* VA */
non_overlap_area_size, /* size */
- MT_NS | MT_RW | MT_EXECUTE_NEVER |
- MT_NON_CACHEABLE); /* attrs */
+ MT_DEVICE | MT_RW | MT_NS); /* attrs */
assert(ret == 0);
- zero_normalmem((void *)non_overlap_area_start, non_overlap_area_size);
+ zeromem((void *)non_overlap_area_start, non_overlap_area_size);
flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
- (void)mmap_remove_dynamic_region(non_overlap_area_start,
+ ret = mmap_remove_dynamic_region(non_overlap_area_start,
non_overlap_area_size);
+ assert(ret == 0);
}
-/*
- * Program the Video Memory carveout region
- *
- * phys_base = physical base of aperture
- * size_in_bytes = size of aperture in bytes
- */
-void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
+static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base,
+ unsigned long size_in_bytes)
{
uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20);
uintptr_t vmem_end_new = phys_base + size_in_bytes;
unsigned long long non_overlap_area_size;
/*
- * Setup the Memory controller to restrict CPU accesses to the Video
- * Memory region
- */
- INFO("Configuring Video Memory Carveout\n");
-
- /*
- * Configure Memory Controller directly for the first time.
- */
- if (video_mem_base == 0U)
- goto done;
-
- /*
- * Lock the non overlapping memory being cleared so that other masters
- * do not accidently write to it. The memory would be unlocked once
- * the non overlapping region is cleared and the new memory
- * settings take effect.
- */
- tegra_lock_videomem_nonoverlap(video_mem_base,
- video_mem_size_mb << 20);
-
- /*
* Clear the old regions now being exposed. The following cases
* can occur -
*
@@ -338,8 +314,6 @@
* 2. clear old sub-region below new base
* 3. clear old sub-region above new end
*/
- INFO("Cleaning previous Video Memory Carveout\n");
-
if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) {
tegra_clear_videomem(video_mem_base,
video_mem_size_mb << 20U);
@@ -353,26 +327,55 @@
tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
}
}
+}
-done:
+/*
+ * Program the Video Memory carveout region
+ *
+ * phys_base = physical base of aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+ /*
+ * Setup the Memory controller to restrict CPU accesses to the Video
+ * Memory region
+ */
+
+ INFO("Configuring Video Memory Carveout\n");
+
+ if (video_mem_base != 0U) {
+ /*
+ * Lock the non overlapping memory being cleared so that
+ * other masters do not accidently write to it. The memory
+ * would be unlocked once the non overlapping region is
+ * cleared and the new memory settings take effect.
+ */
+ tegra_lock_videomem_nonoverlap(video_mem_base,
+ video_mem_size_mb << 20);
+ }
+
/* program the Videomem aperture */
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
(uint32_t)(phys_base >> 32));
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
- /* unlock the previous locked nonoverlapping aperture */
- tegra_unlock_videomem_nonoverlap();
-
- /* store new values */
- video_mem_base = phys_base;
- video_mem_size_mb = size_in_bytes >> 20;
-
/*
* MCE propagates the VideoMem configuration values across the
* CCPLEX.
*/
- mce_update_gsc_videomem();
+ (void)mce_update_gsc_videomem();
+
+ /* Clear the non-overlapping memory */
+ if (video_mem_base != 0U) {
+ tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes);
+ tegra_unlock_videomem_nonoverlap();
+ }
+
+ /* store new values */
+ video_mem_base = phys_base;
+ video_mem_size_mb = (uint64_t)size_in_bytes >> 20;
}
/*
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 269afb1..40713b2 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -367,7 +367,15 @@
int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
{
uint64_t end = base + size_in_bytes - U(1);
- int32_t ret = 0;
+
+ /*
+ * Sanity check the input values
+ */
+ if ((base == 0U) || (size_in_bytes == 0U)) {
+ ERROR("NS address 0x%llx (%lld bytes) is invalid\n",
+ base, size_in_bytes);
+ return -EINVAL;
+ }
/*
* Check if the NS DRAM address is valid
@@ -376,7 +384,7 @@
(end > TEGRA_DRAM_END)) {
ERROR("NS address 0x%llx is out-of-bounds!\n", base);
- ret = -EFAULT;
+ return -EFAULT;
}
/*
@@ -385,9 +393,9 @@
*/
if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) {
ERROR("NS address 0x%llx overlaps TZDRAM!\n", base);
- ret = -ENOTSUP;
+ return -ENOTSUP;
}
/* valid NS address */
- return ret;
+ return 0;
}
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index a86a315..f412a80 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -14,9 +14,16 @@
COMMON_DIR := plat/nvidia/tegra/common
-TEGRA_GICv2_SOURCES := drivers/arm/gic/common/gic_common.c \
- drivers/arm/gic/v2/gicv2_main.c \
- drivers/arm/gic/v2/gicv2_helpers.c \
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+TEGRA_GICv3_SOURCES := $(GICV3_SOURCES) \
+ plat/common/plat_gicv3.c \
+ ${COMMON_DIR}/tegra_gicv3.c
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+TEGRA_GICv2_SOURCES := ${GICV2_SOURCES} \
plat/common/plat_gicv2.c \
${COMMON_DIR}/tegra_gicv2.c
diff --git a/plat/nvidia/tegra/common/tegra_gicv3.c b/plat/nvidia/tegra/common/tegra_gicv3.c
new file mode 100644
index 0000000..cba2f9b
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_gicv3.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <tegra_private.h>
+#include <tegra_def.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static unsigned int plat_tegra_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+/******************************************************************************
+ * Tegra common helper to setup the GICv3 driver data.
+ *****************************************************************************/
+void tegra_gic_setup(const interrupt_prop_t *interrupt_props,
+ unsigned int interrupt_props_num)
+{
+ /*
+ * Tegra GIC configuration settings
+ */
+ static gicv3_driver_data_t tegra_gic_data;
+
+ /*
+ * Register Tegra GICv3 driver
+ */
+ tegra_gic_data.gicd_base = TEGRA_GICD_BASE;
+ tegra_gic_data.gicr_base = TEGRA_GICR_BASE;
+ tegra_gic_data.rdistif_num = PLATFORM_CORE_COUNT;
+ tegra_gic_data.rdistif_base_addrs = rdistif_base_addrs;
+ tegra_gic_data.mpidr_to_core_pos = plat_tegra_mpidr_to_core_pos;
+ tegra_gic_data.interrupt_props = interrupt_props;
+ tegra_gic_data.interrupt_props_num = interrupt_props_num;
+ gicv3_driver_init(&tegra_gic_data);
+
+ /* initialize the GICD and GICR */
+ tegra_gic_init();
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the GICv3 only driver.
+ *****************************************************************************/
+void tegra_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Tegra common helper to disable the GICv3 CPU interface
+ *****************************************************************************/
+void tegra_gic_cpuif_deactivate(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the per cpu distributor interface
+ * in GICv3
+ *****************************************************************************/
+void tegra_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
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/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 3d61f06..a4724e6 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -62,7 +62,7 @@
$(eval $(call add_define,RELOCATE_BL32_IMAGE))
# modify BUILD_PLAT to point to SoC specific build directory
-BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_SOC}/${BUILD_TYPE}
+BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${TARGET_SOC}/${BUILD_TYPE}
# platform cflags (enable signed comparisons, disable stdlib)
TF_CFLAGS += -Wsign-compare -nostdlib
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index 0a49d81..cfacd1f 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -17,6 +17,7 @@
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
#include <libfdt.h>
#include <drivers/arm/gicv2.h>
@@ -200,13 +201,6 @@
enable_mmu_el3(0);
}
-static uint32_t dtb_size(const void *dtb)
-{
- const uint32_t *dtb_header = dtb;
-
- return fdt32_to_cpu(dtb_header[1]);
-}
-
static void rpi4_prepare_dtb(void)
{
void *dtb = (void *)rpi4_get_dtb_address();
@@ -250,7 +244,7 @@
if (ret < 0)
ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
- clean_dcache_range((uintptr_t)dtb, dtb_size(dtb));
+ clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
INFO("Changed device tree to advertise PSCI.\n");
}
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
index 679f14d..4524610 100644
--- a/plat/socionext/uniphier/uniphier_bl2_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -21,8 +21,8 @@
#include "uniphier.h"
-#define UNIPHIER_IMAGE_BUF_OFFSET 0x04300000UL
-#define UNIPHIER_IMAGE_BUF_SIZE 0x00100000UL
+#define UNIPHIER_IMAGE_BUF_OFFSET 0x03800000UL
+#define UNIPHIER_IMAGE_BUF_SIZE 0x00800000UL
static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
diff --git a/plat/socionext/uniphier/uniphier_image_desc.c b/plat/socionext/uniphier/uniphier_image_desc.c
index 8c232ba..dd62d1e 100644
--- a/plat/socionext/uniphier/uniphier_image_desc.c
+++ b/plat/socionext/uniphier/uniphier_image_desc.c
@@ -14,9 +14,9 @@
#include "uniphier.h"
#define UNIPHIER_BL33_OFFSET 0x04000000UL
-#define UNIPHIER_BL33_MAX_SIZE 0x00100000UL
+#define UNIPHIER_BL33_MAX_SIZE 0x00800000UL
-#define UNIPHIER_SCP_OFFSET 0x04100000UL
+#define UNIPHIER_SCP_OFFSET 0x04800000UL
#define UNIPHIER_SCP_MAX_SIZE 0x00020000UL
static struct bl_mem_params_node uniphier_image_descs[] = {
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 77d1eaf..92e15b0 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -25,8 +25,8 @@
#define UNIPHIER_OCM_REGION_SIZE 0x00040000ULL
-#define UNIPHIER_BLOCK_BUF_OFFSET 0x04200000UL
-#define UNIPHIER_BLOCK_BUF_SIZE 0x00100000UL
+#define UNIPHIER_BLOCK_BUF_OFFSET 0x03000000UL
+#define UNIPHIER_BLOCK_BUF_SIZE 0x00800000UL
static const io_dev_connector_t *uniphier_fip_dev_con;
static uintptr_t uniphier_fip_dev_handle;
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
new file mode 100644
index 0000000..13f4b13
--- /dev/null
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SHARED_RESOURCES_H
+#define STM32MP_SHARED_RESOURCES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef STM32MP_SHARED_RESOURCES
+enum stm32mp_shres;
+
+/* Return true if @clock_id is shared by secure and non-secure worlds */
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
+
+/* Return true if and only if @reset_id relates to a non-secure peripheral */
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
+
+/* Register a shared resource assigned to the secure world */
+void stm32mp_register_secure_periph(enum stm32mp_shres id);
+
+/* Register a shared resource assigned to the non-secure world */
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id);
+
+/* Register a peripheral as secure or non-secure based on IO base address */
+void stm32mp_register_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base);
+
+/* Register a GPIO as secure or non-secure based on its bank and pin numbers */
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
+
+/* Consolidate peripheral states and lock against new peripheral registering */
+void stm32mp_lock_periph_registering(void);
+#else
+static inline void stm32mp_register_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline void stm32mp_register_secure_gpio(unsigned int bank __unused,
+ unsigned int pin __unused)
+{
+}
+
+static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused,
+ unsigned int pin __unused)
+{
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+#endif /* STM32MP_SHARED_RESOURCES_H */
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_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..3f6367e
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <stm32mp_shared_resources.h>
+
+#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i))
+
+enum stm32mp_shres {
+ STM32MP1_SHRES_CRYP1,
+ STM32MP1_SHRES_GPIOZ_0,
+ STM32MP1_SHRES_GPIOZ_1,
+ STM32MP1_SHRES_GPIOZ_2,
+ STM32MP1_SHRES_GPIOZ_3,
+ STM32MP1_SHRES_GPIOZ_4,
+ STM32MP1_SHRES_GPIOZ_5,
+ STM32MP1_SHRES_GPIOZ_6,
+ STM32MP1_SHRES_GPIOZ_7,
+ STM32MP1_SHRES_HASH1,
+ STM32MP1_SHRES_I2C4,
+ STM32MP1_SHRES_I2C6,
+ STM32MP1_SHRES_IWDG1,
+ STM32MP1_SHRES_MCU,
+ STM32MP1_SHRES_MDMA,
+ STM32MP1_SHRES_PLL3,
+ STM32MP1_SHRES_RNG1,
+ STM32MP1_SHRES_RTC,
+ STM32MP1_SHRES_SPI6,
+ STM32MP1_SHRES_USART1,
+
+ STM32MP1_SHRES_COUNT
+};
+#endif /* STM32MP1_SHARED_RESOURCES_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/platform.mk b/plat/st/stm32mp1/platform.mk
index b0ba82a..9998236 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -16,6 +16,11 @@
$(eval $(call assert_boolean,PLAT_XLAT_TABLES_DYNAMIC))
$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+ifeq ($(AARCH32_SP),sp_min)
+# Disable Neon support: sp_min runtime may conflict with non-secure world
+TF_CFLAGS += -mfloat-abi=soft
+endif
+
# Not needed for Cortex-A7
WORKAROUND_CVE_2017_5715:= 0
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 180620e..5d7d495 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -6,10 +6,13 @@
SP_MIN_WITH_SECURE_FIQ := 1
+BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES
+
BL32_SOURCES += drivers/st/etzpc/etzpc.c \
plat/common/aarch32/platform_mp_stack.S \
plat/st/stm32mp1/sp_min/sp_min_setup.c \
plat/st/stm32mp1/stm32mp1_pm.c \
+ plat/st/stm32mp1/stm32mp1_shared_resources.c \
plat/st/stm32mp1/stm32mp1_topology.c
# Generic GIC v2
@@ -22,6 +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 e1799ed..b639fcb 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -77,24 +77,35 @@
return next_image_info;
}
+CASSERT((STM32MP_SEC_SYSRAM_BASE == STM32MP_SYSRAM_BASE) &&
+ ((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <=
+ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+ assert_secure_sysram_fits_at_begining_of_sysram);
+
+#ifdef STM32MP_NS_SYSRAM_BASE
+CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) &&
+ ((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) ==
+ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+ assert_non_secure_sysram_fits_at_end_of_sysram);
+
+CASSERT((STM32MP_NS_SYSRAM_BASE & (PAGE_SIZE_4KB - U(1))) == 0U,
+ assert_non_secure_sysram_base_is_4kbyte_aligned);
+
+#define TZMA1_SECURE_RANGE \
+ (((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> FOUR_KB_SHIFT) - 1U)
+#else
#define TZMA1_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
+#endif /* STM32MP_NS_SYSRAM_BASE */
#define TZMA0_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
static void stm32mp1_etzpc_early_setup(void)
{
- unsigned int n;
-
if (etzpc_init() != 0) {
panic();
}
etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
-
- /* Release security on all shared resources */
- for (n = 0; n < STM32MP1_ETZPC_SEC_ID_LIMIT; n++) {
- etzpc_configure_decprot(n, ETZPC_DECPROT_NS_RW);
- }
}
/*******************************************************************************
@@ -181,14 +192,13 @@
stm32mp1_gic_init();
- /* Set GPIO bank Z as non secure */
- for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) {
- set_gpio_secure_cfg(GPIO_BANK_Z, pin, false);
- }
-
if (stm32_iwdg_init() < 0) {
panic();
}
+
+ 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 0a12b6e..ea18a30 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -25,6 +25,7 @@
#include <stm32mp_shres_helpers.h>
#include <stm32mp1_dbgmcu.h>
#include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
#endif
/*******************************************************************************
@@ -56,6 +57,18 @@
#define STM32MP_SYSRAM_BASE U(0x2FFC0000)
#define STM32MP_SYSRAM_SIZE U(0x00040000)
+#define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE
+#define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \
+ 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)
+
/* DDR configuration */
#define STM32MP_DDR_BASE U(0xC0000000)
#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
@@ -81,18 +94,18 @@
/* 256 Octets reserved for header */
#define STM32MP_HEADER_SIZE U(0x00000100)
-#define STM32MP_BINARY_BASE (STM32MP_SYSRAM_BASE + \
+#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \
STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE)
-#define STM32MP_BINARY_SIZE (STM32MP_SYSRAM_SIZE - \
+#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \
(STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE))
#ifdef AARCH32_SP_OPTEE
#define STM32MP_BL32_SIZE U(0)
-#define STM32MP_OPTEE_BASE STM32MP_SYSRAM_BASE
+#define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE
#define STM32MP_OPTEE_SIZE (STM32MP_DTB_BASE - \
STM32MP_OPTEE_BASE)
@@ -104,8 +117,8 @@
#endif
#endif
-#define STM32MP_BL32_BASE (STM32MP_SYSRAM_BASE + \
- STM32MP_SYSRAM_SIZE - \
+#define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_SEC_SYSRAM_SIZE - \
STM32MP_BL32_SIZE)
#ifdef AARCH32_SP_OPTEE
@@ -484,14 +497,16 @@
#define IWDG2_BASE U(0x5A002000)
/*******************************************************************************
- * STM32MP1 I2C4
+ * Miscellaneous STM32MP1 peripherals base address
******************************************************************************/
-#define I2C4_BASE U(0x5C002000)
-
-/*******************************************************************************
- * STM32MP1 DBGMCU
- ******************************************************************************/
+#define CRYP1_BASE U(0x54001000)
#define DBGMCU_BASE U(0x50081000)
+#define HASH1_BASE U(0x54002000)
+#define I2C4_BASE U(0x5C002000)
+#define I2C6_BASE U(0x5c009000)
+#define RNG1_BASE U(0x54003000)
+#define RTC_BASE U(0x5c004000)
+#define SPI6_BASE U(0x5c001000)
/*******************************************************************************
* Device Tree defines
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index cf9fa8e..31a9ae7 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -10,6 +10,7 @@
#include <platform_def.h>
#include <arch_helpers.h>
+#include <bl32/sp_min/platform_sp_min.h>
#include <common/debug.h>
#include <drivers/arm/gic_common.h>
#include <drivers/arm/gicv2.h>
@@ -68,9 +69,8 @@
return PSCI_E_INVALID_PARAMS;
}
- if ((stm32_sec_entrypoint < STM32MP_SYSRAM_BASE) ||
- (stm32_sec_entrypoint > (STM32MP_SYSRAM_BASE +
- (STM32MP_SYSRAM_SIZE - 1)))) {
+ /* Only one valid entry point */
+ if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) {
return PSCI_E_INVALID_ADDRESS;
}
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 779228d..fd60db2 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -30,12 +30,29 @@
BOARD_ID_REVISION_SHIFT)
#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK)
-#define MAP_SRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
+#if defined(IMAGE_BL2)
+#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
STM32MP_SYSRAM_SIZE, \
MT_MEMORY | \
MT_RW | \
MT_SECURE | \
MT_EXECUTE_NEVER)
+#elif defined(IMAGE_BL32)
+#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \
+ STM32MP_SEC_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */
+#define MAP_NS_SYSRAM MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \
+ STM32MP_NS_SYSRAM_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_NS | \
+ MT_EXECUTE_NEVER)
+#endif
#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
STM32MP1_DEVICE1_SIZE, \
@@ -53,7 +70,7 @@
#if defined(IMAGE_BL2)
static const mmap_region_t stm32mp1_mmap[] = {
- MAP_SRAM,
+ MAP_SEC_SYSRAM,
MAP_DEVICE1,
MAP_DEVICE2,
{0}
@@ -61,7 +78,8 @@
#endif
#if defined(IMAGE_BL32)
static const mmap_region_t stm32mp1_mmap[] = {
- MAP_SRAM,
+ MAP_SEC_SYSRAM,
+ MAP_NS_SYSRAM,
MAP_DEVICE1,
MAP_DEVICE2,
{0}
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/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..208e34a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+
+#include <stm32mp_shared_resources.h>
+
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+ SHRES_UNREGISTERED = 0,
+ SHRES_SECURE,
+ SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
+ [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+ [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+ [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+ [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+ [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+ [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+ [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+ [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+ [STM32MP1_SHRES_IWDG1] = "IWDG1",
+ [STM32MP1_SHRES_USART1] = "USART1",
+ [STM32MP1_SHRES_SPI6] = "SPI6",
+ [STM32MP1_SHRES_I2C4] = "I2C4",
+ [STM32MP1_SHRES_RNG1] = "RNG1",
+ [STM32MP1_SHRES_HASH1] = "HASH1",
+ [STM32MP1_SHRES_CRYP1] = "CRYP1",
+ [STM32MP1_SHRES_I2C6] = "I2C6",
+ [STM32MP1_SHRES_RTC] = "RTC",
+ [STM32MP1_SHRES_MCU] = "MCU",
+ [STM32MP1_SHRES_MDMA] = "MDMA",
+ [STM32MP1_SHRES_PLL3] = "PLL3",
+};
+
+static const char __unused *shres2str_id(enum stm32mp_shres id)
+{
+ assert(id < ARRAY_SIZE(shres2str_id_tbl));
+
+ return shres2str_id_tbl[id];
+}
+
+static const char __unused *shres2str_state_tbl[] = {
+ [SHRES_UNREGISTERED] = "unregistered",
+ [SHRES_NON_SECURE] = "non-secure",
+ [SHRES_SECURE] = "secure",
+};
+
+static const char __unused *shres2str_state(unsigned int state)
+{
+ assert(state < ARRAY_SIZE(shres2str_state_tbl));
+
+ return shres2str_state_tbl[state];
+}
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+ registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+ lock_registering();
+
+ return (shres_state[id] == SHRES_NON_SECURE) ||
+ (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+ return !periph_is_non_secure(id);
+}
+
+/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
+static int8_t gpioz_nbpin = -1;
+
+static unsigned int get_gpio_nbpin(unsigned int bank)
+{
+ if (bank != GPIO_BANK_Z) {
+ int count = fdt_get_gpio_bank_pin_count(bank);
+
+ assert((count >= 0) || (count <= (GPIO_PIN_MAX + 1)));
+
+ return (unsigned int)count;
+ }
+
+ if (gpioz_nbpin < 0) {
+ int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
+
+ assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
+
+ gpioz_nbpin = count;
+ }
+
+ return (unsigned int)gpioz_nbpin;
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+ return get_gpio_nbpin(GPIO_BANK_Z);
+}
+
+static void register_periph(enum stm32mp_shres id, unsigned int state)
+{
+ assert((id < STM32MP1_SHRES_COUNT) &&
+ ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
+
+ if (registering_locked) {
+ if (shres_state[id] == state) {
+ return;
+ }
+ panic();
+ }
+
+ if ((shres_state[id] != SHRES_UNREGISTERED) &&
+ (shres_state[id] != state)) {
+ VERBOSE("Cannot change %s from %s to %s\n",
+ shres2str_id(id),
+ shres2str_state(shres_state[id]),
+ shres2str_state(state));
+ panic();
+ }
+
+ if (shres_state[id] == SHRES_UNREGISTERED) {
+ VERBOSE("Register %s as %s\n",
+ shres2str_id(id), shres2str_state(state));
+ }
+
+ if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
+ (id <= STM32MP1_SHRES_GPIOZ(7)) &&
+ ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
+ ERROR("Invalid GPIO pin %u, %u pin(s) available\n",
+ id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin());
+ panic();
+ }
+
+ shres_state[id] = (uint8_t)state;
+
+ /* Explore clock tree to lock dependencies */
+ if (state == SHRES_SECURE) {
+ enum stm32mp_shres clock_res_id;
+
+ switch (id) {
+ case STM32MP1_SHRES_GPIOZ(0):
+ case STM32MP1_SHRES_GPIOZ(1):
+ case STM32MP1_SHRES_GPIOZ(2):
+ case STM32MP1_SHRES_GPIOZ(3):
+ case STM32MP1_SHRES_GPIOZ(4):
+ case STM32MP1_SHRES_GPIOZ(5):
+ case STM32MP1_SHRES_GPIOZ(6):
+ case STM32MP1_SHRES_GPIOZ(7):
+ clock_res_id = GPIOZ;
+ break;
+ case STM32MP1_SHRES_IWDG1:
+ clock_res_id = IWDG1;
+ break;
+ case STM32MP1_SHRES_USART1:
+ clock_res_id = USART1_K;
+ break;
+ case STM32MP1_SHRES_SPI6:
+ clock_res_id = SPI6_K;
+ break;
+ case STM32MP1_SHRES_I2C4:
+ clock_res_id = I2C4_K;
+ break;
+ case STM32MP1_SHRES_RNG1:
+ clock_res_id = RNG1_K;
+ break;
+ case STM32MP1_SHRES_HASH1:
+ clock_res_id = HASH1;
+ break;
+ case STM32MP1_SHRES_CRYP1:
+ clock_res_id = CRYP1;
+ break;
+ case STM32MP1_SHRES_I2C6:
+ clock_res_id = I2C6_K;
+ break;
+ case STM32MP1_SHRES_RTC:
+ clock_res_id = RTC;
+ break;
+ default:
+ /* No clock resource dependency */
+ return;
+ }
+
+ stm32mp1_register_clock_parents_secure(clock_res_id);
+ }
+}
+
+/* Register resource by ID */
+void stm32mp_register_secure_periph(enum stm32mp_shres id)
+{
+ register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
+{
+ register_periph(id, SHRES_NON_SECURE);
+}
+
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+ enum stm32mp_shres id;
+
+ switch (base) {
+ case CRYP1_BASE:
+ id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1_BASE:
+ id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_BASE:
+ id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_BASE:
+ id = STM32MP1_SHRES_I2C6;
+ break;
+ case IWDG1_BASE:
+ id = STM32MP1_SHRES_IWDG1;
+ break;
+ case RNG1_BASE:
+ id = STM32MP1_SHRES_RNG1;
+ break;
+ case RTC_BASE:
+ id = STM32MP1_SHRES_RTC;
+ break;
+ case SPI6_BASE:
+ id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_BASE:
+ id = STM32MP1_SHRES_USART1;
+ break;
+
+ case GPIOA_BASE:
+ case GPIOB_BASE:
+ case GPIOC_BASE:
+ case GPIOD_BASE:
+ case GPIOE_BASE:
+ case GPIOF_BASE:
+ case GPIOG_BASE:
+ case GPIOH_BASE:
+ case GPIOI_BASE:
+ case GPIOJ_BASE:
+ case GPIOK_BASE:
+ case USART2_BASE:
+ case USART3_BASE:
+ case UART4_BASE:
+ case UART5_BASE:
+ case USART6_BASE:
+ case UART7_BASE:
+ case UART8_BASE:
+ case IWDG2_BASE:
+ /* Allow drivers to register some non-secure resources */
+ VERBOSE("IO for non-secure resource 0x%x\n",
+ (unsigned int)base);
+ if (state != SHRES_NON_SECURE) {
+ panic();
+ }
+
+ return;
+
+ default:
+ panic();
+ }
+
+ register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+ break;
+ default:
+ ERROR("GPIO bank %u cannot be secured\n", bank);
+ panic();
+ }
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+ unsigned int non_secure = 0U;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return true;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ non_secure++;
+ }
+ }
+
+ return non_secure == get_gpioz_nbpin();
+}
+
+static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+ unsigned int secure = 0U;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return false;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ secure++;
+ }
+ }
+
+ return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+ switch (clock_id) {
+ case CK_CSI:
+ case CK_HSE:
+ case CK_HSE_DIV2:
+ case CK_HSI:
+ case CK_LSE:
+ case CK_LSI:
+ case PLL1_P:
+ case PLL1_Q:
+ case PLL1_R:
+ case PLL2_P:
+ case PLL2_Q:
+ case PLL2_R:
+ case PLL3_P:
+ case PLL3_Q:
+ case PLL3_R:
+ case RTCAPB:
+ return true;
+ case GPIOZ:
+ /* Allow clock access if at least one pin is non-secure */
+ return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
+ case CRYP1:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_K:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_K:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case IWDG1:
+ shres_id = STM32MP1_SHRES_IWDG1;
+ break;
+ case RNG1_K:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case RTC:
+ shres_id = STM32MP1_SHRES_RTC;
+ break;
+ case SPI6_K:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_K:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ default:
+ return false;
+ }
+
+ return periph_is_non_secure(shres_id);
+}
+
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
+{
+ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+ switch (reset_id) {
+ case CRYP1_R:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case GPIOZ_R:
+ /* GPIOZ reset mandates all pins are non-secure */
+ return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
+ case HASH1_R:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_R:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_R:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case MCU_R:
+ shres_id = STM32MP1_SHRES_MCU;
+ break;
+ case MDMA_R:
+ shres_id = STM32MP1_SHRES_MDMA;
+ break;
+ case RNG1_R:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case SPI6_R:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_R:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ default:
+ return false;
+ }
+
+ return periph_is_non_secure(shres_id);
+}
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+ switch (id) {
+ case STM32MP1_SHRES_MCU:
+ case STM32MP1_SHRES_PLL3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+ assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+ (id > STM32MP1_SHRES_GPIOZ(7)));
+
+ if (periph_is_non_secure(id)) {
+ return ETZPC_DECPROT_NS_RW;
+ }
+
+ return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+ /* Some system peripherals shall be secure */
+ etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+ etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+ etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+ ETZPC_DECPROT_NS_R_S_W);
+ etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+ ETZPC_DECPROT_NS_R_S_W);
+
+ /* Configure ETZPC with peripheral registering */
+ etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_HASH1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+ shres2decprot_attr(STM32MP1_SHRES_I2C4));
+ etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+ shres2decprot_attr(STM32MP1_SHRES_I2C6));
+ etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_RNG1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_USART1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+ shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+ uint32_t n;
+ uint32_t error = 0U;
+ bool mckprot = stm32mp1_rcc_is_mckprot();
+ bool secure = stm32mp1_rcc_is_secure();
+
+ for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+ if (shres_state[n] != SHRES_SECURE) {
+ continue;
+ }
+
+ if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+ ERROR("RCC %s MCKPROT %s and %s secure\n",
+ secure ? "secure" : "non-secure",
+ mckprot ? "set" : "not set",
+ shres2str_id(n));
+ error++;
+ }
+ }
+
+ if (error != 0U) {
+ panic();
+ }
+}
+
+static void set_gpio_secure_configuration(void)
+{
+ uint32_t pin;
+
+ for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+ bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+ set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+ }
+}
+
+static void print_shared_resources_state(void)
+{
+ unsigned int id;
+
+ for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+ switch (shres_state[id]) {
+ case SHRES_SECURE:
+ INFO("stm32mp1 %s is secure\n", shres2str_id(id));
+ break;
+ case SHRES_NON_SECURE:
+ case SHRES_UNREGISTERED:
+ VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
+ break;
+ default:
+ VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
+ panic();
+ }
+ }
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+ registering_locked = true;
+
+ print_shared_resources_state();
+
+ check_rcc_secure_configuration();
+ set_etzpc_secure_configuration();
+ set_gpio_secure_configuration();
+}
diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk
index 65d5cc2..2de21aa 100644
--- a/plat/ti/k3/platform.mk
+++ b/plat/ti/k3/platform.mk
@@ -11,4 +11,4 @@
include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
# modify BUILD_PLAT to point to board specific build directory
-BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
+BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
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)
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index a818037..4c2b58d 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -350,6 +350,7 @@
spmd_spm_core_context_t *ctx = spmd_get_context();
bool secure_origin;
int32_t ret;
+ uint32_t input_version;
/* Determine which security state this SMC originated from */
secure_origin = is_caller_secure(flags);
@@ -375,15 +376,24 @@
break; /* not reached */
case FFA_VERSION:
+ input_version = (uint32_t)(0xFFFFFFFF & x1);
/*
- * TODO: This is an optimization that the version information
- * provided by the SPM Core manifest is returned by the SPM
- * dispatcher. It might be a better idea to simply forward this
- * call to the SPM Core and wash our hands completely.
+ * If caller is secure and SPMC was initialized,
+ * return FFA_VERSION of SPMD.
+ * If caller is non secure and SPMC was initialized,
+ * return SPMC's version.
+ * Sanity check to "input_version".
*/
- ret = MAKE_FFA_VERSION(spmc_attrs.major_version,
- spmc_attrs.minor_version);
- SMC_RET8(handle, FFA_SUCCESS_SMC32, FFA_TARGET_INFO_MBZ, ret,
+ if ((input_version & FFA_VERSION_BIT31_MASK) ||
+ (ctx->state == SPMC_STATE_RESET)) {
+ ret = FFA_ERROR_NOT_SUPPORTED;
+ } else if (!secure_origin) {
+ ret = MAKE_FFA_VERSION(spmc_attrs.major_version, spmc_attrs.minor_version);
+ } else {
+ ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR);
+ }
+
+ SMC_RET8(handle, ret, FFA_TARGET_INFO_MBZ, FFA_TARGET_INFO_MBZ,
FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
FFA_PARAM_MBZ, FFA_PARAM_MBZ);
break; /* not reached */
diff --git a/tools/cert_create/include/dualroot/cot.h b/tools/cert_create/include/dualroot/cot.h
index 47e371f..1d959d4 100644
--- a/tools/cert_create/include/dualroot/cot.h
+++ b/tools/cert_create/include/dualroot/cot.h
@@ -32,6 +32,7 @@
TRUSTED_BOOT_FW_HASH_EXT,
TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
HW_CONFIG_HASH_EXT,
+ FW_CONFIG_HASH_EXT,
TRUSTED_WORLD_PK_EXT,
SCP_FW_CONTENT_CERT_PK_EXT,
SCP_FW_HASH_EXT,
diff --git a/tools/cert_create/include/tbbr/tbb_ext.h b/tools/cert_create/include/tbbr/tbb_ext.h
index 7ac97a5..692b2d4 100644
--- a/tools/cert_create/include/tbbr/tbb_ext.h
+++ b/tools/cert_create/include/tbbr/tbb_ext.h
@@ -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
*/
@@ -15,6 +15,7 @@
TRUSTED_BOOT_FW_HASH_EXT,
TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
HW_CONFIG_HASH_EXT,
+ FW_CONFIG_HASH_EXT,
TRUSTED_WORLD_PK_EXT,
NON_TRUSTED_WORLD_PK_EXT,
SCP_FW_CONTENT_CERT_PK_EXT,
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
index 2965828..a12ea21 100644
--- a/tools/cert_create/src/dualroot/cot.c
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -30,9 +30,10 @@
TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_BOOT_FW_HASH_EXT,
TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
- HW_CONFIG_HASH_EXT
+ HW_CONFIG_HASH_EXT,
+ FW_CONFIG_HASH_EXT
},
- .num_ext = 4
+ .num_ext = 5
},
[TRUSTED_KEY_CERT] = {
@@ -239,6 +240,17 @@
.optional = 1
},
+ [FW_CONFIG_HASH_EXT] = {
+ .oid = FW_CONFIG_HASH_OID,
+ .opt = "fw-config",
+ .help_msg = "Firmware Config file",
+ .sn = "FirmwareConfigHash",
+ .ln = "Firmware Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
+
[TRUSTED_WORLD_PK_EXT] = {
.oid = TRUSTED_WORLD_PK_OID,
.sn = "TrustedWorldPublicKey",
diff --git a/tools/cert_create/src/tbbr/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
index b614e2e..f4fe63d 100644
--- a/tools/cert_create/src/tbbr/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.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
*/
@@ -28,9 +28,10 @@
TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_BOOT_FW_HASH_EXT,
TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
- HW_CONFIG_HASH_EXT
+ HW_CONFIG_HASH_EXT,
+ FW_CONFIG_HASH_EXT
},
- .num_ext = 4
+ .num_ext = 5
},
[TRUSTED_KEY_CERT] = {
.id = TRUSTED_KEY_CERT,
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index 0068d3b..60bafb4 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.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
*/
@@ -69,6 +69,16 @@
.type = EXT_TYPE_HASH,
.optional = 1
},
+ [FW_CONFIG_HASH_EXT] = {
+ .oid = FW_CONFIG_HASH_OID,
+ .opt = "fw-config",
+ .help_msg = "Firmware Config file",
+ .sn = "FirmwareConfigHash",
+ .ln = "Firmware Config hash",
+ .asn1_type = V_ASN1_OCTET_STRING,
+ .type = EXT_TYPE_HASH,
+ .optional = 1
+ },
[TRUSTED_WORLD_PK_EXT] = {
.oid = TRUSTED_WORLD_PK_OID,
.sn = "TrustedWorldPublicKey",
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 80b498e..8c5b04a 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -24,17 +24,17 @@
#define OPT_ALIGN 2
static int info_cmd(int argc, char *argv[]);
-static void info_usage(void);
+static void info_usage(int);
static int create_cmd(int argc, char *argv[]);
-static void create_usage(void);
+static void create_usage(int);
static int update_cmd(int argc, char *argv[]);
-static void update_usage(void);
+static void update_usage(int);
static int unpack_cmd(int argc, char *argv[]);
-static void unpack_usage(void);
+static void unpack_usage(int);
static int remove_cmd(int argc, char *argv[]);
-static void remove_usage(void);
+static void remove_usage(int);
static int version_cmd(int argc, char *argv[]);
-static void version_usage(void);
+static void version_usage(int);
static int help_cmd(int argc, char *argv[]);
static void usage(void);
@@ -448,7 +448,7 @@
fip_toc_header_t toc_header;
if (argc != 2)
- info_usage();
+ info_usage(EXIT_FAILURE);
argc--, argv++;
parse_fip(argv[0], &toc_header);
@@ -487,10 +487,10 @@
return 0;
}
-static void info_usage(void)
+static void info_usage(int exit_status)
{
printf("fiptool info FIP_FILENAME\n");
- exit(1);
+ exit(exit_status);
}
static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align)
@@ -669,7 +669,7 @@
unsigned long align = 1;
if (argc < 2)
- create_usage();
+ create_usage(EXIT_FAILURE);
opts = fill_common_opts(opts, &nr_opts, required_argument);
opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument,
@@ -710,7 +710,7 @@
if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
filename[0] == '\0')
- create_usage();
+ create_usage(EXIT_FAILURE);
desc = lookup_image_desc_from_uuid(&uuid);
if (desc == NULL) {
@@ -722,7 +722,7 @@
break;
}
default:
- create_usage();
+ create_usage(EXIT_FAILURE);
}
}
argc -= optind;
@@ -730,7 +730,7 @@
free(opts);
if (argc == 0)
- create_usage();
+ create_usage(EXIT_SUCCESS);
update_fip();
@@ -738,7 +738,7 @@
return 0;
}
-static void create_usage(void)
+static void create_usage(int exit_status)
{
toc_entry_t *toc_entry = toc_entries;
@@ -753,7 +753,7 @@
for (; toc_entry->cmdline_name != NULL; toc_entry++)
printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
toc_entry->name);
- exit(1);
+ exit(exit_status);
}
static int update_cmd(int argc, char *argv[])
@@ -767,7 +767,7 @@
int pflag = 0;
if (argc < 2)
- update_usage();
+ update_usage(EXIT_FAILURE);
opts = fill_common_opts(opts, &nr_opts, required_argument);
opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -807,7 +807,7 @@
if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
filename[0] == '\0')
- update_usage();
+ update_usage(EXIT_FAILURE);
desc = lookup_image_desc_from_uuid(&uuid);
if (desc == NULL) {
@@ -825,7 +825,7 @@
snprintf(outfile, sizeof(outfile), "%s", optarg);
break;
default:
- update_usage();
+ update_usage(EXIT_FAILURE);
}
}
argc -= optind;
@@ -833,7 +833,7 @@
free(opts);
if (argc == 0)
- update_usage();
+ update_usage(EXIT_SUCCESS);
if (outfile[0] == '\0')
snprintf(outfile, sizeof(outfile), "%s", argv[0]);
@@ -851,7 +851,7 @@
return 0;
}
-static void update_usage(void)
+static void update_usage(int exit_status)
{
toc_entry_t *toc_entry = toc_entries;
@@ -867,7 +867,7 @@
for (; toc_entry->cmdline_name != NULL; toc_entry++)
printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
toc_entry->name);
- exit(1);
+ exit(exit_status);
}
static int unpack_cmd(int argc, char *argv[])
@@ -880,7 +880,7 @@
int unpack_all = 1;
if (argc < 2)
- unpack_usage();
+ unpack_usage(EXIT_FAILURE);
opts = fill_common_opts(opts, &nr_opts, required_argument);
opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b');
@@ -915,7 +915,7 @@
if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
filename[0] == '\0')
- unpack_usage();
+ unpack_usage(EXIT_FAILURE);
desc = lookup_image_desc_from_uuid(&uuid);
if (desc == NULL) {
@@ -934,7 +934,7 @@
snprintf(outdir, sizeof(outdir), "%s", optarg);
break;
default:
- unpack_usage();
+ unpack_usage(EXIT_FAILURE);
}
}
argc -= optind;
@@ -942,7 +942,7 @@
free(opts);
if (argc == 0)
- unpack_usage();
+ unpack_usage(EXIT_SUCCESS);
parse_fip(argv[0], NULL);
@@ -986,7 +986,7 @@
return 0;
}
-static void unpack_usage(void)
+static void unpack_usage(int exit_status)
{
toc_entry_t *toc_entry = toc_entries;
@@ -1003,7 +1003,7 @@
toc_entry->name);
printf("\n");
printf("If no options are provided, all images will be unpacked.\n");
- exit(1);
+ exit(exit_status);
}
static int remove_cmd(int argc, char *argv[])
@@ -1017,7 +1017,7 @@
int fflag = 0;
if (argc < 2)
- remove_usage();
+ remove_usage(EXIT_FAILURE);
opts = fill_common_opts(opts, &nr_opts, no_argument);
opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -1053,7 +1053,7 @@
filename, sizeof(filename));
if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0)
- remove_usage();
+ remove_usage(EXIT_FAILURE);
desc = lookup_image_desc_from_uuid(&uuid);
if (desc == NULL) {
@@ -1071,7 +1071,7 @@
snprintf(outfile, sizeof(outfile), "%s", optarg);
break;
default:
- remove_usage();
+ remove_usage(EXIT_FAILURE);
}
}
argc -= optind;
@@ -1079,7 +1079,7 @@
free(opts);
if (argc == 0)
- remove_usage();
+ remove_usage(EXIT_SUCCESS);
if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag)
log_errx("File %s already exists, use --force to overwrite it",
@@ -1110,7 +1110,7 @@
return 0;
}
-static void remove_usage(void)
+static void remove_usage(int exit_status)
{
toc_entry_t *toc_entry = toc_entries;
@@ -1126,7 +1126,7 @@
for (; toc_entry->cmdline_name != NULL; toc_entry++)
printf(" --%-16s\t%s\n", toc_entry->cmdline_name,
toc_entry->name);
- exit(1);
+ exit(exit_status);
}
static int version_cmd(int argc, char *argv[])
@@ -1140,10 +1140,10 @@
return 0;
}
-static void version_usage(void)
+static void version_usage(int exit_status)
{
printf("fiptool version\n");
- exit(1);
+ exit(exit_status);
}
static int help_cmd(int argc, char *argv[])
@@ -1157,7 +1157,7 @@
for (i = 0; i < NELEM(cmds); i++) {
if (strcmp(cmds[i].name, argv[0]) == 0 &&
cmds[i].usage != NULL)
- cmds[i].usage();
+ cmds[i].usage(EXIT_SUCCESS);
}
if (i == NELEM(cmds))
printf("No help for subcommand '%s'\n", argv[0]);
@@ -1178,7 +1178,7 @@
printf(" remove\tRemove images from FIP.\n");
printf(" version\tShow fiptool version.\n");
printf(" help\t\tShow help for given command.\n");
- exit(1);
+ exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h
index af3fcbd..88c4a7e 100644
--- a/tools/fiptool/fiptool.h
+++ b/tools/fiptool/fiptool.h
@@ -48,7 +48,7 @@
typedef struct cmd {
char *name;
int (*handler)(int, char **);
- void (*usage)(void);
+ void (*usage)(int);
} cmd_t;
#endif /* FIPTOOL_H */
diff --git a/tools/fiptool/tbbr_config.c b/tools/fiptool/tbbr_config.c
index 1c5ef5f..bf721c1 100644
--- a/tools/fiptool/tbbr_config.c
+++ b/tools/fiptool/tbbr_config.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -69,6 +69,11 @@
},
/* Dynamic Configs */
{
+ .name = "FW_CONFIG",
+ .uuid = UUID_FW_CONFIG,
+ .cmdline_name = "fw-config"
+ },
+ {
.name = "HW_CONFIG",
.uuid = UUID_HW_CONFIG,
.cmdline_name = "hw-config"
diff --git a/tools/marvell/doimage/doimage.c b/tools/marvell/doimage/doimage.c
index 82fd375..e08b820 100644
--- a/tools/marvell/doimage/doimage.c
+++ b/tools/marvell/doimage/doimage.c
@@ -51,7 +51,7 @@
/* Number of address pairs in control array */
#define CP_CTRL_EL_ARRAY_SZ 32
-#define VERSION_STRING "Marvell(C) doimage utility version 3.2"
+#define VERSION_STRING "Marvell(C) doimage utility version 3.3"
/* A8K definitions */
@@ -303,7 +303,7 @@
MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
/* First compute the SHA256 hash for the input blob */
- mbedtls_sha256(input, ilen, hash, 0);
+ mbedtls_sha256_ret(input, ilen, hash, 0);
/* Then calculate the hash signature */
rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx),
@@ -354,6 +354,7 @@
mbedtls_pk_context pk_ctx;
unsigned char hash[32];
int rval;
+ unsigned char *pkey = (unsigned char *)pub_key;
/* Not sure this is required,
* but it's safer to start with empty buffer
@@ -373,8 +374,7 @@
}
/* Check ability to read the public key */
- rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key,
- MAX_RSA_DER_BYTE_LEN);
+ rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx);
if (rval != 0) {
fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n",
rval);
@@ -387,7 +387,7 @@
MBEDTLS_MD_SHA256);
/* Compute the SHA256 hash for the input buffer */
- mbedtls_sha256(input, ilen, hash, 0);
+ mbedtls_sha256_ret(input, ilen, hash, 0);
rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx),
mbedtls_ctr_drbg_random,
@@ -458,7 +458,7 @@
/* compute SHA-256 digest of the results
* and use it as the init vector (IV)
*/
- mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0);
+ mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0);
memcpy(IV, digest, AES_BLOCK_SZ);
mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key,
AES_KEY_BIT_LEN);
@@ -880,11 +880,13 @@
fname);
return 1;
}
+
/* Data in the output buffer is aligned to the buffer end */
der_buf_start = output_buf + sizeof(output_buf) - output_len;
/* In the header DER data is aligned
* to the start of appropriate field
*/
+ bzero(out_der_key, MAX_RSA_DER_BYTE_LEN);
memcpy(out_der_key, der_buf_start, output_len);
} /* for every private key file */
@@ -899,8 +901,10 @@
fprintf(stderr, "Failed to sign CSK keys block!\n");
return 1;
}
+
/* Check that everything is correct */
- if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN,
+ if (verify_rsa_signature(sec_ext.kak_key,
+ MAX_RSA_DER_BYTE_LEN,
&sec_ext.csk_keys[0][0],
sizeof(sec_ext.csk_keys),
opts.sec_opts->kak_key_file,
@@ -1333,7 +1337,7 @@
goto error;
}
- mbedtls_sha256(sec_entry->kak_key,
+ mbedtls_sha256_ret(sec_entry->kak_key,
MAX_RSA_DER_BYTE_LEN, hash, 0);
fprintf(stdout,
">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n");
@@ -1559,13 +1563,9 @@
int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd)
{
- int aligned_size;
int written;
- /* Image size must be aligned to 4 bytes */
- aligned_size = (image_size + 3) & (~0x3);
-
- written = fwrite(buf, aligned_size, 1, out_fd);
+ written = fwrite(buf, image_size, 1, out_fd);
if (written != 1) {
fprintf(stderr, "Error: Failed to write boot image\n");
goto error;
@@ -1587,7 +1587,7 @@
int ext_cnt = 0;
int opt;
int ret = 0;
- int image_size;
+ int image_size, file_size;
uint8_t *image_buf = NULL;
int read;
size_t len;
@@ -1683,16 +1683,18 @@
goto main_exit;
}
- /* Read the input file to buffer */
- image_size = get_file_size(in_file);
- image_buf = calloc((image_size + AES_BLOCK_SZ - 1) &
- ~(AES_BLOCK_SZ - 1), 1);
+ /* Read the input file to buffer
+ * Always align the image to 16 byte boundary
+ */
+ file_size = get_file_size(in_file);
+ image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1);
+ image_buf = calloc(image_size, 1);
if (image_buf == NULL) {
fprintf(stderr, "Error: failed allocating input buffer\n");
return 1;
}
- read = fread(image_buf, image_size, 1, in_fd);
+ read = fread(image_buf, file_size, 1, in_fd);
if (read != 1) {
fprintf(stderr, "Error: failed to read input file\n");
goto main_exit;
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index f2387f6..2153a56 100755
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -55,8 +55,8 @@
data = json.load(in_file)
json_file = os.path.abspath(sys.argv[2])
json_dir = os.path.dirname(json_file)
-gen_file = sys.argv[1]
-out_dir = sys.argv[3][2:]
+gen_file = os.path.abspath(sys.argv[1])
+out_dir = os.path.abspath(sys.argv[3])
dtb_dir = out_dir + "/fdts/"
print(dtb_dir)