Merge changes from topic "romlib-fixes" into integration
* changes:
fix(romlib): wrap indirectly included functions
fix(arm): remove duplicate jumptable entry
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 7b6a1f5..2d1afab 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023, Arm Limited. All rights reserved
+# Copyright (c) 2023-2024, Arm Limited. All rights reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -19,9 +19,8 @@
jobs:
post_create_environment:
- pip install poetry=="1.3.2"
- - poetry config virtualenvs.create false
post_install:
- - poetry install --with doc
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs
sphinx:
configuration: docs/conf.py
diff --git a/Makefile b/Makefile
index cb5eb36..2fc856a 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,7 @@
MAKE_HELPERS_DIRECTORY := make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}build-rules.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
################################################################################
@@ -120,6 +121,9 @@
SP_MK_GEN ?= ${SPTOOLPATH}/sp_mk_generator.py
SP_DTS_LIST_FRAGMENT ?= ${BUILD_PLAT}/sp_list_fragment.dts
+# Variables for use with Certificate Conversion (cot-dt2c) Tool
+CERTCONVPATH ?= tools/cot_dt2c
+
# Variables for use with ROMLIB
ROMLIBPATH ?= lib/romlib
@@ -690,8 +694,6 @@
FFH_SUPPORT := 0
endif
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
-
ifeq (${ARM_ARCH_MAJOR},7)
include make_helpers/armv7-a-cpus.mk
endif
@@ -1231,6 +1233,7 @@
ENABLE_FEAT_DIT \
ENABLE_FEAT_ECV \
ENABLE_FEAT_FGT \
+ ENABLE_FEAT_FGT2 \
ENABLE_FEAT_HCX \
ENABLE_FEAT_MTE2 \
ENABLE_FEAT_PAN \
@@ -1383,6 +1386,7 @@
ENABLE_MPMM \
ENABLE_MPMM_FCONF \
ENABLE_FEAT_FGT \
+ ENABLE_FEAT_FGT2 \
ENABLE_FEAT_ECV \
ENABLE_FEAT_AMUv1p1 \
ENABLE_FEAT_SEL2 \
@@ -1478,7 +1482,6 @@
endif
endif #(!ERROR_DEPRECATED)
-$(eval $(call MAKE_LIB_DIRS))
$(eval $(call MAKE_LIB,c))
# Expand build macros for the different images
@@ -1562,7 +1565,7 @@
# Add Secure Partition packages
ifeq (${NEED_SP_PKG},yes)
-$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | ${BUILD_PLAT}
+$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | $$(@D)/
$(q)${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT) ${COT} ${SP_DTS_LIST_FRAGMENT}
sp: $(DTBS) $(BUILD_PLAT)/sp_gen.mk $(SP_PKGS)
$(s)echo
@@ -1582,6 +1585,7 @@
clean:
$(s)echo " CLEAN"
$(call SHELL_REMOVE_DIR,${BUILD_PLAT})
+ $(q)${MAKE} -C ${CERTCONVPATH} clean
ifdef UNIX_MK
$(q)${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
else
@@ -1597,6 +1601,7 @@
$(s)echo " REALCLEAN"
$(call SHELL_REMOVE_DIR,${BUILD_BASE})
$(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*)
+ $(q)${MAKE} -C ${CERTCONVPATH} clean
ifdef UNIX_MK
$(q)${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
else
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 03b8bf8..7e9fde3 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -105,6 +105,10 @@
BL31_SOURCES += ${AMU_SOURCES}
endif
+ifneq (${ENABLE_FEAT_FGT2},0)
+BL31_SOURCES += lib/extensions/fgt/fgt2.c
+endif
+
ifeq (${ENABLE_MPMM},1)
BL31_SOURCES += ${MPMM_SOURCES}
endif
diff --git a/changelog.yaml b/changelog.yaml
index e4a6883..2b760c7 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -104,6 +104,9 @@
- title: Extended Translation Control Register (FEAT_TCR2).
scope: tcr2
+ - title: Fine-grained Traps 2 (FEAT_FGT2).
+ scope: fgt2
+
- title: CPU feature / ID register handling in general
scope: cpufeat
@@ -1441,6 +1444,9 @@
- title: R/ZG Layout Tool
scope: rzg-layout
+ - title: Transfer List Compiler
+ scope: tlc
+
- title: Dependencies
scope: deps
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 823beb1..9b9f7b4 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -334,7 +334,8 @@
/* v8.6 features */
check_feature(ENABLE_FEAT_AMUv1p1, read_feat_amu_id_field(),
"AMUv1p1", 2, 2);
- check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT", 1, 1);
+ check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT", 1, 2);
+ check_feature(ENABLE_FEAT_FGT2, read_feat_fgt_id_field(), "FGT2", 2, 2);
check_feature(ENABLE_FEAT_ECV, read_feat_ecv_id_field(), "ECV", 1, 2);
check_feature(ENABLE_FEAT_TWED, read_feat_twed_id_field(),
"TWED", 1, 1);
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index cbed72f..8ac09ae 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -565,8 +565,8 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
:|G|: `abdellatif-elkhlifi`_
-:|M|: Xueliang Zhong <xueliang.zhong@arm.com>
-:|G|: `xueliang-zhong-arm`_
+:|M|: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
+:|G|: `hugues-kambampiana-arm`_
:|F|: plat/arm/board/corstone700
:|F|: plat/arm/board/a5ds
:|F|: plat/arm/board/corstone1000
@@ -1050,6 +1050,7 @@
.. _harrisonmutai-arm: https://github.com/harrisonmutai-arm
.. _hilamirandakuzi1: https://github.com/hilamirandakuzi1
.. _hzhuang1: https://github.com/hzhuang1
+.. _hugues-kambampiana-arm: https://github.com/hugueskamba
.. _JackyBai: https://github.com/JackyBai
.. _J-Alves: https://github.com/J-Alves
.. _jason-ch-chen: https://github.com/jason-ch-chen
@@ -1112,7 +1113,6 @@
.. _vijayenthiran-arm: https://github.com/vijayenthiran-arm
.. _vishnu-banavath: https://github.com/vishnu-banavath
.. _vwadekar: https://github.com/vwadekar
-.. _xueliang-zhong-arm: https://github.com/xueliang-zhong-arm
.. _Yann-lms: https://github.com/Yann-lms
--------------
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
index 702bb56..1d31e3d 100644
--- a/docs/components/cot-binding.rst
+++ b/docs/components/cot-binding.rst
@@ -138,7 +138,7 @@
trusted-key-cert: trusted-key-cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted-world-pk: trusted-world-pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -152,7 +152,7 @@
image-id = <SCP_FW_KEY_CERT_ID>;
parent = <&trusted-key-cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_content_pk: scp_fw_content_pk {
oid = SCP_FW_CONTENT_CERT_PK_OID;
@@ -312,13 +312,13 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted-nv-counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
reg = <TFW_NVCTR_BASE>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
reg = <NTFW_CTR_BASE>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index ee322ac..29b89b2 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -1,5 +1,5 @@
FF-A manifest binding to device tree
-========================================
+====================================
This document defines the nodes and properties used to define a partition,
according to the FF-A specification.
@@ -82,7 +82,7 @@
the partition. Absence of this field indicates that the entry point is at
offset 0x0 from the base of the partition's binary.
-- xlat-granule [mandatory]
+- xlat-granule
- value type: <u32>
- Translation granule used with the partition:
@@ -91,10 +91,10 @@
- 0x2: 64k
- boot-order
- - value type: <u16>
+ - value type: <u32>
- A unique number amongst all partitions that specifies if this partition
must be booted before others. The partition with the smaller number will be
- booted first.
+ booted first. Highest vlue allowed for this field is 0xFFFF.
- rx-tx-buffer
- value type: "memory-regions" node
@@ -103,13 +103,15 @@
The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer".
- messaging-method [mandatory]
- - value type: <u8>
+ - value type: <u32>
- Specifies which messaging methods are supported by the partition, set bit
means the feature is supported, clear bit - not supported:
- - Bit[0]: partition can receive direct requests if set
- - Bit[1]: partition can send direct requests if set
+ - Bit[0]: partition can receive direct requests via FFA_MSG_SEND_DIRECT_REQ ABI if set
+ - Bit[1]: partition can send direct requests via FFA_MSG_SEND_DIRECT_REQ ABI if set
- Bit[2]: partition can send and receive indirect messages
+ - Bit[9]: partition can receive direct requests via FFA_MSG_SEND_DIRECT_REQ2 ABI if set
+ - Bit[10]: partition can send direct requests via FFA_MSG_SEND_DIRECT_REQ2 ABI if set
- managed-exit
- value type: <empty>
@@ -117,6 +119,11 @@
- This field is deprecated in favor of ns-interrupts-action field in the FF-A
v1.1 EAC0 spec.
+- managed-exit-virq
+ - value type: <empty>
+ - Indicates if the partition needs managed exit, if supported, to be signaled
+ through vFIQ signal.
+
- ns-interrupts-action [mandatory]
- value type: <u32>
- Specifies the action that the SPMC must take in response to a Non-secure
@@ -136,6 +143,12 @@
- 0x0: Other-Secure interrupt is queued
- 0x1: Other-Secure interrupt is signaled
+- runtime-model
+ - value type: <u32>
+ - Indicates whether the SP execution can be preempted.
+ - This field is deprecated in favor of other-s-interrupts-action and
+ ns-interrupts-action fields in the FF-A v1.1 spec.
+
- has-primary-scheduler
- value type: <empty>
- Presence of this field indicates that the partition implements the primary
@@ -157,11 +170,6 @@
the FF-A boot information blob to be passed in the specified general purpose
register.
-- stream-endpoint-ids
- - value type: <prop-encoded-array>
- - List of <u32> tuples, identifying the IDs this partition is acting as
- proxy for.
-
- power-management-messages
- value type: <u32>
- Specifies which power management messages a partition subscribes to.
@@ -172,6 +180,17 @@
- Bit[1]: CPU_SUSPEND
- Bit[2]: CPU_SUSPEND_RESUME
+- vm-availability-messages
+ - value type: <u32>
+ - Specifies which VM availability messages a partition subscribes to. A set
+ bit means the partition should be informed of the event, clear bit - should
+ not be informed of event:
+
+ - Bit[0]: VM created
+ - Bit[1]: VM destroyed
+
+.. _memory_region_node:
+
Memory Regions
--------------
@@ -209,6 +228,25 @@
then communicate the region properties (including the base address chosen
by the partition manager) to the partition.
+- stream-ids
+ - value type: <prop-encoded-array>
+ - List of IDs belonging to a DMA capable peripheral device that has access to
+ the memory region represented by current node.
+ - Each ID must have been declared in exactly one device region node.
+
+- smmu-id
+ - value type: <u32>
+ - Identifies the SMMU IP that enforces the access control for the DMA device
+ that owns the above stream-ids.
+
+- stream-ids-access-permissions
+ - value type: <prop-encoded-array>
+ - List of attributes representing the instruction and data access permissions
+ used by the DMA device streams to access the memory region represented by
+ current node.
+
+.. _device_region_node:
+
Device Regions
--------------
@@ -251,11 +289,10 @@
- stream-ids
- value type: <prop-encoded-array>
- - A list of (id, mem-manage) pair, where:
+ - List of IDs where an ID is a unique <u32> value amongst all devices assigned
+ to the partition.
- - id: A unique <u32> value amongst all devices assigned to the partition.
-
-- interrupts [mandatory]
+- interrupts
- value type: <prop-encoded-array>
- A list of (id, attributes) pair describing the device interrupts, where:
@@ -306,4 +343,4 @@
--------------
-*Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index b6f4219..220c3ce 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -10,42 +10,12 @@
========
+--------+--------------------------------------+
-| CoT | Chain of Trust |
-+--------+--------------------------------------+
-| DMA | Direct Memory Access |
-+--------+--------------------------------------+
-| DTB | Device Tree Blob |
-+--------+--------------------------------------+
| DTS | Device Tree Source |
+--------+--------------------------------------+
-| EC | Execution Context |
-+--------+--------------------------------------+
-| FIP | Firmware Image Package |
-+--------+--------------------------------------+
| FF-A | Firmware Framework for Arm A-profile |
+--------+--------------------------------------+
-| IPA | Intermediate Physical Address |
-+--------+--------------------------------------+
-| JOP | Jump-Oriented Programming |
-+--------+--------------------------------------+
| NWd | Normal World |
+--------+--------------------------------------+
-| ODM | Original Design Manufacturer |
-+--------+--------------------------------------+
-| OEM | Original Equipment Manufacturer |
-+--------+--------------------------------------+
-| PA | Physical Address |
-+--------+--------------------------------------+
-| PE | Processing Element |
-+--------+--------------------------------------+
-| PM | Power Management |
-+--------+--------------------------------------+
-| PVM | Primary VM |
-+--------+--------------------------------------+
-| ROP | Return-Oriented Programming |
-+--------+--------------------------------------+
-| SMMU | System Memory Management Unit |
-+--------+--------------------------------------+
| SP | Secure Partition |
+--------+--------------------------------------+
| SPD | Secure Payload Dispatcher |
@@ -56,16 +26,8 @@
+--------+--------------------------------------+
| SPMD | SPM Dispatcher |
+--------+--------------------------------------+
-| SiP | Silicon Provider |
-+--------+--------------------------------------+
| SWd | Secure World |
+--------+--------------------------------------+
-| TLV | Tag-Length-Value |
-+--------+--------------------------------------+
-| TOS | Trusted Operating System |
-+--------+--------------------------------------+
-| VM | Virtual Machine |
-+--------+--------------------------------------+
Foreword
========
@@ -74,34 +36,14 @@
codebase:
#. S-EL2 SPMC based on the FF-A specification `[1]`_, enabling virtualization in
- the secure world, managing multiple S-EL1 or S-EL0 partitions.
+ the secure world, managing multiple S-EL1 or S-EL0 partitions `[5]`_.
#. EL3 SPMC based on the FF-A specification, managing a single S-EL1 partition
- without virtualization in the secure world.
+ without virtualization in the secure world `[6]`_.
#. EL3 SPM based on the MM specification, legacy implementation managing a
single S-EL0 partition `[2]`_.
These implementations differ in their respective SW architecture and only one
-can be selected at build time. This document:
-
-- describes the implementation from bullet 1. when the SPMC resides at S-EL2.
-- 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/SPMC secure firmware on platforms
- implementing the FEAT_SEL2 architecture extension.
-
-Terminology
------------
-
-- The term Hypervisor refers to the NS-EL2 component managing Virtual Machines
- (or partitions) in the normal world.
-- The term SPMC refers to the S-EL2 component managing secure partitions in
- the secure world when the FEAT_SEL2 architecture extension is implemented.
-- Alternatively, SPMC can refer to an S-EL1 component, itself being a secure
- partition and implementing the FF-A ABI on platforms not implementing the
- FEAT_SEL2 architecture extension.
-- The term VM refers to a normal world Virtual Machine managed by an Hypervisor.
-- The term SP refers to a secure world "Virtual Machine" managed by an SPMC.
+can be selected at build time.
Support for legacy platforms
----------------------------
@@ -123,16 +65,6 @@
- S-EL2 SPMC for platforms implementing the FEAT_SEL2 architecture
extension. The SPMD relays the FF-A protocol from EL3 to S-EL2.
-Sample reference stack
-======================
-
-The following diagram illustrates a possible configuration when the
-FEAT_SEL2 architecture extension is implemented, showing the SPMD
-and SPMC, one or multiple secure partitions, with an optional
-Hypervisor:
-
-.. image:: ../resources/diagrams/ff-a-spm-sel2.png
-
TF-A build options
==================
@@ -147,16 +79,15 @@
level to being at S-EL2. It defaults to enabled (value 1) when
SPD=spmd is chosen.
- **SPMC_AT_EL3**: this option adjusts the SPMC exception level to being
- at EL3.
-- If neither ``SPMD_SPM_AT_SEL2`` or ``SPMC_AT_EL3`` are enabled the SPMC
- exception level is set to S-EL1.
+ at EL3. If neither ``SPMD_SPM_AT_SEL2`` or ``SPMC_AT_EL3`` are enabled the
+ SPMC exception level is set to S-EL1.
``SPMD_SPM_AT_SEL2`` is enabled. The context save/restore routine
and exhaustive list of registers is visible at `[4]`_.
- **SPMC_AT_EL3_SEL0_SP**: this option enables the support to load SEL0 SP
when SPMC at EL3 support is enabled.
- **SP_LAYOUT_FILE**: this option specifies a text description file
providing paths to SP binary images and manifests in DTS format
- (see `Describing secure partitions`_). It
+ (see `[3]`_). It
is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
secure partitions are to be loaded by BL2 on behalf of the SPMC.
@@ -275,1358 +206,28 @@
PLAT=fvp \
all fip
-FVP model invocation
-====================
-
-The FVP command line needs the following options to exercise the S-EL2 SPMC:
-
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_arm_v8-5=1 | Implements FEAT_SEL2, FEAT_PAuth, |
-| - cluster1.has_arm_v8-5=1 | and FEAT_BTI. |
-+---------------------------------------------------+------------------------------------+
-| - pci.pci_smmuv3.mmu.SMMU_AIDR=2 | Parameters required for the |
-| - pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B | SMMUv3.2 modeling. |
-| - pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 | |
-| - pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 | |
-| - pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_branch_target_exception=1 | Implements FEAT_BTI. |
-| - cluster1.has_branch_target_exception=1 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_pointer_authentication=2 | Implements FEAT_PAuth |
-| - cluster1.has_pointer_authentication=2 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.memory_tagging_support_level=2 | Implements FEAT_MTE2 |
-| - cluster1.memory_tagging_support_level=2 | |
-| - bp.dram_metadata.is_enabled=1 | |
-+---------------------------------------------------+------------------------------------+
-
-Sample FVP command line invocation:
-
-.. code:: shell
-
- <path-to-fvp-model>/FVP_Base_RevC-2xAEMvA -C pctl.startup=0.0.0.0 \
- -C cluster0.NUM_CORES=4 -C cluster1.NUM_CORES=4 -C bp.secure_memory=1 \
- -C bp.secureflashloader.fname=trusted-firmware-a/build/fvp/debug/bl1.bin \
- -C bp.flashloader0.fname=trusted-firmware-a/build/fvp/debug/fip.bin \
- -C bp.pl011_uart0.out_file=fvp-uart0.log -C bp.pl011_uart1.out_file=fvp-uart1.log \
- -C bp.pl011_uart2.out_file=fvp-uart2.log \
- -C cluster0.has_arm_v8-5=1 -C cluster1.has_arm_v8-5=1 \
- -C cluster0.has_pointer_authentication=2 -C cluster1.has_pointer_authentication=2 \
- -C cluster0.has_branch_target_exception=1 -C cluster1.has_branch_target_exception=1 \
- -C cluster0.memory_tagging_support_level=2 -C cluster1.memory_tagging_support_level=2 \
- -C bp.dram_metadata.is_enabled=1 \
- -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \
- -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \
- -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \
- -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0
-
Boot process
============
-Loading Hafnium and secure partitions in the secure world
----------------------------------------------------------
-
-TF-A BL2 is the bootlader for the SPMC and SPs in the secure world.
-
-SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
-Thus they are supplied as distinct signed entities within the FIP flash
-image. The FIP image itself is not signed hence this provides the ability
-to upgrade SPs in the field.
-
-Booting through TF-A
---------------------
-
-SP manifests
-~~~~~~~~~~~~
-
-An SP manifest describes SP attributes as defined in `[1]`_
-(partition manifest at virtual FF-A instance) in DTS 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 property) 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
-
-Describing secure partitions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A json-formatted description file is passed to the build flow specifying paths
-to the SP binary image and associated DTS partition manifest file. The latter
-is processed by the dtc compiler to generate a DTB fed into the SP package.
-Optionally, the partition's json description can contain offsets for both
-the image and partition manifest within the SP package. Both offsets need to be
-4KB aligned, because it is the translation granule supported by Hafnium SPMC.
-These fields can be leveraged to support SPs with S1 translation granules that
-differ from 4KB, and to configure the regions allocated within the SP package,
-as well as to comply with the requirements for the implementation of the boot
-information protocol (see `Passing boot data to the SP`_ for more details). In
-case the offsets are absent in their json node, they default to 0x1000 and
-0x4000 for the manifest offset and image offset respectively.
-This file also specifies the SP owner (as an optional field) identifying the
-signing domain in case of dual root CoT.
-The SP owner can either be the silicon or the platform provider. The
-corresponding "owner" field value can either take the value of "SiP" or "Plat".
-In absence of "owner" field, it defaults to "SiP" owner.
-The UUID of the partition can be specified as a field in the description file or
-if it does not exist there the UUID is extracted from the DTS partition
-manifest.
-
-.. code:: shell
-
- {
- "tee1" : {
- "image": "tee1.bin",
- "pm": "tee1.dts",
- "owner": "SiP",
- "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f"
- },
-
- "tee2" : {
- "image": "tee2.bin",
- "pm": "tee2.dts",
- "owner": "Plat"
- },
-
- "tee3" : {
- "image": {
- "file": "tee3.bin",
- "offset":"0x2000"
- },
- "pm": {
- "file": "tee3.dts",
- "offset":"0x6000"
- },
- "owner": "Plat"
- },
- }
-
-SPMC manifest
-~~~~~~~~~~~~~
-
-This manifest contains the SPMC *attribute* node consumed by the SPMD at boot
-time. It implements `[1]`_ (SP manifest at physical FF-A instance) and serves
-two different cases:
-
-- The SPMC resides at S-EL1: the SPMC manifest is used by the SPMD to setup a
- SP that co-resides with the SPMC and executes at S-EL1 or Secure Supervisor
- mode.
-- The SPMC resides at S-EL2: the SPMC manifest is used by the SPMD to setup
- the environment required by the SPMC to run at S-EL2. SPs run at S-EL1 or
- S-EL0.
-
-.. code:: shell
-
- attribute {
- spmc_id = <0x8000>;
- maj_ver = <0x1>;
- min_ver = <0x1>;
- 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 the SPMC execution state (AArch64 or AArch32).
- Notice Hafnium used as a SPMC only supports AArch64.
-- *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``) to enter the SPMC.
-
-Other nodes in the manifest are consumed by Hafnium in the secure world.
-A sample can be found at `[7]`_:
-
-- The *hypervisor* node describes SPs. *is_ffa_partition* boolean attribute
- indicates a FF-A compliant SP. The *load_address* field specifies the load
- address at which BL2 loaded the SP package.
-- *cpus* node provide the platform topology and allows MPIDR to VMPIDR mapping.
- Note the primary core is declared first, then secondary cores are declared
- in reverse order.
-- The *memory* nodes provide platform information on the ranges of memory
- available for use by SPs at runtime. These ranges relate to either
- secure or non-secure memory, depending on the *device_type* field.
- If the field specifies "memory" the range is secure, else if it specifies
- "ns-memory" the memory is non-secure. The system integrator must exclude
- the memory used by other components that are not SPs, such as the monitor,
- or the SPMC itself, the OS Kernel/Hypervisor, or other NWd VMs. The SPMC
- limits the SP's address space such that they do not access memory outside
- of those ranges.
+The boot process involving SPMC is highly dependent on the SPMC implementation.
+It is recommended to refer to corresponding SPMC documentation for further
+details. Some aspects of boot process are described here in the greater interest
+of the project.
SPMC boot
-~~~~~~~~~
+---------
-The SPMC is loaded by BL2 as the BL32 image.
+When SPMC resides at a lower EL i.e., S-EL1 or S-EL2, it is loaded by BL2 as the
+BL32 image. The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[7]`_.
-The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_.
-
-BL2 passes the SPMC manifest address to BL31 through a register.
-
-At boot time, the SPMD in BL31 runs from the primary core, initializes the core
-contexts and launches the SPMC (BL32) passing the following information through
-registers:
+BL2 passes the SPMC manifest address to BL31 through a register. At boot time,
+the SPMD in BL31 runs from the primary core, initializes the core contexts and
+launches the SPMC (BL32) passing the following information through registers:
- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob).
- X1 holds the ``HW_CONFIG`` physical address.
- X4 holds the currently running core linear id.
-Loading of SPs
-~~~~~~~~~~~~~~
-
-At boot time, BL2 loads SPs sequentially in addition to the SPMC as depicted
-below:
-
-.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
-
-Note this boot flow is an implementation sample on Arm's FVP platform.
-Platforms not using TF-A's *Firmware CONFiguration* framework would adjust to a
-different boot flow. The flow restricts to a maximum of 8 secure partitions.
-
-Secure boot
-~~~~~~~~~~~
-
-The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
-SPMC manifest, 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 `[8]`_) allows
-the use of two root keys namely S-ROTPK and NS-ROTPK:
-
-- SPMC (BL32) and SPMC manifest are signed by the SiP using the S-ROTPK.
-- BL33 may be signed by the OEM using NS-ROTPK.
-- An SP may be signed either by SiP (using S-ROTPK) or by OEM (using NS-ROTPK).
-- A maximum of 4 partitions can be signed with the S-ROTPK key and 4 partitions
- signed with the NS-ROTPK key.
-
-Also refer to `Describing secure partitions`_ and `TF-A build options`_ sections.
-
-Hafnium in the secure world
-===========================
-
-General considerations
-----------------------
-
-Build platform for the secure world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In the Hafnium reference implementation specific code parts are only relevant to
-the secure world. Such portions are isolated in architecture specific files
-and/or enclosed by a ``SECURE_WORLD`` macro.
-
-Secure partitions scheduling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The FF-A specification `[1]`_ provides two ways to relinquinsh CPU time to
-secure partitions. For this a VM (Hypervisor or OS kernel), or SP invokes one of:
-
-- the FFA_MSG_SEND_DIRECT_REQ interface.
-- the FFA_RUN interface.
-
-Additionally a secure interrupt can pre-empt the normal world execution and give
-CPU cycles by transitioning to EL3 and S-EL2.
-
-Platform topology
-~~~~~~~~~~~~~~~~~
-
-The *execution-ctx-count* SP manifest field can take the value of one or the
-total number of PEs. The FF-A specification `[1]`_ recommends the
-following SP types:
-
-- Pinned MP SPs: an execution context matches a physical PE. MP SPs must
- implement the same number of ECs as the number of PEs in the platform.
-- Migratable UP SPs: a single execution context can run and be migrated on any
- physical PE. Such SP declares a single EC in its SP manifest. An UP SP can
- receive a direct message request originating from any physical core targeting
- the single execution context.
-
-Parsing SP partition manifests
-------------------------------
-
-Hafnium consumes SP manifests as defined in `[1]`_ and `SP manifests`_.
-Note the current implementation may not implement all optional fields.
-
-The SP manifest may contain memory and device regions nodes. In case of
-an S-EL2 SPMC:
-
-- Memory regions are mapped in the SP EL1&0 Stage-2 translation regime at
- load time (or EL1&0 Stage-1 for an S-EL1 SPMC). A memory region node can
- specify RX/TX buffer regions in which case it is not necessary for an SP
- to explicitly invoke the ``FFA_RXTX_MAP`` interface. The memory referred
- shall be contained within the memory ranges defined in SPMC manifest. The
- NS bit in the attributes field should be consistent with the security
- state of the range that it relates to. I.e. non-secure memory shall be
- part of a non-secure memory range, and secure memory shall be contained
- in a secure memory range of a given platform.
-- Device regions are mapped in the SP EL1&0 Stage-2 translation regime (or
- EL1&0 Stage-1 for an S-EL1 SPMC) as peripherals and possibly allocate
- additional resources (e.g. interrupts).
-
-For the S-EL2 SPMC, base addresses for memory and device region nodes are IPAs
-provided the SPMC identity maps IPAs to PAs within SP EL1&0 Stage-2 translation
-regime.
-
-Note: in the current implementation both VTTBR_EL2 and VSTTBR_EL2 point 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 specification
-provides a memory security attribute hinting to map either to the secure or
-non-secure EL1&0 Stage-2 table if it exists.
-
-Passing boot data to the SP
----------------------------
-
-In `[1]`_ , the section "Boot information protocol" defines a method for passing
-data to the SPs at boot time. It specifies the format for the boot information
-descriptor and boot information header structures, which describe the data to be
-exchanged between SPMC and SP.
-The specification also defines the types of data that can be passed.
-The aggregate of both the boot info structures and the data itself is designated
-the boot information blob, and is passed to a Partition as a contiguous memory
-region.
-
-Currently, the SPM implementation supports the FDT type which is used to pass the
-partition's DTB manifest.
-
-The region for the boot information blob is allocated through the SP package.
-
-.. image:: ../resources/diagrams/partition-package.png
-
-To adjust the space allocated for the boot information blob, the json description
-of the SP (see section `Describing secure partitions`_) shall be updated to contain
-the manifest offset. If no offset is provided the manifest offset defaults to 0x1000,
-which is the page size in the Hafnium SPMC.
-
-The configuration of the boot protocol is done in the SPs manifest. As defined by
-the specification, the manifest field 'gp-register-num' configures the GP register
-which shall be used to pass the address to the partitions boot information blob when
-booting the partition.
-In addition, the Hafnium SPMC implementation requires the boot information arguments
-to be listed in a designated DT node:
-
-.. code:: shell
-
- boot-info {
- compatible = "arm,ffa-manifest-boot-info";
- ffa_manifest;
- };
-
-The whole secure partition package image (see `Secure Partition packages`_) is
-mapped to the SP secure EL1&0 Stage-2 translation regime. As such, the SP can
-retrieve the address for the boot information blob in the designated GP register,
-process the boot information header and descriptors, 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. SPMC boots the SPs in accordance to the boot order attribute,
-lowest to the highest value. If the boot order attribute is absent from the FF-A
-manifest, the SP is treated as if it had the highest boot order value
-(i.e. lowest booting priority).
-
-It is possible for an SP to call into another SP through a direct request
-provided the latter SP has already been booted.
-
-Boot phases
------------
-
-Primary core boot-up
-~~~~~~~~~~~~~~~~~~~~
-
-Upon boot-up, BL31 hands over to the SPMC (BL32) on the primary boot physical
-core. The SPMC performs its platform initializations and registers the SPMC
-secondary physical core entry point physical address by the use of the
-`FFA_SECONDARY_EP_REGISTER`_ interface (SMC invocation from the SPMC to the SPMD
-at secure physical FF-A instance).
-
-The SPMC then creates secure partitions based on SP packages and manifests. Each
-secure partition is launched in sequence (`SP Boot order`_) on their "primary"
-execution context. If the primary boot physical core linear id is N, an MP SP is
-started using EC[N] on PE[N] (see `Platform topology`_). If the partition is a
-UP SP, it is started using its unique EC0 on PE[N].
-
-The SP primary EC (or the EC used when the partition is booted as described
-above):
-
-- Performs the overall SP boot time initialization, and in case of a MP SP,
- prepares the SP environment for other execution contexts.
-- In the case of a MP SP, it invokes the FFA_SECONDARY_EP_REGISTER at secure
- virtual FF-A instance (SMC invocation from SP to SPMC) to provide the IPA
- entry point for other execution contexts.
-- Exits through ``FFA_MSG_WAIT`` to indicate successful initialization or
- ``FFA_ERROR`` in case of failure.
-
-Secondary cores boot-up
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Once the system is started and NWd brought up, a secondary physical core is
-woken up by the ``PSCI_CPU_ON`` service invocation. The TF-A SPD hook mechanism
-calls into the SPMD on the newly woken up physical core. Then the SPMC is
-entered at the secondary physical core entry point.
-
-In the current implementation, the first SP is resumed on the coresponding EC
-(the virtual CPU which matches the physical core). The implication is that the
-first SP must be a MP SP.
-
-In a linux based system, once secure and normal worlds are booted but prior to
-a NWd FF-A driver has been loaded:
-
-- The first SP has initialized all its ECs in response to primary core boot up
- (at system initialization) and secondary core boot up (as a result of linux
- invoking PSCI_CPU_ON for all secondary cores).
-- Other SPs have their first execution context initialized as a result of secure
- world initialization on the primary boot core. Other ECs for those SPs have to
- be run first through ffa_run to complete their initialization (which results
- in the EC completing with FFA_MSG_WAIT).
-
-Refer to `Power management`_ for further details.
-
-Notifications
--------------
-
-The FF-A v1.1 specification `[1]`_ defines notifications as an asynchronous
-communication mechanism with non-blocking semantics. It allows for one FF-A
-endpoint to signal another for service provision, without hindering its current
-progress.
-
-Hafnium currently supports 64 notifications. The IDs of each notification define
-a position in a 64-bit bitmap.
-
-The signaling of notifications can interchangeably happen between NWd and SWd
-FF-A endpoints.
-
-The SPMC is in charge of managing notifications from SPs to SPs, from SPs to
-VMs, and from VMs to SPs. An hypervisor component would only manage
-notifications from VMs to VMs. Given the SPMC has no visibility of the endpoints
-deployed in NWd, the Hypervisor or OS kernel must invoke the interface
-FFA_NOTIFICATION_BITMAP_CREATE to allocate the notifications bitmap per FF-A
-endpoint in the NWd that supports it.
-
-A sender can signal notifications once the receiver has provided it with
-permissions. Permissions are provided by invoking the interface
-FFA_NOTIFICATION_BIND.
-
-Notifications are signaled by invoking FFA_NOTIFICATION_SET. Henceforth
-they are considered to be in a pending sate. The receiver can retrieve its
-pending notifications invoking FFA_NOTIFICATION_GET, which, from that moment,
-are considered to be handled.
-
-Per the FF-A v1.1 spec, each FF-A endpoint must be associated with a scheduler
-that is in charge of donating CPU cycles for notifications handling. The
-FF-A driver calls FFA_NOTIFICATION_INFO_GET to retrieve the information about
-which FF-A endpoints have pending notifications. The receiver scheduler is
-called and informed by the FF-A driver, and it should allocate CPU cycles to the
-receiver.
-
-There are two types of notifications supported:
-
-- Global, which are targeted to a FF-A endpoint and can be handled within any of
- its execution contexts, as determined by the scheduler of the system.
-- Per-vCPU, which are targeted to a FF-A endpoint and to be handled within a
- a specific execution context, as determined by the sender.
-
-The type of a notification is set when invoking FFA_NOTIFICATION_BIND to give
-permissions to the sender.
-
-Notification signaling resorts to two interrupts:
-
-- Schedule Receiver Interrupt: non-secure physical interrupt to be handled by
- the FF-A driver within the receiver scheduler. At initialization the SPMC
- donates a SGI ID chosen from the secure SGI IDs range and configures it as
- non-secure. The SPMC triggers this SGI on the currently running core when
- there are pending notifications, and the respective receivers need CPU cycles
- to handle them.
-- Notifications Pending Interrupt: virtual interrupt to be handled by the
- receiver of the notification. Set when there are pending notifications for the
- given secure partition. The NPI is pended when the NWd relinquishes CPU cycles
- to an SP.
-
-The notifications receipt support is enabled in the partition FF-A manifest.
-
-Mandatory interfaces
---------------------
-
-The following interfaces are exposed to SPs:
-
-- ``FFA_VERSION``
-- ``FFA_FEATURES``
-- ``FFA_RX_RELEASE``
-- ``FFA_RXTX_MAP``
-- ``FFA_RXTX_UNMAP``
-- ``FFA_PARTITION_INFO_GET``
-- ``FFA_ID_GET``
-- ``FFA_MSG_WAIT``
-- ``FFA_MSG_SEND_DIRECT_REQ``
-- ``FFA_MSG_SEND_DIRECT_RESP``
-- ``FFA_MEM_DONATE``
-- ``FFA_MEM_LEND``
-- ``FFA_MEM_SHARE``
-- ``FFA_MEM_RETRIEVE_REQ``
-- ``FFA_MEM_RETRIEVE_RESP``
-- ``FFA_MEM_RELINQUISH``
-- ``FFA_MEM_FRAG_RX``
-- ``FFA_MEM_FRAG_TX``
-- ``FFA_MEM_RECLAIM``
-- ``FFA_RUN``
-
-As part of the FF-A v1.1 support, the following interfaces were added:
-
- - ``FFA_NOTIFICATION_BITMAP_CREATE``
- - ``FFA_NOTIFICATION_BITMAP_DESTROY``
- - ``FFA_NOTIFICATION_BIND``
- - ``FFA_NOTIFICATION_UNBIND``
- - ``FFA_NOTIFICATION_SET``
- - ``FFA_NOTIFICATION_GET``
- - ``FFA_NOTIFICATION_INFO_GET``
- - ``FFA_SPM_ID_GET``
- - ``FFA_SECONDARY_EP_REGISTER``
- - ``FFA_MEM_PERM_GET``
- - ``FFA_MEM_PERM_SET``
- - ``FFA_MSG_SEND2``
- - ``FFA_RX_ACQUIRE``
-
-FFA_VERSION
-~~~~~~~~~~~
-
-``FFA_VERSION`` requires a *requested_version* parameter from the caller.
-The returned value depends on the caller:
-
-- Hypervisor or OS kernel in NS-EL1/EL2: the SPMD returns the SPMC version
- specified in the SPMC manifest.
-- SP: the SPMC returns its own implemented version.
-- SPMC at S-EL1/S-EL2: the SPMD returns its own implemented version.
-
-FFA_FEATURES
-~~~~~~~~~~~~
-
-FF-A features supported by the SPMC may be discovered by secure partitions at
-boot (that is prior to NWd is booted) or run-time.
-
-The SPMC calling FFA_FEATURES at secure physical FF-A instance always get
-FFA_SUCCESS from the SPMD.
-
-The request made by an Hypervisor or OS kernel is forwarded to the SPMC and
-the response relayed back to the NWd.
-
-FFA_RXTX_MAP/FFA_RXTX_UNMAP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When invoked from a secure partition FFA_RXTX_MAP maps the provided send and
-receive buffers described by their IPAs to the SP EL1&0 Stage-2 translation
-regime as secure buffers in the MMU descriptors.
-
-When invoked from the Hypervisor or OS kernel, the buffers are mapped into the
-SPMC EL2 Stage-1 translation regime and marked as NS buffers in the MMU
-descriptors. The provided addresses may be owned by a VM in the normal world,
-which is expected to receive messages from the secure world. The SPMC will in
-this case allocate internal state structures to facilitate RX buffer access
-synchronization (through FFA_RX_ACQUIRE interface), and to permit SPs to send
-messages.
-
-The FFA_RXTX_UNMAP unmaps the RX/TX pair from the translation regime of the
-caller, either it being the Hypervisor or OS kernel, as well as a secure
-partition.
-
-FFA_PARTITION_INFO_GET
-~~~~~~~~~~~~~~~~~~~~~~
-
-Partition info get call can originate:
-
-- from SP to SPMC
-- from Hypervisor or OS kernel to SPMC. The request is relayed by the SPMD.
-
-FFA_ID_GET
-~~~~~~~~~~
-
-The FF-A id space is split into a non-secure space and secure space:
-
-- FF-A ID with bit 15 clear relates to VMs.
-- FF-A ID with bit 15 set related to SPs.
-- FF-A IDs 0, 0xffff, 0x8000 are assigned respectively to the Hypervisor, SPMD
- and SPMC.
-
-The SPMD returns:
-
-- The 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`_)
-
-This convention helps the SPMC to determine the origin and destination worlds in
-an FF-A ABI 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 by spoofing:
-
-- A VM-to-SP direct request/response shall set the origin world to be non-secure
- (FF-A ID bit 15 clear) and destination world to be secure (FF-A ID bit 15
- set).
-- Similarly, an SP-to-SP direct request/response shall set the FF-A ID bit 15
- 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".
-
-
-FFA_MSG_SEND_DIRECT_REQ/FFA_MSG_SEND_DIRECT_RESP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This is a mandatory interface for secure partitions consisting in direct request
-and responses with the following rules:
-
-- An SP can send a direct request to another SP.
-- An SP can receive a direct request from another SP.
-- An SP can send a direct response to another SP.
-- An SP cannot send a direct request to an Hypervisor or OS kernel.
-- An Hypervisor or OS kernel can send a direct request to an SP.
-- An SP can send a direct response to an Hypervisor or OS kernel.
-
-FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The secure partitions notifications bitmap are statically allocated by the SPMC.
-Hence, this interface is not to be issued by secure partitions.
-
-At initialization, the SPMC is not aware of VMs/partitions deployed in the
-normal world. Hence, the Hypervisor or OS kernel must use both ABIs for SPMC
-to be prepared to handle notifications for the provided VM ID.
-
-FFA_NOTIFICATION_BIND/FFA_NOTIFICATION_UNBIND
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Pair of interfaces to manage permissions to signal notifications. Prior to
-handling notifications, an FF-A endpoint must allow a given sender to signal a
-bitmap of notifications.
-
-If the receiver doesn't have notification support enabled in its FF-A manifest,
-it won't be able to bind notifications, hence forbidding it to receive any
-notifications.
-
-FFA_NOTIFICATION_SET/FFA_NOTIFICATION_GET
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-FFA_NOTIFICATION_GET retrieves all pending global notifications and
-per-vCPU notifications targeted to the current vCPU.
-
-Hafnium maintains a global count of pending notifications which gets incremented
-and decremented when handling FFA_NOTIFICATION_SET and FFA_NOTIFICATION_GET
-respectively. A delayed SRI is triggered if the counter is non-zero when the
-SPMC returns to normal world.
-
-FFA_NOTIFICATION_INFO_GET
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Hafnium maintains a global count of pending notifications whose information
-has been retrieved by this interface. The count is incremented and decremented
-when handling FFA_NOTIFICATION_INFO_GET and FFA_NOTIFICATION_GET respectively.
-It also tracks notifications whose information has been retrieved individually,
-such that it avoids duplicating returned information for subsequent calls to
-FFA_NOTIFICATION_INFO_GET. For each notification, this state information is
-reset when receiver called FFA_NOTIFICATION_GET to retrieve them.
-
-FFA_SPM_ID_GET
-~~~~~~~~~~~~~~
-
-Returns the FF-A ID allocated to an SPM component which can be one of SPMD
-or SPMC.
-
-At initialization, the SPMC queries the SPMD for the SPMC ID, using the
-FFA_ID_GET interface, and records it. The SPMC can also query the SPMD ID using
-the FFA_SPM_ID_GET interface at the secure physical FF-A instance.
-
-Secure partitions call this interface at the virtual FF-A instance, to which
-the SPMC returns the priorly retrieved SPMC ID.
-
-The Hypervisor or OS kernel can issue the FFA_SPM_ID_GET call handled by the
-SPMD, which returns the SPMC ID.
-
-FFA_SECONDARY_EP_REGISTER
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When the SPMC boots, all secure partitions are initialized on their primary
-Execution Context.
-
-The FFA_SECONDARY_EP_REGISTER interface is to be used by a secure partition
-from its first execution context, to provide the entry point address for
-secondary execution contexts.
-
-A secondary EC is first resumed either upon invocation of PSCI_CPU_ON from
-the NWd or by invocation of FFA_RUN.
-
-FFA_RX_ACQUIRE/FFA_RX_RELEASE
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The RX buffers can be used to pass information to an FF-A endpoint in the
-following scenarios:
-
- - When it was targetted by a FFA_MSG_SEND2 invokation from another endpoint.
- - Return the result of calling ``FFA_PARTITION_INFO_GET``.
- - In a memory share operation, as part of the ``FFA_MEM_RETRIEVE_RESP``,
- with the memory descriptor of the shared memory.
-
-If a normal world VM is expected to exchange messages with secure world,
-its RX/TX buffer addresses are forwarded to the SPMC via FFA_RXTX_MAP ABI,
-and are from this moment owned by the SPMC.
-The hypervisor must call the FFA_RX_ACQUIRE interface before attempting
-to use the RX buffer, in any of the aforementioned scenarios. A successful
-call to FFA_RX_ACQUIRE transfers ownership of RX buffer to hypervisor, such
-that it can be safely used.
-
-The FFA_RX_RELEASE interface is used after the FF-A endpoint is done with
-processing the data received in its RX buffer. If the RX buffer has been
-acquired by the hypervisor, the FFA_RX_RELEASE call must be forwarded to
-the SPMC to reestablish SPMC's RX ownership.
-
-An attempt from an SP to send a message to a normal world VM whose RX buffer
-was acquired by the hypervisor fails with error code FFA_BUSY, to preserve
-the RX buffer integrity.
-The operation could then be conducted after FFA_RX_RELEASE.
-
-FFA_MSG_SEND2
-~~~~~~~~~~~~~
-
-Hafnium copies a message from the sender TX buffer into receiver's RX buffer.
-For messages from SPs to VMs, operation is only possible if the SPMC owns
-the receiver's RX buffer.
-
-Both receiver and sender need to enable support for indirect messaging,
-in their respective partition manifest. The discovery of support
-of such feature can be done via FFA_PARTITION_INFO_GET.
-
-On a successful message send, Hafnium pends an RX buffer full framework
-notification for the receiver, to inform it about a message in the RX buffer.
-
-The handling of framework notifications is similar to that of
-global notifications. Binding of these is not necessary, as these are
-reserved to be used by the hypervisor or SPMC.
-
-SPMC-SPMD direct requests/responses
------------------------------------
-
-Implementation-defined FF-A IDs are allocated to the SPMC and SPMD.
-Using those IDs in source/destination fields of a direct request/response
-permits SPMD to SPMC communication and either way.
-
-- SPMC to SPMD direct request/response uses SMC conduit.
-- SPMD to SPMC direct request/response uses ERET conduit.
-
-This is used in particular to convey power management messages.
-
-Memory Sharing
---------------
-
-Hafnium implements the following memory sharing interfaces:
-
- - ``FFA_MEM_SHARE`` - for shared access between lender and borrower.
- - ``FFA_MEM_LEND`` - borrower to obtain exclusive access, though lender
- retains ownership of the memory.
- - ``FFA_MEM_DONATE`` - lender permanently relinquishes ownership of memory
- to the borrower.
-
-The ``FFA_MEM_RETRIEVE_REQ`` interface is for the borrower to request the
-memory to be mapped into its address space: for S-EL1 partitions the SPM updates
-their stage 2 translation regime; for S-EL0 partitions the SPM updates their
-stage 1 translation regime. On a successful call, the SPMC responds back with
-``FFA_MEM_RETRIEVE_RESP``.
-
-The ``FFA_MEM_RELINQUISH`` interface is for when the borrower is done with using
-a memory region.
-
-The ``FFA_MEM_RECLAIM`` interface is for the owner of the memory to reestablish
-its ownership and exclusive access to the memory shared.
-
-The memory transaction descriptors are transmitted via RX/TX buffers. In
-situations where the size of the memory transaction descriptor exceeds the
-size of the RX/TX buffers, Hafnium provides support for fragmented transmission
-of the full transaction descriptor. The ``FFA_MEM_FRAG_RX`` and ``FFA_MEM_FRAG_TX``
-interfaces are for receiving and transmitting the next fragment, respectively.
-
-If lender and borrower(s) are SPs, all memory sharing operations are supported.
-
-Hafnium also supports memory sharing operations between the normal world and the
-secure world. If there is an SP involved, the SPMC allocates data to track the
-state of the operation.
-
-The SPMC is also the designated allocator for the memory handle. The hypervisor
-or OS kernel has the possibility to rely on the SPMC to maintain the state
-of the operation, thus saving memory.
-A lender SP can only donate NS memory to a borrower from the normal world.
-
-The SPMC supports the hypervisor retrieve request, as defined by the FF-A
-v1.1 EAC0 specification, in section 16.4.3. The intent is to aid with operations
-that the hypervisor must do for a VM retriever. For example, when handling
-an FFA_MEM_RECLAIM, if the hypervisor relies on SPMC to keep the state
-of the operation, the hypervisor retrieve request can be used to obtain
-that state information, do the necessary validations, and update stage 2
-memory translation.
-
-Hafnium also supports memory lend and share targetting multiple borrowers.
-This is the case for a lender SP to multiple SPs, and for a lender VM to
-multiple endpoints (from both secure world and normal world). If there is
-at least one borrower VM, the hypervisor is in charge of managing its
-stage 2 translation on a successful memory retrieve.
-The semantics of ``FFA_MEM_DONATE`` implies ownership transmission,
-which should target only one partition.
-
-The memory share interfaces are backwards compatible with memory transaction
-descriptors from FF-A v1.0. These get translated to FF-A v1.1 descriptors for
-Hafnium's internal processing of the operation. If the FF-A version of a
-borrower is v1.0, Hafnium provides FF-A v1.0 compliant memory transaction
-descriptors on memory retrieve response.
-
-PE MMU configuration
---------------------
-
-With secure virtualization enabled (``HCR_EL2.VM = 1``) and for S-EL1
-partitions, two IPA spaces (secure and non-secure) are output from the
-secure EL1&0 Stage-1 translation.
-The EL1&0 Stage-2 translation hardware is fed by:
-
-- A secure IPA when the SP EL1&0 Stage-1 MMU is disabled.
-- One of secure or non-secure IPA when the secure EL1&0 Stage-1 MMU is enabled.
-
-``VTCR_EL2`` and ``VSTCR_EL2`` provide configuration bits for controlling the
-NS/S IPA translations. The following controls are set up:
-``VSTCR_EL2.SW = 0`` , ``VSTCR_EL2.SA = 0``, ``VTCR_EL2.NSW = 0``,
-``VTCR_EL2.NSA = 1``:
-
-- Stage-2 translations for the NS IPA space access the NS PA space.
-- Stage-2 translation table walks for the NS IPA space are to the secure PA space.
-
-Secure and non-secure IPA regions (rooted to by ``VTTBR_EL2`` and ``VSTTBR_EL2``)
-use the same set of Stage-2 page tables within a SP.
-
-The ``VTCR_EL2/VSTCR_EL2/VTTBR_EL2/VSTTBR_EL2`` virtual address space
-configuration is made part of a vCPU context.
-
-For S-EL0 partitions with VHE enabled, a single secure EL2&0 Stage-1 translation
-regime is used for both Hafnium and the partition.
-
-Schedule modes and SP Call chains
----------------------------------
-
-An SP execution context is said to be in SPMC scheduled mode if CPU cycles are
-allocated to it by SPMC. Correspondingly, an SP execution context is said to be
-in Normal world scheduled mode if CPU cycles are allocated by the normal world.
-
-A call chain represents all SPs in a sequence of invocations of a direct message
-request. When execution on a PE is in the secure state, only a single call chain
-that runs in the Normal World scheduled mode can exist. FF-A v1.1 spec allows
-any number of call chains to run in the SPMC scheduled mode but the Hafnium
-SPMC restricts the number of call chains in SPMC scheduled mode to only one for
-keeping the implementation simple.
-
-Partition runtime models
-------------------------
-
-The runtime model of an endpoint describes the transitions permitted for an
-execution context between various states. These are the four partition runtime
-models supported (refer to `[1]`_ section 7):
-
- - RTM_FFA_RUN: runtime model presented to an execution context that is
- allocated CPU cycles through FFA_RUN interface.
- - RTM_FFA_DIR_REQ: runtime model presented to an execution context that is
- allocated CPU cycles through FFA_MSG_SEND_DIRECT_REQ interface.
- - RTM_SEC_INTERRUPT: runtime model presented to an execution context that is
- allocated CPU cycles by SPMC to handle a secure interrupt.
- - RTM_SP_INIT: runtime model presented to an execution context that is
- allocated CPU cycles by SPMC to initialize its state.
-
-If an endpoint execution context attempts to make an invalid transition or a
-valid transition that could lead to a loop in the call chain, SPMC denies the
-transition with the help of above runtime models.
-
-Interrupt management
---------------------
-
-GIC ownership
-~~~~~~~~~~~~~
-
-The SPMC owns the GIC configuration. Secure and non-secure interrupts are
-trapped at S-EL2. The SPMC manages interrupt resources and allocates interrupt
-IDs based on SP manifests. The SPMC acknowledges physical interrupts and injects
-virtual interrupts by setting the use of vIRQ/vFIQ bits before resuming a SP.
-
-Abbreviations:
-
- - NS-Int: A non-secure physical interrupt. It requires a switch to the normal
- world to be handled if it triggers while execution is in secure world.
- - Other S-Int: A secure physical interrupt targeted to an SP different from
- the one that is currently running.
- - Self S-Int: A secure physical interrupt targeted to the SP that is currently
- running.
-
-Non-secure interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This section documents the actions supported in SPMC in response to a non-secure
-interrupt as per the guidance provided by FF-A v1.1 EAC0 specification.
-An SP specifies one of the following actions in its partition manifest:
-
- - Non-secure interrupt is signaled.
- - Non-secure interrupt is signaled after a managed exit.
- - Non-secure interrupt is queued.
-
-An SP execution context in a call chain could specify a less permissive action
-than subsequent SP execution contexts in the same call chain. The less
-permissive action takes precedence over the more permissive actions specified
-by the subsequent execution contexts. Please refer to FF-A v1.1 EAC0 section
-8.3.1 for further explanation.
-
-Secure interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This section documents the support implemented for secure interrupt handling in
-SPMC as per the guidance provided by FF-A v1.1 EAC0 specification.
-The following assumptions are made about the system configuration:
-
- - In the current implementation, S-EL1 SPs are expected to use the para
- virtualized ABIs for interrupt management rather than accessing the virtual
- GIC interface.
- - Unless explicitly stated otherwise, this support is applicable only for
- S-EL1 SPs managed by SPMC.
- - Secure interrupts are configured as G1S or G0 interrupts.
- - All physical interrupts are routed to SPMC when running a secure partition
- execution context.
- - All endpoints with multiple execution contexts have their contexts pinned
- to corresponding CPUs. Hence, a secure virtual interrupt cannot be signaled
- to a target vCPU that is currently running or blocked on a different
- physical CPU.
-
-A physical secure interrupt could trigger while CPU is executing in normal world
-or secure world.
-The action of SPMC for a secure interrupt depends on: the state of the target
-execution context of the SP that is responsible for handling the interrupt;
-whether the interrupt triggered while execution was in normal world or secure
-world.
-
-Secure interrupt signaling mechanisms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Signaling refers to the mechanisms used by SPMC to indicate to the SP execution
-context that it has a pending virtual interrupt and to further run the SP
-execution context, such that it can handle the virtual interrupt. SPMC uses
-either the FFA_INTERRUPT interface with ERET conduit or vIRQ signal for signaling
-to S-EL1 SPs. When normal world execution is preempted by a secure interrupt,
-the SPMD uses the FFA_INTERRUPT ABI with ERET conduit to signal interrupt to SPMC
-running in S-EL2.
-
-+-----------+---------+---------------+---------------------------------------+
-| SP State | Conduit | Interface and | Description |
-| | | parameters | |
-+-----------+---------+---------------+---------------------------------------+
-| WAITING | ERET, | FFA_INTERRUPT,| SPMC signals to SP the ID of pending |
-| | vIRQ | Interrupt ID | interrupt. It pends vIRQ signal and |
-| | | | resumes execution context of SP |
-| | | | through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-| BLOCKED | ERET, | FFA_INTERRUPT | SPMC signals to SP that an interrupt |
-| | vIRQ | | is pending. It pends vIRQ signal and |
-| | | | resumes execution context of SP |
-| | | | through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-| PREEMPTED | vIRQ | NA | SPMC pends the vIRQ signal but does |
-| | | | not resume execution context of SP. |
-+-----------+---------+---------------+---------------------------------------+
-| RUNNING | ERET, | NA | SPMC pends the vIRQ signal and resumes|
-| | vIRQ | | execution context of SP through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-
-Secure interrupt completion mechanisms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A SP signals secure interrupt handling completion to the SPMC through the
-following mechanisms:
-
- - ``FFA_MSG_WAIT`` ABI if it was in WAITING state.
- - ``FFA_RUN`` ABI if its was in BLOCKED state.
-
-This is a remnant of SPMC implementation based on the FF-A v1.0 specification.
-In the current implementation, S-EL1 SPs use the para-virtualized HVC interface
-implemented by SPMC to perform priority drop and interrupt deactivation (SPMC
-configures EOImode = 0, i.e. priority drop and deactivation are done together).
-The SPMC performs checks to deny the state transition upon invocation of
-either FFA_MSG_WAIT or FFA_RUN interface if the SP didn't perform the
-deactivation of the secure virtual interrupt.
-
-If the current SP execution context was preempted by a secure interrupt to be
-handled by execution context of target SP, SPMC resumes current SP after signal
-completion by target SP execution context.
-
-Actions for a secure interrupt triggered while execution is in normal world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-+-------------------+----------+-----------------------------------------------+
-| State of target | Action | Description |
-| execution context | | |
-+-------------------+----------+-----------------------------------------------+
-| WAITING | Signaled | This starts a new call chain in SPMC scheduled|
-| | | mode. |
-+-------------------+----------+-----------------------------------------------+
-| PREEMPTED | Queued | The target execution must have been preempted |
-| | | by a non-secure interrupt. SPMC queues the |
-| | | secure virtual interrupt now. It is signaled |
-| | | when the target execution context next enters |
-| | | the RUNNING state. |
-+-------------------+----------+-----------------------------------------------+
-| BLOCKED, RUNNING | NA | The target execution context is blocked or |
-| | | running on a different CPU. This is not |
-| | | supported by current SPMC implementation and |
-| | | execution hits panic. |
-+-------------------+----------+-----------------------------------------------+
-
-If normal world execution was preempted by a secure interrupt, SPMC uses
-FFA_NORMAL_WORLD_RESUME ABI to indicate completion of secure interrupt handling
-and further returns execution to normal world.
-
-The following figure describes interrupt handling flow when a secure interrupt
-triggers while execution is in normal world:
-
-.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-nwd.png
-
-A brief description of the events:
-
- - 1) Secure interrupt triggers while normal world is running.
- - 2) FIQ gets trapped to EL3.
- - 3) SPMD signals secure interrupt to SPMC at S-EL2 using FFA_INTERRUPT ABI.
- - 4) SPMC identifies target vCPU of SP and injects virtual interrupt (pends
- vIRQ).
- - 5) Assuming SP1 vCPU is in WAITING state, SPMC signals virtual interrupt
- using FFA_INTERRUPT with interrupt id as an argument and resumes the SP1
- vCPU using ERET in SPMC scheduled mode.
- - 6) Execution traps to vIRQ handler in SP1 provided that the virtual
- interrupt is not masked i.e., PSTATE.I = 0
- - 7) SP1 queries for the pending virtual interrupt id using a paravirtualized
- HVC call. SPMC clears the pending virtual interrupt state management
- and returns the pending virtual interrupt id.
- - 8) SP1 services the virtual interrupt and invokes the paravirtualized
- de-activation HVC call. SPMC de-activates the physical interrupt,
- clears the fields tracking the secure interrupt and resumes SP1 vCPU.
- - 9) SP1 performs secure interrupt completion through FFA_MSG_WAIT ABI.
- - 10) SPMC returns control to EL3 using FFA_NORMAL_WORLD_RESUME.
- - 11) EL3 resumes normal world execution.
-
-Actions for a secure interrupt triggered while execution is in secure world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-+-------------------+----------+------------------------------------------------+
-| State of target | Action | Description |
-| execution context | | |
-+-------------------+----------+------------------------------------------------+
-| WAITING | Signaled | This starts a new call chain in SPMC scheduled |
-| | | mode. |
-+-------------------+----------+------------------------------------------------+
-| PREEMPTED by Self | Signaled | The target execution context reenters the |
-| S-Int | | RUNNING state to handle the secure virtual |
-| | | interrupt. |
-+-------------------+----------+------------------------------------------------+
-| PREEMPTED by | Queued | SPMC queues the secure virtual interrupt now. |
-| NS-Int | | It is signaled when the target execution |
-| | | context next enters the RUNNING state. |
-+-------------------+----------+------------------------------------------------+
-| BLOCKED | Signaled | Both preempted and target execution contexts |
-| | | must have been part of the Normal world |
-| | | scheduled call chain. Refer scenario 1 of |
-| | | Table 8.4 in the FF-A v1.1 EAC0 spec. |
-+-------------------+----------+------------------------------------------------+
-| RUNNING | NA | The target execution context is running on a |
-| | | different CPU. This scenario is not supported |
-| | | by current SPMC implementation and execution |
-| | | hits panic. |
-+-------------------+----------+------------------------------------------------+
-
-The following figure describes interrupt handling flow when a secure interrupt
-triggers while execution is in secure world. We assume OS kernel sends a direct
-request message to SP1. Further, SP1 sends a direct request message to SP2. SP1
-enters BLOCKED state and SPMC resumes SP2.
-
-.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-swd.png
-
-A brief description of the events:
-
- - 1) Secure interrupt triggers while SP2 is running.
- - 2) SP2 gets preempted and execution traps to SPMC as IRQ.
- - 3) SPMC finds the target vCPU of secure partition responsible for handling
- this secure interrupt. In this scenario, it is SP1.
- - 4) SPMC pends vIRQ for SP1 and signals through FFA_INTERRUPT interface.
- SPMC further resumes SP1 through ERET conduit. Note that SP1 remains in
- Normal world schedule mode.
- - 6) Execution traps to vIRQ handler in SP1 provided that the virtual
- interrupt is not masked i.e., PSTATE.I = 0
- - 7) SP1 queries for the pending virtual interrupt id using a paravirtualized
- HVC call. SPMC clears the pending virtual interrupt state management
- and returns the pending virtual interrupt id.
- - 8) SP1 services the virtual interrupt and invokes the paravirtualized
- de-activation HVC call. SPMC de-activates the physical interrupt and
- clears the fields tracking the secure interrupt and resumes SP1 vCPU.
- - 9) Since SP1 direct request completed with FFA_INTERRUPT, it resumes the
- direct request to SP2 by invoking FFA_RUN.
- - 9) SPMC resumes the pre-empted vCPU of SP2.
-
-EL3 interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~
-
-In GICv3 based systems, EL3 interrupts are configured as Group0 secure
-interrupts. Execution traps to SPMC when a Group0 interrupt triggers while an
-SP is running. Further, SPMC running at S-EL2 uses FFA_EL3_INTR_HANDLE ABI to
-request EL3 platform firmware to handle a pending Group0 interrupt.
-Similarly, SPMD registers a handler with interrupt management framework to
-delegate handling of Group0 interrupt to the platform if the interrupt triggers
-in normal world.
-
- - Platform hook
-
- - plat_spmd_handle_group0_interrupt
-
- SPMD provides platform hook to handle Group0 secure interrupts. In the
- current design, SPMD expects the platform not to delegate handling to the
- NWd (such as through SDEI) while processing Group0 interrupts.
-
-Power management
-----------------
-
-In platforms with or without secure virtualization:
-
-- The NWd owns the platform PM policy.
-- The Hypervisor or OS kernel is the component initiating PSCI service calls.
-- The EL3 PSCI library is in charge of the PM coordination and control
- (eventually writing to platform registers).
-- While coordinating PM events, the PSCI library calls backs into the Secure
- Payload Dispatcher for events the latter has statically registered to.
-
-When using the SPMD as a Secure Payload Dispatcher:
-
-- A power management event is relayed through the SPD hook to the SPMC.
-- In the current implementation only cpu on (svc_on_finish) and cpu off
- (svc_off) hooks are registered.
-- The behavior for the cpu on event is described in `Secondary cores boot-up`_.
- The SPMC is entered through its secondary physical core entry point.
-- The cpu off event occurs when the NWd calls PSCI_CPU_OFF. The PM event is
- signaled to the SPMC through a power management framework message.
- It consists in a SPMD-to-SPMC direct request/response (`SPMC-SPMD direct
- requests/responses`_) conveying the event details and SPMC response.
- The SPMD performs a synchronous entry into the SPMC. The SPMC is entered and
- updates its internal state to reflect the physical core is being turned off.
- In the current implementation no SP is resumed as a consequence. This behavior
- ensures a minimal support for CPU hotplug e.g. when initiated by the NWd linux
- userspace.
-
-Arm architecture extensions for security hardening
-==================================================
-
-Hafnium supports the following architecture extensions for security hardening:
-
-- Pointer authentication (FEAT_PAuth): the extension permits detection of forged
- pointers used by ROP type of attacks through the signing of the pointer
- value. Hafnium is built with the compiler branch protection option to permit
- generation of a pointer authentication code for return addresses (pointer
- authentication for instructions). The APIA key is used while Hafnium runs.
- A random key is generated at boot time and restored upon entry into Hafnium
- at run-time. APIA and other keys (APIB, APDA, APDB, APGA) are saved/restored
- in vCPU contexts permitting to enable pointer authentication in VMs/SPs.
-- Branch Target Identification (FEAT_BTI): the extension permits detection of
- unexpected indirect branches used by JOP type of attacks. Hafnium is built
- with the compiler branch protection option, inserting land pads at function
- prologues that are reached by indirect branch instructions (BR/BLR).
- Hafnium code pages are marked as guarded in the EL2 Stage-1 MMU descriptors
- such that an indirect branch must always target a landpad. A fault is
- triggered otherwise. VMs/SPs can (independently) mark their code pages as
- guarded in the EL1&0 Stage-1 translation regime.
-- Memory Tagging Extension (FEAT_MTE): the option permits detection of out of
- bound memory array accesses or re-use of an already freed memory region.
- Hafnium enables the compiler option permitting to leverage MTE stack tagging
- applied to core stacks. Core stacks are marked as normal tagged memory in the
- EL2 Stage-1 translation regime. A synchronous data abort is generated upon tag
- check failure on load/stores. A random seed is generated at boot time and
- restored upon entry into Hafnium. MTE system registers are saved/restored in
- vCPU contexts permitting MTE usage from VMs/SPs.
-
-SMMUv3 support in Hafnium
-=========================
-
-An SMMU is analogous to an MMU in a CPU. It performs address translations for
-Direct Memory Access (DMA) requests from system I/O devices.
-The responsibilities of an SMMU include:
-
-- Translation: Incoming DMA requests are translated from bus address space to
- system physical address space using translation tables compliant to
- Armv8/Armv7 VMSA descriptor format.
-- Protection: An I/O device can be prohibited from read, write access to a
- memory region or allowed.
-- Isolation: Traffic from each individial device can be independently managed.
- The devices are differentiated from each other using unique translation
- tables.
-
-The following diagram illustrates a typical SMMU IP integrated in a SoC with
-several I/O devices along with Interconnect and Memory system.
-
-.. image:: ../resources/diagrams/MMU-600.png
-
-SMMU has several versions including SMMUv1, SMMUv2 and SMMUv3. Hafnium provides
-support for SMMUv3 driver in both normal and secure world. A brief introduction
-of SMMUv3 functionality and the corresponding software support in Hafnium is
-provided here.
-
-SMMUv3 features
----------------
-
-- SMMUv3 provides Stage1, Stage2 translation as well as nested (Stage1 + Stage2)
- translation support. It can either bypass or abort incoming translations as
- well.
-- Traffic (memory transactions) from each upstream I/O peripheral device,
- referred to as Stream, can be independently managed using a combination of
- several memory based configuration structures. This allows the SMMUv3 to
- support a large number of streams with each stream assigned to a unique
- translation context.
-- Support for Armv8.1 VMSA where the SMMU shares the translation tables with
- a Processing Element. AArch32(LPAE) and AArch64 translation table format
- are supported by SMMUv3.
-- SMMUv3 offers non-secure stream support with secure stream support being
- optional. Logically, SMMUv3 behaves as if there is an indepdendent SMMU
- instance for secure and non-secure stream support.
-- It also supports sub-streams to differentiate traffic from a virtualized
- peripheral associated with a VM/SP.
-- Additionally, SMMUv3.2 provides support for PEs implementing Armv8.4-A
- extensions. Consequently, SPM depends on Secure EL2 support in SMMUv3.2
- for providing Secure Stage2 translation support to upstream peripheral
- devices.
-
-SMMUv3 Programming Interfaces
------------------------------
-
-SMMUv3 has three software interfaces that are used by the Hafnium driver to
-configure the behaviour of SMMUv3 and manage the streams.
-
-- Memory based data strutures that provide unique translation context for
- each stream.
-- Memory based circular buffers for command queue and event queue.
-- A large number of SMMU configuration registers that are memory mapped during
- boot time by Hafnium driver. Except a few registers, all configuration
- registers have independent secure and non-secure versions to configure the
- behaviour of SMMUv3 for translation of secure and non-secure streams
- respectively.
-
-Peripheral device manifest
---------------------------
-
-Currently, SMMUv3 driver in Hafnium only supports dependent peripheral devices.
-These devices are dependent on PE endpoint to initiate and receive memory
-management transactions on their behalf. The acccess to the MMIO regions of
-any such device is assigned to the endpoint during boot. Moreover, SMMUv3 driver
-uses the same stage 2 translations for the device as those used by partition
-manager on behalf of the PE endpoint. This ensures that the peripheral device
-has the same visibility of the physical address space as the endpoint. The
-device node of the corresponding partition manifest (refer to `[1]`_ section 3.2
-) must specify these additional properties for each peripheral device in the
-system :
-
-- smmu-id: This field helps to identify the SMMU instance that this device is
- upstream of.
-- stream-ids: List of stream IDs assigned to this device.
-
-.. code:: shell
-
- smmuv3-testengine {
- base-address = <0x00000000 0x2bfe0000>;
- pages-count = <32>;
- attributes = <0x3>;
- smmu-id = <0>;
- stream-ids = <0x0 0x1>;
- interrupts = <0x2 0x3>, <0x4 0x5>;
- exclusive-access;
- };
-
-SMMUv3 driver limitations
--------------------------
-
-The primary design goal for the Hafnium SMMU driver is to support secure
-streams.
-
-- Currently, the driver only supports Stage2 translations. No support for
- Stage1 or nested translations.
-- Supports only AArch64 translation format.
-- No support for features such as PCI Express (PASIDs, ATS, PRI), MSI, RAS,
- Fault handling, Performance Monitor Extensions, Event Handling, MPAM.
-- No support for independent peripheral devices.
-
-S-EL0 Partition support
-=======================
-The SPMC (Hafnium) has limited capability to run S-EL0 FF-A partitions using
-FEAT_VHE (mandatory with ARMv8.1 in non-secure state, and in secure world
-with ARMv8.4 and FEAT_SEL2).
-
-S-EL0 partitions are useful for simple partitions that don't require full
-Trusted OS functionality. It is also useful to reduce jitter and cycle
-stealing from normal world since they are more lightweight than VMs.
-
-S-EL0 partitions are presented, loaded and initialized the same as S-EL1 VMs by
-the SPMC. They are differentiated primarily by the 'exception-level' property
-and the 'execution-ctx-count' property in the SP manifest. They are host apps
-under the single EL2&0 Stage-1 translation regime controlled by the SPMC and
-call into the SPMC through SVCs as opposed to HVCs and SMCs. These partitions
-can use FF-A defined services (FFA_MEM_PERM_*) to update or change permissions
-for memory regions.
-
-S-EL0 partitions are required by the FF-A specification to be UP endpoints,
-capable of migrating, and the SPMC enforces this requirement. The SPMC allows
-a S-EL0 partition to accept a direct message from secure world and normal world,
-and generate direct responses to them.
-All S-EL0 partitions must use AArch64. AArch32 S-EL0 partitions are not supported.
-
-Memory sharing, indirect messaging, and notifications functionality with S-EL0
-partitions is supported.
-
-Interrupt handling is not supported with S-EL0 partitions and is work in
-progress.
References
==========
@@ -1641,8 +242,7 @@
.. _[3]:
-[3] `Trusted Boot Board Requirements
-Client <https://developer.arm.com/documentation/den0006/d/>`__
+[3] https://hafnium.readthedocs.io/en/latest/secure-partition-manager/secure-partition-manager.html#secure-partitions-layout-file
.. _[4]:
@@ -1650,23 +250,15 @@
.. _[5]:
-[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+[5] https://hafnium.readthedocs.io/en/latest/secure-partition-manager/index.html
.. _[6]:
-[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/ffa-manifest-binding.html
+[6] :ref:`EL3 Secure Partition Manager<EL3 Secure Partition Manager>`
.. _[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://lists.trustedfirmware.org/archives/list/tf-a@lists.trustedfirmware.org/thread/CFQFGU6H2D5GZYMUYGTGUSXIU3OYZP6U/
-
-.. _[9]:
-
-[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
+[7] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
--------------
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 6147c1f..7af2eae 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -833,6 +833,9 @@
- ``ERRATA_X4_2763018``: This applies errata 2763018 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+- ``ERRATA_X4_2816013``: This applies errata 2816013 workaround to Cortex-X4
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+
For Cortex-A510, the following errata build flags are defined :
- ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to
@@ -929,6 +932,10 @@
For Cortex-A720, the following errata build flags are defined :
+- ``ERRATA_A720_2844092``: This applies errata 2844092 workaround to
+ Cortex-A720 CPU. This needs to be enabled for revisions r0p0 and r0p1.
+ It is fixed in r0p2.
+
- ``ERRATA_A720_2926083``: This applies errata 2926083 workaround to
Cortex-A720 CPU. This needs to be enabled for revisions r0p0 and r0p1.
It is fixed in r0p2.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index c9c92fd..2e33911 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -23,8 +23,9 @@
is expected to contain a makefile called ``<aarch32_sp-value>.mk``.
- ``AMU_RESTRICT_COUNTERS``: Register reads to the group 1 counters will return
- zero at all but the highest implemented exception level. Reads from the
- memory mapped view are unaffected by this control.
+ zero at all but the highest implemented exception level. External
+ memory-mapped debug accesses are unaffected by this control.
+ The default value is 1 for all platforms.
- ``ARCH`` : Choose the target build architecture for TF-A. It can take either
``aarch64`` or ``aarch32`` as values. By default, it is defined to
@@ -98,6 +99,10 @@
file that contains the BL32 private key in PEM format or a PKCS11 URI. If
``SAVE_KEYS=1``, only a file is accepted and it will be used to save the key.
+- ``RMM``: This is an optional build option used when ``ENABLE_RME`` is set.
+ It specifies the path to RMM binary for the ``fip`` target. If the RMM option
+ is not specified, TF-A builds the TRP to load and run at R-EL2.
+
- ``BL33``: Path to BL33 image in the host file system. This is mandatory for
``fip`` target in case TF-A BL2 is used.
@@ -346,6 +351,13 @@
This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
+- ``ENABLE_FEAT_FGT2``: Numeric value to enable support for FGT2
+ (Fine Grain Traps 2) feature allowing for access to Fine-grained trap 2 registers
+ during EL2 to EL3 context save/restore operations.
+ Its an optional architectural feature and is available from v8.8 and upwards.
+ This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
+ mechanism. Default value is ``0``.
+
- ``ENABLE_FEAT_HCX``: Numeric value to set the bit SCR_EL3.HXEn in EL3 to
allow access to HCRX_EL2 (extended hypervisor control register) from EL2 as
well as adding HCRX_EL2 to the EL2 context save/restore operations. Its a
diff --git a/docs/license.rst b/docs/license.rst
index 8996105..9e0298b 100644
--- a/docs/license.rst
+++ b/docs/license.rst
@@ -93,9 +93,27 @@
- ``include/lib/dice/dice.h``
+- Some source files originating from the `pydevicetree`_ project.
+ These files are licensed under the Apache License, Version 2.0, which is a
+ permissive license compatible with BSD-3-Clause. Any contributions to this
+ code must also be made under the terms of `Apache License 2.0`_.
+ These files are:
+
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py``
+
+
.. _FreeBSD: http://www.freebsd.org
.. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT
.. _SCC: http://www.simple-cc.org/
.. _Open Profile for DICE: https://pigweed.googlesource.com/open-dice/
.. _Apache License 2.0: https://www.apache.org/licenses/LICENSE-2.0.txt
-
+.. _pydevicetree: https://pypi.org/project/pydevicetree/
diff --git a/docs/plat/xilinx-versal-net.rst b/docs/plat/xilinx-versal-net.rst
index e9dd772..d22a46d 100644
--- a/docs/plat/xilinx-versal-net.rst
+++ b/docs/plat/xilinx-versal-net.rst
@@ -75,7 +75,7 @@
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
-PM SMC call ranges
+PM SMC call ranges for SiP SVC version 0.1
--------------------------------------------------------
+---------------------------+---------------------------------------------------------------------------+
@@ -84,6 +84,19 @@
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
+PM SMC call ranges for SiP SVC version 0.2
+--------------------------------------------------------
+
++---------------------------+---------------------------------------------------------------------------+
+| SMC Function Identifier | Service type |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000FFF | Fast SMC64 SiP Service call used for pass-through of AMD-Xilinx Platform |
+| | Management APIs to firmware |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000A00-0xc2000AFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+| | specific TF-A APIs |
++---------------------------+---------------------------------------------------------------------------+
+
SMC function IDs for SiP Service queries
----------------------------------------------
diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst
index 072329a..7185d91 100644
--- a/docs/plat/xilinx-versal.rst
+++ b/docs/plat/xilinx-versal.rst
@@ -14,11 +14,6 @@
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31
```
-To build ATF for different platform (supported are "silicon"(default) and "versal_virt")
-```bash
-make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31
-```
-
To build bl32 TSP you have to rebuild bl31 too
```bash
make CROSS_COMPILE=aarch64-none-elf- PLAT=versal SPD=tspd RESET_TO_BL31=1 bl31 bl32
@@ -51,11 +46,6 @@
- `pl011`, `pl011_0`: ARM pl011 UART 0
- `pl011_1` : ARM pl011 UART 1
-* `VERSAL_PLATFORM`: Select the platform. Options:
- - `versal_virt` : Versal Virtual platform
- - `spp_itr6` : SPP ITR6
- - `emu_itr6` : EMU ITR6
-
* `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
secondary cores on receiving power down callback from
firmware. Options:
@@ -98,8 +88,8 @@
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
-PM SMC call ranges
-------------------
+PM SMC call ranges for SiP SVC version 0.1
+--------------------------------------------------------
+---------------------------+---------------------------------------------------------------------------+
| SMC Function Identifier | Service type |
@@ -107,6 +97,19 @@
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
+PM SMC call ranges for SiP SVC version 0.2
+--------------------------------------------------------
+
++---------------------------+---------------------------------------------------------------------------+
+| SMC Function Identifier | Service type |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000FFF | Fast SMC64 SiP Service call used for pass-through of AMD-Xilinx Platform |
+| | Management APIs to firmware |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000A00-0xc2000AFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+| | specific TF-A APIs |
++---------------------------+---------------------------------------------------------------------------+
+
SMC function IDs for SiP Service queries
----------------------------------------
diff --git a/docs/tools/cot-dt2c.rst b/docs/tools/cot-dt2c.rst
new file mode 100644
index 0000000..7b7e56f
--- /dev/null
+++ b/docs/tools/cot-dt2c.rst
@@ -0,0 +1,149 @@
+TF-A CoT dt2c Tool
+==================
+
+This tool is used to automatically generate the corresponding c file for a
+CoT DT file. Since currently TF-A support two type of CoT file: static c file
+and CoT DT binding. This is error prone and hard to maintain, therefore this
+tool can generate the c file for the platform that does not support CoT DT
+binding, given the CoT DT file so the c file can be deprecated.
+
+Prerequisites
+~~~~~~~~~~~~~
+
+#. Python (3.8 or later)
+#. `Poetry`_ Python package manager
+
+
+Getting Started
+~~~~~~~~~~~~~~~
+
+#. Install the tool
+
+ .. code::
+
+ make install
+
+
+#. Verify that the tool runs correctly
+
+ .. code::
+
+ make test
+
+
+#. Usage of the tool
+
+ .. code::
+
+ cot-dt2c
+
+ This command will output the following as usage for this command
+
+ .. code-block:: text
+
+ Usage: cot-dt2c [OPTIONS] COMMAND [ARGS]...
+
+ Options:
+ --version Show the version and exit.
+ --help Show this message and exit.
+
+ Commands:
+ convert-to-c
+ validate-cot
+ visualize-cot
+ validate-dt
+
+#. Uninstall the tool
+ .. code::
+
+ make uninstall
+
+ This command will uninstall the tool
+
+
+#. Uninstall the tool and clean all the build file
+ .. code::
+
+ make clean
+
+ This command will clean all the build file and implicitly uninstall the tool
+
+
+#. Call the make file from TF-A root directory
+ .. code::
+
+ make -C tools/cot-dt2c install
+ make -C tools/cot-dt2c uninstall
+ make -C tools/cot-dt2c clean
+
+Convert CoT descriptors to C file
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To convert the CoT descriptors
+
+This command is for the platform that does not use CoT DT parser,
+which can generate the C file given the CoT descriptors. Before
+the conversion to C file, the tool will do an implicit checks on
+the validity of the CoT DT file.
+
+.. code::
+
+ cot-dt2c convert-to-c [INPUT DTB PATH] [OUTPUT C PATH]
+ cot-dt2c convert-to-c fdts/tbbr_cot_descriptors.dtsi test.c
+
+
+Validate CoT descriptors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To validate the certificate
+
+The tests folder in the tool folder provides some bad-example of the
+DT file, and the tool will print out "not a valid CoT DT file" on console.
+
+The command will check the format of the CoT file
+
+#. The open bracket
+#. The open ifdef macro
+#. The missing mandatory attribute
+#. Malformed DT file (cert missing parent, missing root certs. etc.)
+
+Currently the validation is specifically for checking the CoT DT file
+
+.. code::
+
+ cot-dt2c validate-cot [INPUT DTB PATH]
+ cot-dt2c validate-cot fdts/tbbr_cot_descriptors.dtsi
+
+
+Visualize CoT descriptors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This command create a HTML to visualize the relationship between
+the certificates and the image of a CoT DT file.
+
+.. code::
+
+ cot-dt2c visualize-cot [INPUT DTB PATH]
+ cot-dt2c visualize-cot fdts/tbbr_cot_descriptors.dtsi
+
+
+Validate Other DT files
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The command will transform the dtsi/dts file into a more standard
+dtsi/dts file inside /tmp folder that can be used as input to dt-schema
+for further validation. Currently the tool will perform some basic validation
+for the file (syntax) and dt-schema can be used for advance checks. dt-schema
+is not installed along with the tool.
+
+.. code::
+
+ cot-dt2c validate-dt [INPUT DTS PATH or INPUT DTS folder]
+ cot-dt2c validate-dt fdts/
+ cot-dt2c validate-dt fdts/fvp-bsae-gicv3.dtsi
+
+--------------
+
+*Copyright (c) 2024, Arm Limited. All rights reserved.*
+
+.. _Poetry: https://python-poetry.org/docs/
diff --git a/docs/tools/index.rst b/docs/tools/index.rst
index 2dee2c0..c0e214a 100644
--- a/docs/tools/index.rst
+++ b/docs/tools/index.rst
@@ -6,7 +6,9 @@
:caption: Contents
memory-layout-tool
+ transfer-list-compiler
+ cot-dt2c
--------------
-*Copyright (c) 2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2023-2024, Arm Limited. All rights reserved.*
diff --git a/docs/tools/transfer-list-compiler.rst b/docs/tools/transfer-list-compiler.rst
new file mode 100644
index 0000000..fa660dc
--- /dev/null
+++ b/docs/tools/transfer-list-compiler.rst
@@ -0,0 +1,311 @@
+Transfer List Compiler
+======================
+
+The Transfer List Compiler (tlc) is a host tool used by TF-A to generate transfer
+lists compliant with the v0.9 of the `Firmware Handoff specification`_. It enables
+developers to statically generate transfer list blobs containing any number of
+transfer entries.
+
+Getting Started
+~~~~~~~~~~~~~~~
+
+``tlc`` is installed by default with TF-A's poetry environment. All of it's
+dependencies are listed in `tools/tlc/pyproject.toml`_.
+
+To install ``tlc`` seperately, run the following command:
+
+.. code::
+
+ make -C tools/tlc install
+
+Creating a Transfer List
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+To create an empty TL, you can use the ``create`` command.
+
+.. code::
+
+ tlc create tl.bin
+
+This commands generates a binary blob representing an empty TL, shown in the
+hexdump below.
+
+.. code::
+
+ $ hexdump tl.bin | head
+ 0000000 b10b 4a0f 01a6 0318 0018 0000 1000 0000
+ 0000010 0001 0000 0000 0000
+
+A common use-case this tool supports is the addition of TE's via the option
+``--entry``. This takes as input the tag ID and path to a binary blob to be
+included in the transfer list. The snippet below shows how to include an FDT in
+the TL.
+
+.. code::
+
+ tlc create --entry 1 fdt.dtb tl.bin
+
+Alternatively, addition of a device tree is supported through the option
+``--fdt``. This has the same effect as passing the device tree and it's tag ID
+through the ``--entry`` option.
+
+.. code::
+
+ tlc create --fdt fdt.dtb tl.bin
+
+.. note::
+
+ ``tlc`` makes no effort to verify the contents of a binary blob against the
+ provided tag ID. It only checks that the tags provided as input are within
+ range and that there is sufficient memory to include their TE's.
+
+You can also create a TL from a YAML config file.
+
+.. code ::
+
+ tlc create --from-yaml config.yaml tl.bin
+
+Printing the contents of a TL
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Support is provided for dumping the contents of a TL via the ``info`` command.
+This prints the header of the TL and all included TE's.
+
+.. code::
+
+ $ tlc info tl.bin
+ signature 0x4a0fb10b
+ checksum 0xe1
+ version 0x1
+ hdr_size 0x18
+ alignment 0x3
+ size 0x2a6f
+ total_size 0x4e20
+ flags 0x1
+ ----
+ id 0x1
+ data_size 0x2a47
+ hdr_size 0x8
+ offset 0x18
+ ----
+ id 0x0
+ data_size 0x0
+ hdr_size 0x8
+ offset 0x2a68
+
+The example above shows the dump produced by ``tlc`` for a 20Kb TL containing a
+device tree (tag_id=1) and a NULL entry (tag_id=0).
+
+Modifying the contents of an existing TL
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`tlc` supports removal of one or more entries from a TL through the ``remove``
+command. It takes as argument the filename, and one or more tag ID's, passed
+through the ``--tags`` option. It produces a valid TL blob without those
+entries.
+
+
+For example, using the same blob as in the section above, we can remove the FDT
+TE with the command.
+
+.. code::
+
+ $ tlc remove --tags 1 tl.bin
+
+Using the ``info`` command, shows the the TE has been remove:
+
+.. code::
+
+ $ tlc info tl.bin
+
+ signature 0x4a0fb10b
+ checksum 0x38
+ version 0x1
+ hdr_size 0x18
+ alignment 0x3
+ size 0x20
+ total_size 0x4e20
+ flags 0x1
+ ----
+ id 0x0
+ data_size 0x0
+ hdr_size 0x8
+ offset 0x18
+
+Note that more than one entry can be removed at a time. The ``--tags`` option
+accepts multiple tag ID's.
+
+Conversely, TE's can be added to an existing TL. This is achieved through the
+`add` command.
+
+.. code::
+
+ $ tlc add --entry 1 fdt.dtb tl.bin
+
+
+The result of this modification is shown below:
+
+.. code::
+
+ $ tlc info tl.bin
+
+ signature 0x4a0fb10b
+ checksum 0xe1
+ version 0x1
+ hdr_size 0x18
+ alignment 0x3
+ size 0x2a6f
+ total_size 0x4e20
+ flags 0x1
+ ----
+ id 0x0
+ data_size 0x0
+ hdr_size 0x8
+ offset 0x18
+ ----
+ id 0x1
+ data_size 0x2a47
+ hdr_size 0x8
+ offset 0x20
+
+Unpacking a Transfer List
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Given a transfer list, ``tlc`` also provides a mechanism for extracting TE data.
+Running the command ``unpack``, yields binary files containing data from all the TE's.
+
+.. code::
+
+ $ tlc create --size 20000 --fdt build/fvp/debug/fdts/fvp-base-gicv3-psci.dtb tl.bin
+ $ tlc unpack tl.bin
+ $ file te_1.bin
+ te_1.bin: Device Tree Blob version 17, size=10823, boot CPU=0, string block size=851, DT structure block size=9900
+
+Validate a Transfer List
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+``tlc validate`` provides a quick and simple mechanism for checking wether the TL
+is compliant with version of the specification supported by the tool. It
+performs the following checks:
+
+#. Validates the signature.
+#. Ensures that the specified version is greater than or equal to the tool’s current version.
+#. Verifies alignment criteria for all TE’s.
+
+YAML Config File Format
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Example YAML config file:
+
+.. code::
+
+ execution_state: aarch32
+ has_checksum: true
+ max_size: 4096
+ entries:
+ - tag_id: 258 # entry point info
+ ep_info:
+ args:
+ - 67112968
+ - 67112960
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ h:
+ attr: 8
+ type: 1
+ version: 2
+ pc: 67239936
+ spsr: 467
+ - tag_id: 3 # memory layout
+ addr: 8
+ size: 8
+ - tag_id: 1, # fdt
+ blob_file_path: "fdt.bin",
+
+`max_size` defaults to `0x1000`, `execution_state` defaults to `aarch64`, and `has_checksum`
+defaults to `true`.
+
+The fields of the YAML file should match the fields in the specification for the transfer list. You
+don't need to give the hdr_size or data_size fields. For example, a memory layout entry would have
+an entry like:
+
+.. code::
+
+ tag_id: 3
+ addr: 8
+ size: 8
+
+You can input blob files by giving paths to the current working directory. You can do this for any
+TE type. For example, an FDT layout would have an entry like:
+
+.. code::
+
+ tag_id: 1,
+ blob_file_path: "fdt.bin",
+
+You can input C-types by giving its fields. For example, an entry point
+info entry would have an entry like:
+
+.. code::
+
+ tag_id: 258
+ ep_info:
+ args:
+ - 67112968
+ - 67112960
+ - 0
+ - 0
+ h:
+ attr: 8
+ type: 1
+ version: 2
+ lr_svc: 0
+ pc: 67239936
+ spsr: 467
+
+You can give the name of the tag instead of the tag id number. The valid tag names are in the
+`transfer_entry_formats` dict in `tools/tlc/tlc/tl.py`_. Some examples are:
+
+* empty
+* fdt
+* hob_block
+* hob_list
+
+You can input the attr field of entry_point_info as a string of flag
+names separated by `|`. The names are taken from ep_info_exp.h in TF-A.
+For example:
+
+.. code::
+
+ has_checksum: true
+ max_size: 4096
+ entries:
+ - tag_id: 0x102
+ ep_info:
+ args:
+ - 67112976
+ - 67112960
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ h:
+ attr: EP_NON_SECURE | EP_ST_ENABLE
+ type: 1
+ version: 2
+ pc: 67239936
+ spsr: 965
+
+--------------
+
+*Copyright (c) 2024, Arm Limited. All rights reserved.*
+
+.. _Firmware Handoff specification: https://github.com/FirmwareHandoff/firmware_handoff/
+.. _tools/tlc/pyproject.toml: https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/heads/master/tools/tlc/pyproject.toml
+.. _tools/tlc/tlc/tl.py: https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/heads/master/tools/tlc/tlc/tl.py
diff --git a/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/arm/gic/v3/arm_gicv3_common.c
index 4489892..cc82ddb 100644
--- a/drivers/arm/gic/v3/arm_gicv3_common.c
+++ b/drivers/arm/gic/v3/arm_gicv3_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -28,10 +28,13 @@
void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
{
uintptr_t gicr_base = 0;
+ unsigned int typer_reg;
assert(gicv3_driver_data);
assert(gicv3_driver_data->rdistif_base_addrs);
+ assert(gicv3_driver_data->gicd_base != 0U);
+ typer_reg = gicd_read_typer(gicv3_driver_data->gicd_base);
/*
* The GICR_WAKER.Sleep bit should be set only when both
* GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
@@ -60,9 +63,14 @@
*/
gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
- /* Wait until the GICR_WAKER.Quiescent bit is set */
- while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
- ;
+ /*
+ * If LPIs are supported, wait until the GICR_WAKER.Quiescent bit is
+ * set.
+ */
+ if ((typer_reg & TYPER_LPIS) != 0U) {
+ while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
+ ;
+ }
}
/*
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 8ea164c..2be19db 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -686,6 +686,8 @@
gicr_write_ctlr(gicr_base,
rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT));
+ gicr_wait_for_pending_write(gicr_base);
+
/* Restore registers' content */
gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser);
gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser);
diff --git a/drivers/auth/cca/bl1_cot.c b/drivers/auth/cca/bl1_cot.c
new file mode 100644
index 0000000..43cb18a
--- /dev/null
+++ b/drivers/auth/cca/bl1_cot.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <mbedtls/version.h>
+
+#include <common/tbbr/cot_def.h>
+#include <drivers/auth/auth_mod.h>
+#include <platform_def.h>
+#include <tools_share/cca_oid.h>
+
+/*
+ * 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];
+
+/*
+ * Parameter type descriptors.
+ */
+static auth_param_type_desc_t cca_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, CCA_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
+
+/* CCA Content Certificate */
+static const auth_img_desc_t cca_content_cert = {
+ .img_id = CCA_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &cca_nv_ctr,
+ .plat_nv_ctr = &cca_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tb_fw_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tb_fw_config_hash,
+ .data = {
+ .ptr = (void *)tb_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &fw_config_hash,
+ .data = {
+ .ptr = (void *)fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl2_image = {
+ .img_id = BL2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cca_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t tb_fw_config = {
+ .img_id = TB_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &cca_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_config_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t fw_config = {
+ .img_id = FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &cca_content_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
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t * const cot_desc[] = {
+ [CCA_CONTENT_CERT_ID] = &cca_content_cert,
+ [BL2_IMAGE_ID] = &bl2_image,
+ [TB_FW_CONFIG_ID] = &tb_fw_config,
+ [FW_CONFIG_ID] = &fw_config,
+};
+
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/cca/cot.c b/drivers/auth/cca/cot.c
deleted file mode 100644
index 2a03604..0000000
--- a/drivers/auth/cca/cot.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-
-#include <mbedtls/version.h>
-
-#include <common/tbbr/cot_def.h>
-#include <drivers/auth/auth_mod.h>
-#include <tools_share/cca_oid.h>
-
-#include <platform_def.h>
-
-/*
- * 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];
-static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
-static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char rmm_hash_buf[HASH_DER_LEN];
-
-#ifdef IMAGE_BL2
-static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
-#if defined(SPD_spmd)
-static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
-#endif /* SPD_spmd */
-
-static unsigned char core_swd_pk_buf[PK_DER_LEN];
-static unsigned char plat_pk_buf[PK_DER_LEN];
-#endif /* IMAGE_BL2 */
-
-/*
- * Parameter type descriptors.
- */
-static auth_param_type_desc_t cca_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, CCA_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, 0);
-static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG, 0);
-static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG_ALG, 0);
-static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_RAW_DATA, 0);
-
-static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
-static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- 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);
-static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
-static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t rmm_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, RMM_HASH_OID);
-
-#ifdef IMAGE_BL2
-static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
-
-static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, PROT_PK_OID);
-static auth_param_type_desc_t swd_rot_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, SWD_ROT_PK_OID);
-static auth_param_type_desc_t core_swd_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, CORE_SWD_PK_OID);
-static auth_param_type_desc_t plat_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, PLAT_PK_OID);
-
-static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
-static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
-static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
-#if defined(SPD_spmd)
-static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
-static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
-static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
-static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
-static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
-static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
-static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
-static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
-#endif /* SPD_spmd */
-#endif /* IMAGE_BL2 */
-
-/* CCA Content Certificate */
-static const auth_img_desc_t cca_content_cert = {
- .img_id = CCA_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &cca_nv_ctr,
- .plat_nv_ctr = &cca_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tb_fw_hash,
- .data = {
- .ptr = (void *)tb_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tb_fw_config_hash,
- .data = {
- .ptr = (void *)tb_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &fw_config_hash,
- .data = {
- .ptr = (void *)fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &hw_config_hash,
- .data = {
- .ptr = (void *)hw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [4] = {
- .type_desc = &soc_fw_hash,
- .data = {
- .ptr = (void *)soc_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [5] = {
- .type_desc = &soc_fw_config_hash,
- .data = {
- .ptr = (void *)soc_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [6] = {
- .type_desc = &rmm_hash,
- .data = {
- .ptr = (void *)rmm_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-#ifdef IMAGE_BL1
-static const auth_img_desc_t bl2_image = {
- .img_id = BL2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tb_fw_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t tb_fw_config = {
- .img_id = TB_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tb_fw_config_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t fw_config = {
- .img_id = FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_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
-/* HW Config */
-static const auth_img_desc_t hw_config = {
- .img_id = HW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &hw_config_hash
- }
- }
- }
-};
-
-/* BL31 */
-static const auth_img_desc_t bl31_image = {
- .img_id = BL31_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_hash
- }
- }
- }
-};
-
-/* BL31 Config */
-static const auth_img_desc_t soc_fw_config = {
- .img_id = SOC_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_config_hash
- }
- }
- }
-};
-
-/* RMM */
-static const auth_img_desc_t rmm_image = {
- .img_id = RMM_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &rmm_hash
- }
- }
- }
-};
-
-/* Core SWD Key Certificate */
-static const auth_img_desc_t core_swd_key_cert = {
- .img_id = CORE_SWD_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL, /* SWD ROOT CERT */
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &swd_rot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &core_swd_pk,
- .data = {
- .ptr = (void *)core_swd_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-/* SPMC Content Certificate */
-static const auth_img_desc_t trusted_os_fw_content_cert = {
- .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &core_swd_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &core_swd_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tos_fw_hash,
- .data = {
- .ptr = (void *)tos_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tos_fw_config_hash,
- .data = {
- .ptr = (void *)tos_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-/* SPMC */
-static const auth_img_desc_t bl32_image = {
- .img_id = BL32_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_hash
- }
- }
- }
-};
-
-/* SPM Config */
-static const auth_img_desc_t tos_fw_config = {
- .img_id = TOS_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_config_hash
- }
- }
- }
-};
-
-/* Platform Key Certificate */
-static const auth_img_desc_t plat_key_cert = {
- .img_id = PLAT_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL, /* PLATFORM ROOT CERT */
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &prot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &plat_pk,
- .data = {
- .ptr = (void *)plat_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-/* Non-Trusted Firmware */
-static const auth_img_desc_t non_trusted_fw_content_cert = {
- .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &plat_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &plat_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &nt_world_bl_hash,
- .data = {
- .ptr = (void *)nt_world_bl_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &nt_fw_config_hash,
- .data = {
- .ptr = (void *)nt_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl33_image = {
- .img_id = BL33_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_world_bl_hash
- }
- }
- }
-};
-
-/* NT FW Config */
-static const auth_img_desc_t nt_fw_config = {
- .img_id = NT_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_fw_config_hash
- }
- }
- }
-};
-
-/*
- * Secure Partitions
- */
-#if defined(SPD_spmd)
-static const auth_img_desc_t sip_sp_content_cert = {
- .img_id = SIP_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &core_swd_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &core_swd_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg1_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[0],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg2_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[1],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg3_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[2],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg4_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[3],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_SIP_SP_PKG(1);
-DEFINE_SIP_SP_PKG(2);
-DEFINE_SIP_SP_PKG(3);
-DEFINE_SIP_SP_PKG(4);
-
-static const auth_img_desc_t plat_sp_content_cert = {
- .img_id = PLAT_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &plat_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &plat_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg5_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[4],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg6_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[5],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg7_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[6],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg8_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[7],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_PLAT_SP_PKG(5);
-DEFINE_PLAT_SP_PKG(6);
-DEFINE_PLAT_SP_PKG(7);
-DEFINE_PLAT_SP_PKG(8);
-#endif /* SPD_spmd */
-#endif /* IMAGE_BL2 */
-/*
- * Chain of trust definition
- */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t * const cot_desc[] = {
- [CCA_CONTENT_CERT_ID] = &cca_content_cert,
- [BL2_IMAGE_ID] = &bl2_image,
- [TB_FW_CONFIG_ID] = &tb_fw_config,
- [FW_CONFIG_ID] = &fw_config,
-};
-#else /* IMAGE_BL2 */
-static const auth_img_desc_t * const cot_desc[] = {
- [CCA_CONTENT_CERT_ID] = &cca_content_cert,
- [HW_CONFIG_ID] = &hw_config,
- [BL31_IMAGE_ID] = &bl31_image,
- [SOC_FW_CONFIG_ID] = &soc_fw_config,
- [RMM_IMAGE_ID] = &rmm_image,
- [CORE_SWD_KEY_CERT_ID] = &core_swd_key_cert,
- [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
- [BL32_IMAGE_ID] = &bl32_image,
- [TOS_FW_CONFIG_ID] = &tos_fw_config,
- [PLAT_KEY_CERT_ID] = &plat_key_cert,
- [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
- [BL33_IMAGE_ID] = &bl33_image,
- [NT_FW_CONFIG_ID] = &nt_fw_config,
-#if defined(SPD_spmd)
- [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
- [PLAT_SP_CONTENT_CERT_ID] = &plat_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 /* IMAGE_BL1 */
-
-/* Register the CoT in the authentication module */
-REGISTER_COT(cot_desc);
diff --git a/drivers/auth/dualroot/bl1_cot.c b/drivers/auth/dualroot/bl1_cot.c
new file mode 100644
index 0000000..a548170
--- /dev/null
+++ b/drivers/auth/dualroot/bl1_cot.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <mbedtls/version.h>
+
+#include <common/tbbr/cot_def.h>
+#include <drivers/auth/auth_mod.h>
+#include <platform_def.h>
+#include <tools_share/dualroot_oid.h>
+
+/*
+ * 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 scp_fw_hash_buf[HASH_DER_LEN];
+static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+/*
+ * Parameter type descriptors.
+ */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static 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 scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FWU_HASH_OID);
+
+static const auth_img_desc_t trusted_boot_fw_cert = {
+ .img_id = TRUSTED_BOOT_FW_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tb_fw_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tb_fw_config_hash,
+ .data = {
+ .ptr = (void *)tb_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &fw_config_hash,
+ .data = {
+ .ptr = (void *)fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl2_image = {
+ .img_id = BL2_IMAGE_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 = &tb_fw_hash
+ }
+ }
+ }
+};
+
+/* TB FW Config */
+static const auth_img_desc_t tb_fw_config = {
+ .img_id = TB_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 = &tb_fw_config_hash
+ }
+ }
+ }
+};
+
+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
+ }
+ }
+ }
+};
+
+/* FWU auth descriptor */
+static const auth_img_desc_t fwu_cert = {
+ .img_id = FWU_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &scp_bl2u_hash,
+ .data = {
+ .ptr = (void *)scp_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &bl2u_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &ns_bl2u_hash,
+ .data = {
+ .ptr = (void *)nt_world_bl_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+/* SCP_BL2U */
+static const auth_img_desc_t scp_bl2u_image = {
+ .img_id = SCP_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &scp_bl2u_hash
+ }
+ }
+ }
+};
+
+/* BL2U */
+static const auth_img_desc_t bl2u_image = {
+ .img_id = BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl2u_hash
+ }
+ }
+ }
+};
+
+/* NS_BL2U */
+static const auth_img_desc_t ns_bl2u_image = {
+ .img_id = NS_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ns_bl2u_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t * const cot_desc[] = {
+ [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
+ [BL2_IMAGE_ID] = &bl2_image,
+ [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,
+ [NS_BL2U_IMAGE_ID] = &ns_bl2u_image
+};
+
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
deleted file mode 100644
index c89930c..0000000
--- a/drivers/auth/dualroot/cot.c
+++ /dev/null
@@ -1,962 +0,0 @@
-/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-
-#include <mbedtls/version.h>
-
-#include <common/tbbr/cot_def.h>
-#include <drivers/auth/auth_mod.h>
-
-#include <tools_share/dualroot_oid.h>
-
-#include <platform_def.h>
-
-/*
- * 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];
-static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
-static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
-
-#ifdef IMAGE_BL2
-static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
-static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
-#if defined(SPD_spmd)
-static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
-#endif /* SPD_spmd */
-
-static unsigned char trusted_world_pk_buf[PK_DER_LEN];
-static unsigned char content_pk_buf[PK_DER_LEN];
-#endif
-
-/*
- * Parameter type descriptors.
- */
-static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, 0);
-static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG, 0);
-static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG_ALG, 0);
-static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_RAW_DATA, 0);
-
-static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
-static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- 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);
-static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
-static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, FWU_HASH_OID);
-#endif /* IMAGE_BL1 */
-
-#ifdef IMAGE_BL2
-static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
-
-static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
-static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, PROT_PK_OID);
-
-static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SCP_FW_HASH_OID);
-static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
-static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
-static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
-static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
-static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
-static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
-#if defined(SPD_spmd)
-static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
-static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
-static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
-static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
-static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
-static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
-static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
-static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
-#endif /* SPD_spmd */
-#endif /* IMAGE_BL2 */
-
-
-/* BL2 */
-static const auth_img_desc_t trusted_boot_fw_cert = {
- .img_id = TRUSTED_BOOT_FW_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tb_fw_hash,
- .data = {
- .ptr = (void *)tb_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tb_fw_config_hash,
- .data = {
- .ptr = (void *)tb_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &hw_config_hash,
- .data = {
- .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
- }
- }
- }
-};
-
-#ifdef IMAGE_BL1
-static const auth_img_desc_t bl2_image = {
- .img_id = BL2_IMAGE_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 = &tb_fw_hash
- }
- }
- }
-};
-#endif /* IMAGE_BL1 */
-
-/* HW Config */
-static const auth_img_desc_t hw_config = {
- .img_id = HW_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 = &hw_config_hash
- }
- }
- }
-};
-
-/* TB FW Config */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t tb_fw_config = {
- .img_id = TB_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 = &tb_fw_config_hash
- }
- }
- }
-};
-
-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
-/* Trusted key certificate */
-static const auth_img_desc_t trusted_key_cert = {
- .img_id = TRUSTED_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &trusted_world_pk,
- .data = {
- .ptr = (void *)trusted_world_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- },
- }
-};
-
-/* SCP Firmware */
-static const auth_img_desc_t scp_fw_key_cert = {
- .img_id = SCP_FW_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &scp_fw_content_pk,
- .data = {
- .ptr = (void *)content_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t scp_fw_content_cert = {
- .img_id = SCP_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &scp_fw_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &scp_fw_content_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &scp_fw_hash,
- .data = {
- .ptr = (void *)scp_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t scp_bl2_image = {
- .img_id = SCP_BL2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &scp_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &scp_fw_hash
- }
- }
- }
-};
-
-/* SoC Firmware */
-static const auth_img_desc_t soc_fw_key_cert = {
- .img_id = SOC_FW_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &soc_fw_content_pk,
- .data = {
- .ptr = (void *)content_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t soc_fw_content_cert = {
- .img_id = SOC_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &soc_fw_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &soc_fw_content_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &soc_fw_hash,
- .data = {
- .ptr = (void *)soc_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &soc_fw_config_hash,
- .data = {
- .ptr = (void *)soc_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl31_image = {
- .img_id = BL31_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &soc_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_hash
- }
- }
- }
-};
-
-/* SOC FW Config */
-static const auth_img_desc_t soc_fw_config = {
- .img_id = SOC_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &soc_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_config_hash
- }
- }
- }
-};
-
-/* Trusted OS Firmware */
-static const auth_img_desc_t trusted_os_fw_key_cert = {
- .img_id = TRUSTED_OS_FW_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tos_fw_content_pk,
- .data = {
- .ptr = (void *)content_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t trusted_os_fw_content_cert = {
- .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_os_fw_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &tos_fw_content_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tos_fw_hash,
- .data = {
- .ptr = (void *)tos_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tos_fw_extra1_hash,
- .data = {
- .ptr = (void *)tos_fw_extra1_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &tos_fw_extra2_hash,
- .data = {
- .ptr = (void *)tos_fw_extra2_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &tos_fw_config_hash,
- .data = {
- .ptr = (void *)tos_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl32_image = {
- .img_id = BL32_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t bl32_extra1_image = {
- .img_id = BL32_EXTRA1_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_extra1_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t bl32_extra2_image = {
- .img_id = BL32_EXTRA2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_extra2_hash
- }
- }
- }
-};
-
-/* TOS FW Config */
-static const auth_img_desc_t tos_fw_config = {
- .img_id = TOS_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_config_hash
- }
- }
- }
-};
-
-/* Non-Trusted Firmware */
-static const auth_img_desc_t non_trusted_fw_content_cert = {
- .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL, /* Root certificate. */
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &prot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &nt_world_bl_hash,
- .data = {
- .ptr = (void *)nt_world_bl_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &nt_fw_config_hash,
- .data = {
- .ptr = (void *)nt_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl33_image = {
- .img_id = BL33_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_world_bl_hash
- }
- }
- }
-};
-
-/* NT FW Config */
-static const auth_img_desc_t nt_fw_config = {
- .img_id = NT_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_fw_config_hash
- }
- }
- }
-};
-
-/*
- * Secure Partitions
- */
-#if defined(SPD_spmd)
-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]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg1_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[0],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg2_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[1],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg3_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[2],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg4_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[3],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_SIP_SP_PKG(1);
-DEFINE_SIP_SP_PKG(2);
-DEFINE_SIP_SP_PKG(3);
-DEFINE_SIP_SP_PKG(4);
-
-static const auth_img_desc_t plat_sp_content_cert = {
- .img_id = PLAT_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &prot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg5_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[4],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg6_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[5],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg7_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[6],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg8_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[7],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_PLAT_SP_PKG(5);
-DEFINE_PLAT_SP_PKG(6);
-DEFINE_PLAT_SP_PKG(7);
-DEFINE_PLAT_SP_PKG(8);
-#endif /* SPD_spmd */
-
-#else /* IMAGE_BL2 */
-
-/* FWU auth descriptor */
-static const auth_img_desc_t fwu_cert = {
- .img_id = FWU_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &scp_bl2u_hash,
- .data = {
- .ptr = (void *)scp_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &bl2u_hash,
- .data = {
- .ptr = (void *)tb_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &ns_bl2u_hash,
- .data = {
- .ptr = (void *)nt_world_bl_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-/* SCP_BL2U */
-static const auth_img_desc_t scp_bl2u_image = {
- .img_id = SCP_BL2U_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &fwu_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &scp_bl2u_hash
- }
- }
- }
-};
-
-/* BL2U */
-static const auth_img_desc_t bl2u_image = {
- .img_id = BL2U_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &fwu_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &bl2u_hash
- }
- }
- }
-};
-
-/* NS_BL2U */
-static const auth_img_desc_t ns_bl2u_image = {
- .img_id = NS_BL2U_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &fwu_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &ns_bl2u_hash
- }
- }
- }
-};
-#endif /* IMAGE_BL2 */
-
-/*
- * Chain of trust definition
- */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t * const cot_desc[] = {
- [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
- [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,
- [NS_BL2U_IMAGE_ID] = &ns_bl2u_image
-};
-#else /* IMAGE_BL2 */
-static const auth_img_desc_t * const cot_desc[] = {
- [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
- [HW_CONFIG_ID] = &hw_config,
- [TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
- [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert,
- [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert,
- [SCP_BL2_IMAGE_ID] = &scp_bl2_image,
- [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert,
- [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert,
- [BL31_IMAGE_ID] = &bl31_image,
- [SOC_FW_CONFIG_ID] = &soc_fw_config,
- [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert,
- [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
- [BL32_IMAGE_ID] = &bl32_image,
- [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image,
- [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image,
- [TOS_FW_CONFIG_ID] = &tos_fw_config,
- [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
- [BL33_IMAGE_ID] = &bl33_image,
- [NT_FW_CONFIG_ID] = &nt_fw_config,
-#if defined(SPD_spmd)
- [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
- [PLAT_SP_CONTENT_CERT_ID] = &plat_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
-
-/* Register the CoT in the authentication module */
-REGISTER_COT(cot_desc);
diff --git a/drivers/auth/mbedtls/mbedtls_psa_crypto.c b/drivers/auth/mbedtls/mbedtls_psa_crypto.c
index 2da97dc..53f8adf 100644
--- a/drivers/auth/mbedtls/mbedtls_psa_crypto.c
+++ b/drivers/auth/mbedtls/mbedtls_psa_crypto.c
@@ -104,242 +104,84 @@
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
-static void construct_psa_key_alg_and_type(mbedtls_pk_type_t pk_alg,
- mbedtls_md_type_t md_alg,
- psa_ecc_family_t psa_ecc_family,
- psa_algorithm_t *psa_alg,
- psa_key_type_t *psa_key_type)
-{
- psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
-
- switch (pk_alg) {
- case MBEDTLS_PK_RSASSA_PSS:
- *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
- *psa_key_type = PSA_KEY_TYPE_RSA_PUBLIC_KEY;
- break;
- case MBEDTLS_PK_ECDSA:
- *psa_alg = PSA_ALG_ECDSA(psa_md_alg);
- *psa_key_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(psa_ecc_family);
- break;
- default:
- *psa_alg = PSA_ALG_NONE;
- *psa_key_type = PSA_KEY_TYPE_NONE;
- break;
- }
-}
-
-
-#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
-TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
-
/*
- * This is a helper function to detect padding byte (if the MSB bit of the
- * first data byte is set to 1, for example 0x80) and on detection, ignore the
- * padded byte(0x00) and increase the buffer pointer beyond padded byte and
- * decrease the length of the buffer by 1.
- *
- * On Success returns 0, error otherwise.
- **/
-static inline int ignore_asn1_int_padding_byte(unsigned char **buf_start,
- size_t *buf_len)
-{
- unsigned char *local_buf = *buf_start;
-
- /* Check for negative number */
- if ((local_buf[0] & 0x80U) != 0U) {
- return -1;
- }
-
- if ((local_buf[0] == 0U) && (local_buf[1] > 0x7FU) &&
- (*buf_len > 1U)) {
- *buf_start = &local_buf[1];
- (*buf_len)--;
- }
-
- return 0;
-}
+ * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has
+ * advised that it's better to copy out the declaration than it would be to
+ * update to 3.5.2, where this function is exposed.
+ */
+int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid,
+ const mbedtls_x509_buf *sig_params,
+ mbedtls_md_type_t *md_alg,
+ mbedtls_pk_type_t *pk_alg,
+ void **sig_opts);
/*
- * This is a helper function that gets a pointer to the encoded ECDSA publicKey
- * and its length (as per RFC5280) and returns corresponding decoded publicKey
- * and its length. As well, it retrieves the family of ECC key in the PSA
- * format.
- *
- * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
- * otherwise success(0).
- **/
-static int get_ecdsa_pkinfo_from_asn1(unsigned char **pk_start,
- unsigned int *pk_len,
- psa_ecc_family_t *psa_ecc_family)
+ * This is a helper function which parses a SignatureAlgorithm OID.
+ * It extracts the pk algorithm and constructs a psa_algorithm_t object
+ * to be used by PSA calls.
+ */
+static int construct_psa_alg(void *sig_alg, unsigned int sig_alg_len,
+ mbedtls_pk_type_t *pk_alg, psa_algorithm_t *psa_alg)
{
- mbedtls_asn1_buf alg_oid, alg_params;
- mbedtls_ecp_group_id grp_id;
int rc;
- unsigned char *pk_end;
- size_t len;
- size_t curve_bits;
- unsigned char *pk_ptr = *pk_start;
+ mbedtls_md_type_t md_alg;
+ void *sig_opts = NULL;
+ mbedtls_asn1_buf sig_alg_oid, params;
+ unsigned char *p = (unsigned char *) sig_alg;
+ unsigned char *end = (unsigned char *) sig_alg + sig_alg_len;
- pk_end = pk_ptr + *pk_len;
- rc = mbedtls_asn1_get_tag(&pk_ptr, pk_end, &len,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE);
+ rc = mbedtls_asn1_get_alg(&p, end, &sig_alg_oid, ¶ms);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
}
- pk_end = pk_ptr + len;
- rc = mbedtls_asn1_get_alg(&pk_ptr, pk_end, &alg_oid, &alg_params);
+ rc = mbedtls_x509_get_sig_alg(&sig_alg_oid, ¶ms, &md_alg, pk_alg, &sig_opts);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
}
- if (alg_params.tag == MBEDTLS_ASN1_OID) {
- if (mbedtls_oid_get_ec_grp(&alg_params, &grp_id) != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
- *psa_ecc_family = mbedtls_ecc_group_to_psa(grp_id,
- &curve_bits);
- } else {
- return CRYPTO_ERR_SIGNATURE;
- }
+ psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
- pk_end = pk_ptr + len - (alg_oid.len + alg_params.len +
- 2 * (SIZE_OF_ASN1_LEN + SIZE_OF_ASN1_TAG));
- rc = mbedtls_asn1_get_bitstring_null(&pk_ptr, pk_end, &len);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ switch (*pk_alg) {
+ case MBEDTLS_PK_RSASSA_PSS:
+ *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
+ rc = CRYPTO_SUCCESS;
+ break;
+ case MBEDTLS_PK_ECDSA:
+ *psa_alg = PSA_ALG_ECDSA(psa_md_alg);
+ rc = CRYPTO_SUCCESS;
+ break;
+ default:
+ *psa_alg = PSA_ALG_NONE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ break;
}
- *pk_start = pk_ptr;
- *pk_len = len;
-
+end:
+ mbedtls_free(sig_opts);
return rc;
}
/*
- * Ecdsa-Sig-Value ::= SEQUENCE {
- * r INTEGER,
- * s INTEGER
- * }
- *
- * This helper function that gets a pointer to the encoded ECDSA signature and
- * its length (as per RFC5280) and returns corresponding decoded signature
- * (R_S pair) and its size.
- *
- * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
- * otherwise success(0).
- **/
-static int get_ecdsa_signature_from_asn1(unsigned char *sig_ptr,
- size_t *sig_len,
- unsigned char *r_s_pair)
+ * Helper functions for mbedtls PK contexts.
+ */
+static void initialize_pk_context(mbedtls_pk_context *pk, bool *pk_initialized)
{
- int rc;
- unsigned char *sig_end;
- size_t len, r_len, s_len;
-
- sig_end = sig_ptr + *sig_len;
- rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &len,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- sig_end = sig_ptr + len;
- rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &r_len,
- MBEDTLS_ASN1_INTEGER);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- if (ignore_asn1_int_padding_byte(&sig_ptr, &r_len) != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- (void)memcpy((void *)&r_s_pair[0], (const void *)sig_ptr, r_len);
-
- sig_ptr = sig_ptr + r_len;
- sig_end = sig_ptr + len - (r_len + (SIZE_OF_ASN1_LEN +
- SIZE_OF_ASN1_TAG));
- rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &s_len,
- MBEDTLS_ASN1_INTEGER);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- if (ignore_asn1_int_padding_byte(&sig_ptr, &s_len) != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- (void)memcpy((void *)&r_s_pair[r_len], (const void *)sig_ptr, s_len);
-
- *sig_len = s_len + r_len;
-
- return 0;
+ mbedtls_pk_init(pk);
+ *pk_initialized = true;
}
-#endif /*
- * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
- * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
- **/
-/*
- * This is a helper function that adjusts the start of the pk_start to point to
- * the subjectPublicKey bytes within the SubjectPublicKeyInfo block.
- *
- * SubjectPublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * subjectPublicKey BIT STRING }
- *
- * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
- * otherwise success(0).
- **/
-static int pk_bytes_from_subpubkey(unsigned char **pk_start,
- unsigned int *pk_len)
+static void cleanup_pk_context(mbedtls_pk_context *pk, bool *pk_initialized)
{
- mbedtls_asn1_buf alg_oid, alg_params;
- int rc;
- unsigned char *pk_end;
- size_t len;
- unsigned char *pk_ptr = *pk_start;
-
- pk_end = pk_ptr + *pk_len;
- rc = mbedtls_asn1_get_tag(&pk_ptr, pk_end, &len,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- pk_end = pk_ptr + len;
- rc = mbedtls_asn1_get_alg(&pk_ptr, pk_end, &alg_oid, &alg_params);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ if (*pk_initialized) {
+ mbedtls_pk_free(pk);
+ *pk_initialized = false;
}
- pk_end = pk_ptr + len - (alg_oid.len + alg_params.len +
- 2 * (SIZE_OF_ASN1_LEN + SIZE_OF_ASN1_TAG));
- rc = mbedtls_asn1_get_bitstring_null(&pk_ptr, pk_end, &len);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- *pk_start = pk_ptr;
- *pk_len = len;
-
- return rc;
}
/*
- * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has
- * advised that it's better to copy out the declaration than it would be to
- * update to 3.5.2, where this function is exposed.
- */
-int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid,
- const mbedtls_x509_buf *sig_params,
- mbedtls_md_type_t *md_alg,
- mbedtls_pk_type_t *pk_alg,
- void **sig_opts);
-/*
* Verify a signature.
*
* Parameters are passed using the DER encoding format following the ASN.1
@@ -350,141 +192,99 @@
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
- mbedtls_asn1_buf sig_oid, sig_params;
- mbedtls_asn1_buf signature;
- mbedtls_md_type_t md_alg;
- mbedtls_pk_type_t pk_alg;
- int rc;
- void *sig_opts = NULL;
unsigned char *p, *end;
+ mbedtls_pk_context pk;
+ bool pk_initialized = false;
+ int rc = CRYPTO_ERR_SIGNATURE;
+ psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_id_t psa_key_id;
+ mbedtls_pk_type_t pk_alg;
+ psa_algorithm_t psa_alg;
+ __unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0};
unsigned char *local_sig_ptr;
size_t local_sig_len;
- psa_ecc_family_t psa_ecc_family = 0U;
- __unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0};
- /* construct PSA key algo and type */
- psa_status_t status = PSA_SUCCESS;
- psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
- psa_key_id_t psa_key_id = PSA_KEY_ID_NULL;
- psa_key_type_t psa_key_type;
- psa_algorithm_t psa_alg;
+ /* Load the key into the PSA key store. */
+ initialize_pk_context(&pk, &pk_initialized);
- /* Get pointers to signature OID and parameters */
- p = (unsigned char *)sig_alg;
- end = (unsigned char *)(p + sig_alg_len);
- rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
+ p = (unsigned char *) pk_ptr;
+ end = p + pk_len;
+ rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end2;
}
- /* Get the actual signature algorithm (MD + PK) */
- rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
+ rc = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_MESSAGE, &psa_key_attr);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end2;
+ }
+
+ rc = construct_psa_alg(sig_alg, sig_alg_len, &pk_alg, &psa_alg);
+ if (rc != CRYPTO_SUCCESS) {
+ goto end2;
}
+ psa_set_key_algorithm(&psa_key_attr, psa_alg);
- /* Get the signature (bitstring) */
- p = (unsigned char *)sig_ptr;
- end = (unsigned char *)(p + sig_len);
- signature.tag = *p;
- rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
- if ((rc != 0) || ((size_t)(end - p) != signature.len)) {
+ rc = mbedtls_pk_import_into_psa(&pk, &psa_key_attr, &psa_key_id);
+ if (rc != 0) {
rc = CRYPTO_ERR_SIGNATURE;
goto end2;
}
+ /* Optimize mbedtls heap usage by freeing the pk context now. */
+ cleanup_pk_context(&pk, &pk_initialized);
+
+ /* Extract the signature from sig_ptr. */
+ p = (unsigned char *) sig_ptr;
+ end = p + sig_len;
+ rc = mbedtls_asn1_get_bitstring_null(&p, end, &local_sig_len);
+ if (rc != 0) {
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end1;
+ }
local_sig_ptr = p;
- local_sig_len = signature.len;
#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
if (pk_alg == MBEDTLS_PK_ECDSA) {
- rc = get_ecdsa_signature_from_asn1(local_sig_ptr,
- &local_sig_len,
- reformatted_sig);
- if (rc != 0) {
- goto end2;
- }
-
- local_sig_ptr = reformatted_sig;
+ /* Convert the DER ASN.1 signature to raw format. */
+ size_t key_bits = psa_get_key_bits(&psa_key_attr);
- rc = get_ecdsa_pkinfo_from_asn1((unsigned char **)&pk_ptr,
- &pk_len,
- &psa_ecc_family);
+ rc = mbedtls_ecdsa_der_to_raw(key_bits, p, local_sig_len,
+ reformatted_sig, MAX_ECDSA_R_S_PAIR_LEN,
+ &local_sig_len);
if (rc != 0) {
- goto end2;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end1;
}
+ local_sig_ptr = reformatted_sig;
}
#endif /*
* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
**/
- /* Convert this pk_alg and md_alg to PSA key type and key algorithm */
- construct_psa_key_alg_and_type(pk_alg, md_alg, psa_ecc_family,
- &psa_alg, &psa_key_type);
-
-
- if ((psa_alg == PSA_ALG_NONE) || (psa_key_type == PSA_KEY_TYPE_NONE)) {
- rc = CRYPTO_ERR_SIGNATURE;
- goto end2;
- }
-
- /* filled-in key_attributes */
- psa_set_key_algorithm(&psa_key_attr, psa_alg);
- psa_set_key_type(&psa_key_attr, psa_key_type);
- psa_set_key_usage_flags(&psa_key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
-
- /*
- * Note: In the implementation of the psa_import_key function in
- * version 3.6.0, the function expects the starting pointer of the
- * subject public key instead of the starting point of
- * SubjectPublicKeyInfo.
- * This is only needed while dealing with RSASSA_PSS (RSA Signature
- * scheme with Appendix based on Probabilistic Signature Scheme)
- * algorithm.
- */
- if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
- rc = pk_bytes_from_subpubkey((unsigned char **) &pk_ptr, &pk_len);
- if (rc != 0) {
- goto end2;
- }
- }
-
- /* Get the key_id using import API */
- status = psa_import_key(&psa_key_attr,
- pk_ptr,
- (size_t)pk_len,
- &psa_key_id);
-
- if (status != PSA_SUCCESS) {
- rc = CRYPTO_ERR_SIGNATURE;
- goto end2;
- }
-
- /*
- * Hash calculation and Signature verification of the given data payload
- * is wrapped under the psa_verify_message function.
- */
- status = psa_verify_message(psa_key_id, psa_alg,
+ /* Verify the signature. */
+ psa_status = psa_verify_message(psa_key_id, psa_alg,
data_ptr, data_len,
local_sig_ptr, local_sig_len);
-
- if (status != PSA_SUCCESS) {
+ if (psa_status == PSA_SUCCESS) {
+ /* The signature has been successfully verified. */
+ rc = CRYPTO_SUCCESS;
+ } else {
rc = CRYPTO_ERR_SIGNATURE;
- goto end1;
}
- /* Signature verification success */
- rc = CRYPTO_SUCCESS;
-
end1:
- /*
- * Destroy the key if it is created successfully
- */
+ /* Destroy the key from the PSA subsystem. */
psa_destroy_key(psa_key_id);
end2:
- mbedtls_free(sig_opts);
+ /* Free the pk context, if it is initialized. */
+ cleanup_pk_context(&pk, &pk_initialized);
+
return rc;
}
diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
index 7ae9624..d62eed7 100644
--- a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
+++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
@@ -8,6 +8,10 @@
#include <lib/utils_def.h>
#define FXOSC_BASE_ADDR (0x40050000UL)
+#define ARMPLL_BASE_ADDR (0x40038000UL)
+#define ARM_DFS_BASE_ADDR (0x40054000UL)
+#define CGM0_BASE_ADDR (0x40030000UL)
+#define CGM1_BASE_ADDR (0x40034000UL)
/* FXOSC */
#define FXOSC_CTRL(FXOSC) ((FXOSC) + 0x0UL)
@@ -26,4 +30,80 @@
#define FXOSC_STAT(FXOSC) ((FXOSC) + 0x4UL)
#define FXOSC_STAT_OSC_STAT BIT_32(31U)
+/* PLL */
+#define PLLDIG_PLLCR(PLL) ((PLL) + 0x0UL)
+#define PLLDIG_PLLCR_PLLPD BIT_32(31U)
+
+#define PLLDIG_PLLSR(PLL) ((PLL) + 0x4UL)
+#define PLLDIG_PLLSR_LOCK BIT_32(2U)
+
+#define PLLDIG_PLLDV(PLL) ((PLL) + 0x8UL)
+#define PLLDIG_PLLDV_RDIV_OFFSET 12U
+#define PLLDIG_PLLDV_RDIV_MASK GENMASK_32(14U, PLLDIG_PLLDV_RDIV_OFFSET)
+#define PLLDIG_PLLDV_RDIV_SET(VAL) (PLLDIG_PLLDV_RDIV_MASK & \
+ ((VAL) << PLLDIG_PLLDV_RDIV_OFFSET))
+#define PLLDIG_PLLDV_MFI_MASK GENMASK_32(7U, 0U)
+#define PLLDIG_PLLDV_MFI(DIV) (PLLDIG_PLLDV_MFI_MASK & (DIV))
+
+#define PLLDIG_PLLFD(PLL) ((PLL) + 0x10UL)
+#define PLLDIG_PLLFD_SMDEN BIT_32(30U)
+#define PLLDIG_PLLFD_MFN_MASK GENMASK_32(14U, 0U)
+#define PLLDIG_PLLFD_MFN_SET(VAL) (PLLDIG_PLLFD_MFN_MASK & (VAL))
+
+#define PLLDIG_PLLCLKMUX(PLL) ((PLL) + 0x20UL)
+
+#define PLLDIG_PLLODIV(PLL, N) ((PLL) + 0x80UL + ((N) * 0x4UL))
+#define PLLDIG_PLLODIV_DE BIT_32(31U)
+#define PLLDIG_PLLODIV_DIV_OFFSET 16U
+#define PLLDIG_PLLODIV_DIV_MASK GENMASK_32(23U, PLLDIG_PLLODIV_DIV_OFFSET)
+#define PLLDIG_PLLODIV_DIV(VAL) (((VAL) & PLLDIG_PLLODIV_DIV_MASK) >> \
+ PLLDIG_PLLODIV_DIV_OFFSET)
+#define PLLDIG_PLLODIV_DIV_SET(VAL) (PLLDIG_PLLODIV_DIV_MASK & ((VAL) << \
+ PLLDIG_PLLODIV_DIV_OFFSET))
+
+/* MMC_CGM */
+#define CGM_MUXn_CSC(CGM_ADDR, MUX) ((CGM_ADDR) + 0x300UL + ((MUX) * 0x40UL))
+#define MC_CGM_MUXn_CSC_SELCTL_OFFSET 24U
+#define MC_CGM_MUXn_CSC_SELCTL_MASK GENMASK_32(29U, MC_CGM_MUXn_CSC_SELCTL_OFFSET)
+#define MC_CGM_MUXn_CSC_SELCTL(val) (MC_CGM_MUXn_CSC_SELCTL_MASK & ((val) \
+ << MC_CGM_MUXn_CSC_SELCTL_OFFSET))
+#define MC_CGM_MUXn_CSC_CLK_SW BIT_32(2U)
+#define MC_CGM_MUXn_CSC_SAFE_SW BIT_32(3U)
+
+#define CGM_MUXn_CSS(CGM_ADDR, MUX) ((CGM_ADDR) + 0x304UL + ((MUX) * 0x40UL))
+#define MC_CGM_MUXn_CSS_SELSTAT_OFFSET 24U
+#define MC_CGM_MUXn_CSS_SELSTAT_MASK GENMASK_32(29U, MC_CGM_MUXn_CSS_SELSTAT_OFFSET)
+#define MC_CGM_MUXn_CSS_SELSTAT(css) ((MC_CGM_MUXn_CSS_SELSTAT_MASK & (css))\
+ >> MC_CGM_MUXn_CSS_SELSTAT_OFFSET)
+#define MC_CGM_MUXn_CSS_SWTRG(css) ((MC_CGM_MUXn_CSS_SWTRG_MASK & (css)) \
+ >> MC_CGM_MUXn_CSS_SWTRG_OFFSET)
+#define MC_CGM_MUXn_CSS_SWTRG_OFFSET 17U
+#define MC_CGM_MUXn_CSS_SWTRG_MASK GENMASK_32(19U, MC_CGM_MUXn_CSS_SWTRG_OFFSET)
+#define MC_CGM_MUXn_CSS_SWTRG_SUCCESS 0x1U
+#define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK 0x4U
+#define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE 0x5U
+#define MC_CGM_MUXn_CSS_SWIP BIT_32(16U)
+#define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U)
+
+/* DFS */
+#define DFS_PORTSR(DFS_ADDR) ((DFS_ADDR) + 0xCUL)
+#define DFS_PORTOLSR(DFS_ADDR) ((DFS_ADDR) + 0x10UL)
+#define DFS_PORTOLSR_LOL(N) (BIT_32(N) & GENMASK_32(5U, 0U))
+#define DFS_PORTRESET(DFS_ADDR) ((DFS_ADDR) + 0x14UL)
+#define DFS_PORTRESET_MASK GENMASK_32(5U, 0U)
+#define DFS_PORTRESET_SET(VAL) (((VAL) & DFS_PORTRESET_MASK))
+
+#define DFS_CTL(DFS_ADDR) ((DFS_ADDR) + 0x18UL)
+#define DFS_CTL_RESET BIT_32(1U)
+
+#define DFS_DVPORTn(DFS_ADDR, PORT) ((DFS_ADDR) + 0x1CUL + ((PORT) * 0x4UL))
+#define DFS_DVPORTn_MFI_MASK GENMASK_32(15U, 8U)
+#define DFS_DVPORTn_MFI_SHIFT 8U
+#define DFS_DVPORTn_MFN_MASK GENMASK_32(7U, 0U)
+#define DFS_DVPORTn_MFN_SHIFT 0U
+#define DFS_DVPORTn_MFI(MFI) (((MFI) & DFS_DVPORTn_MFI_MASK) >> DFS_DVPORTn_MFI_SHIFT)
+#define DFS_DVPORTn_MFN(MFN) (((MFN) & DFS_DVPORTn_MFN_MASK) >> DFS_DVPORTn_MFN_SHIFT)
+#define DFS_DVPORTn_MFI_SET(VAL) (((VAL) << DFS_DVPORTn_MFI_SHIFT) & DFS_DVPORTn_MFI_MASK)
+#define DFS_DVPORTn_MFN_SET(VAL) (((VAL) << DFS_DVPORTn_MFN_SHIFT) & DFS_DVPORTn_MFN_MASK)
+
#endif /* S32CC_CLK_REGS_H */
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index f35a469..e23d928 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -10,13 +10,21 @@
#include <common/debug.h>
#include <drivers/clk.h>
#include <lib/mmio.h>
+#include <s32cc-clk-ids.h>
#include <s32cc-clk-modules.h>
#include <s32cc-clk-utils.h>
#define MAX_STACK_DEPTH (15U)
+/* This is used for floating-point precision calculations. */
+#define FP_PRECISION (100000000UL)
+
struct s32cc_clk_drv {
uintptr_t fxosc_base;
+ uintptr_t armpll_base;
+ uintptr_t armdfs_base;
+ uintptr_t cgm0_base;
+ uintptr_t cgm1_base;
};
static int update_stack_depth(unsigned int *depth)
@@ -33,6 +41,10 @@
{
static struct s32cc_clk_drv driver = {
.fxosc_base = FXOSC_BASE_ADDR,
+ .armpll_base = ARMPLL_BASE_ADDR,
+ .armdfs_base = ARM_DFS_BASE_ADDR,
+ .cgm0_base = CGM0_BASE_ADDR,
+ .cgm1_base = CGM1_BASE_ADDR,
};
return &driver;
@@ -67,6 +79,43 @@
return -EINVAL;
}
+static int get_base_addr(enum s32cc_clk_source id, const struct s32cc_clk_drv *drv,
+ uintptr_t *base)
+{
+ int ret = 0;
+
+ switch (id) {
+ case S32CC_FXOSC:
+ *base = drv->fxosc_base;
+ break;
+ case S32CC_ARM_PLL:
+ *base = drv->armpll_base;
+ break;
+ case S32CC_ARM_DFS:
+ *base = drv->armdfs_base;
+ break;
+ case S32CC_CGM0:
+ *base = drv->cgm0_base;
+ break;
+ case S32CC_CGM1:
+ *base = drv->cgm1_base;
+ break;
+ case S32CC_FIRC:
+ break;
+ case S32CC_SIRC:
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret != 0) {
+ ERROR("Unknown clock source id: %u\n", id);
+ }
+
+ return ret;
+}
+
static void enable_fxosc(const struct s32cc_clk_drv *drv)
{
uintptr_t fxosc_base = drv->fxosc_base;
@@ -121,6 +170,593 @@
return ret;
}
+static int get_pll_mfi_mfn(unsigned long pll_vco, unsigned long ref_freq,
+ uint32_t *mfi, uint32_t *mfn)
+
+{
+ unsigned long vco;
+ unsigned long mfn64;
+
+ /* FRAC-N mode */
+ *mfi = (uint32_t)(pll_vco / ref_freq);
+
+ /* MFN formula : (double)(pll_vco % ref_freq) / ref_freq * 18432.0 */
+ mfn64 = pll_vco % ref_freq;
+ mfn64 *= FP_PRECISION;
+ mfn64 /= ref_freq;
+ mfn64 *= 18432UL;
+ mfn64 /= FP_PRECISION;
+
+ if (mfn64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ *mfn = (uint32_t)mfn64;
+
+ vco = ((unsigned long)*mfn * FP_PRECISION) / 18432UL;
+ vco += (unsigned long)*mfi * FP_PRECISION;
+ vco *= ref_freq;
+ vco /= FP_PRECISION;
+
+ if (vco != pll_vco) {
+ ERROR("Failed to find MFI and MFN settings for PLL freq %lu. Nearest freq = %lu\n",
+ pll_vco, vco);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct s32cc_clkmux *get_pll_mux(const struct s32cc_pll *pll)
+{
+ const struct s32cc_clk_obj *source = pll->source;
+ const struct s32cc_clk *clk;
+
+ if (source == NULL) {
+ ERROR("Failed to identify PLL's parent\n");
+ return NULL;
+ }
+
+ if (source->type != s32cc_clk_t) {
+ ERROR("The parent of the PLL isn't a clock\n");
+ return NULL;
+ }
+
+ clk = s32cc_obj2clk(source);
+
+ if (clk->module == NULL) {
+ ERROR("The clock isn't connected to a module\n");
+ return NULL;
+ }
+
+ source = clk->module;
+
+ if ((source->type != s32cc_clkmux_t) &&
+ (source->type != s32cc_shared_clkmux_t)) {
+ ERROR("The parent of the PLL isn't a MUX\n");
+ return NULL;
+ }
+
+ return s32cc_obj2clkmux(source);
+}
+
+static void disable_odiv(uintptr_t pll_addr, uint32_t div_index)
+{
+ mmio_clrbits_32(PLLDIG_PLLODIV(pll_addr, div_index), PLLDIG_PLLODIV_DE);
+}
+
+static void enable_odiv(uintptr_t pll_addr, uint32_t div_index)
+{
+ mmio_setbits_32(PLLDIG_PLLODIV(pll_addr, div_index), PLLDIG_PLLODIV_DE);
+}
+
+static void disable_odivs(uintptr_t pll_addr, uint32_t ndivs)
+{
+ uint32_t i;
+
+ for (i = 0; i < ndivs; i++) {
+ disable_odiv(pll_addr, i);
+ }
+}
+
+static void enable_pll_hw(uintptr_t pll_addr)
+{
+ /* Enable the PLL. */
+ mmio_write_32(PLLDIG_PLLCR(pll_addr), 0x0);
+
+ /* Poll until PLL acquires lock. */
+ while ((mmio_read_32(PLLDIG_PLLSR(pll_addr)) & PLLDIG_PLLSR_LOCK) == 0U) {
+ }
+}
+
+static void disable_pll_hw(uintptr_t pll_addr)
+{
+ mmio_write_32(PLLDIG_PLLCR(pll_addr), PLLDIG_PLLCR_PLLPD);
+}
+
+static int program_pll(const struct s32cc_pll *pll, uintptr_t pll_addr,
+ const struct s32cc_clk_drv *drv, uint32_t sclk_id,
+ unsigned long sclk_freq)
+{
+ uint32_t rdiv = 1, mfi, mfn;
+ int ret;
+
+ ret = get_pll_mfi_mfn(pll->vco_freq, sclk_freq, &mfi, &mfn);
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ /* Disable ODIVs*/
+ disable_odivs(pll_addr, pll->ndividers);
+
+ /* Disable PLL */
+ disable_pll_hw(pll_addr);
+
+ /* Program PLLCLKMUX */
+ mmio_write_32(PLLDIG_PLLCLKMUX(pll_addr), sclk_id);
+
+ /* Program VCO */
+ mmio_clrsetbits_32(PLLDIG_PLLDV(pll_addr),
+ PLLDIG_PLLDV_RDIV_MASK | PLLDIG_PLLDV_MFI_MASK,
+ PLLDIG_PLLDV_RDIV_SET(rdiv) | PLLDIG_PLLDV_MFI(mfi));
+
+ mmio_write_32(PLLDIG_PLLFD(pll_addr),
+ PLLDIG_PLLFD_MFN_SET(mfn) | PLLDIG_PLLFD_SMDEN);
+
+ enable_pll_hw(pll_addr);
+
+ return ret;
+}
+
+static int enable_pll(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_pll *pll = s32cc_obj2pll(module);
+ const struct s32cc_clkmux *mux;
+ uintptr_t pll_addr = UL(0x0);
+ unsigned long sclk_freq;
+ uint32_t sclk_id;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ mux = get_pll_mux(pll);
+ if (mux == NULL) {
+ return -EINVAL;
+ }
+
+ if (pll->instance != mux->module) {
+ ERROR("MUX type is not in sync with PLL ID\n");
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(pll->instance, drv, &pll_addr);
+ if (ret != 0) {
+ ERROR("Failed to detect PLL instance\n");
+ return ret;
+ }
+
+ switch (mux->source_id) {
+ case S32CC_CLK_FIRC:
+ sclk_freq = 48U * MHZ;
+ sclk_id = 0;
+ break;
+ case S32CC_CLK_FXOSC:
+ sclk_freq = 40U * MHZ;
+ sclk_id = 1;
+ break;
+ default:
+ ERROR("Invalid source selection for PLL 0x%lx\n",
+ pll_addr);
+ return -EINVAL;
+ };
+
+ return program_pll(pll, pll_addr, drv, sclk_id, sclk_freq);
+}
+
+static inline struct s32cc_pll *get_div_pll(const struct s32cc_pll_out_div *pdiv)
+{
+ const struct s32cc_clk_obj *parent;
+
+ parent = pdiv->parent;
+ if (parent == NULL) {
+ ERROR("Failed to identify PLL divider's parent\n");
+ return NULL;
+ }
+
+ if (parent->type != s32cc_pll_t) {
+ ERROR("The parent of the divider is not a PLL instance\n");
+ return NULL;
+ }
+
+ return s32cc_obj2pll(parent);
+}
+
+static void config_pll_out_div(uintptr_t pll_addr, uint32_t div_index, uint32_t dc)
+{
+ uint32_t pllodiv;
+ uint32_t pdiv;
+
+ pllodiv = mmio_read_32(PLLDIG_PLLODIV(pll_addr, div_index));
+ pdiv = PLLDIG_PLLODIV_DIV(pllodiv);
+
+ if (((pdiv + 1U) == dc) && ((pllodiv & PLLDIG_PLLODIV_DE) != 0U)) {
+ return;
+ }
+
+ if ((pllodiv & PLLDIG_PLLODIV_DE) != 0U) {
+ disable_odiv(pll_addr, div_index);
+ }
+
+ pllodiv = PLLDIG_PLLODIV_DIV_SET(dc - 1U);
+ mmio_write_32(PLLDIG_PLLODIV(pll_addr, div_index), pllodiv);
+
+ enable_odiv(pll_addr, div_index);
+}
+
+static int enable_pll_div(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module);
+ uintptr_t pll_addr = 0x0ULL;
+ const struct s32cc_pll *pll;
+ uint32_t dc;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ pll = get_div_pll(pdiv);
+ if (pll == NULL) {
+ ERROR("The parent of the PLL DIV is invalid\n");
+ return 0;
+ }
+
+ ret = get_base_addr(pll->instance, drv, &pll_addr);
+ if (ret != 0) {
+ ERROR("Failed to detect PLL instance\n");
+ return -EINVAL;
+ }
+
+ dc = (uint32_t)(pll->vco_freq / pdiv->freq);
+
+ config_pll_out_div(pll_addr, pdiv->index, dc);
+
+ return 0;
+}
+
+static int cgm_mux_clk_config(uintptr_t cgm_addr, uint32_t mux, uint32_t source,
+ bool safe_clk)
+{
+ uint32_t css, csc;
+
+ css = mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux));
+
+ /* Already configured */
+ if ((MC_CGM_MUXn_CSS_SELSTAT(css) == source) &&
+ (MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SUCCESS) &&
+ ((css & MC_CGM_MUXn_CSS_SWIP) == 0U) && !safe_clk) {
+ return 0;
+ }
+
+ /* Ongoing clock switch? */
+ while ((mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux)) &
+ MC_CGM_MUXn_CSS_SWIP) != 0U) {
+ }
+
+ csc = mmio_read_32(CGM_MUXn_CSC(cgm_addr, mux));
+
+ /* Clear previous source. */
+ csc &= ~(MC_CGM_MUXn_CSC_SELCTL_MASK);
+
+ if (!safe_clk) {
+ /* Select the clock source and trigger the clock switch. */
+ csc |= MC_CGM_MUXn_CSC_SELCTL(source) | MC_CGM_MUXn_CSC_CLK_SW;
+ } else {
+ /* Switch to safe clock */
+ csc |= MC_CGM_MUXn_CSC_SAFE_SW;
+ }
+
+ mmio_write_32(CGM_MUXn_CSC(cgm_addr, mux), csc);
+
+ /* Wait for configuration bit to auto-clear. */
+ while ((mmio_read_32(CGM_MUXn_CSC(cgm_addr, mux)) &
+ MC_CGM_MUXn_CSC_CLK_SW) != 0U) {
+ }
+
+ /* Is the clock switch completed? */
+ while ((mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux)) &
+ MC_CGM_MUXn_CSS_SWIP) != 0U) {
+ }
+
+ /*
+ * Check if the switch succeeded.
+ * Check switch trigger cause and the source.
+ */
+ css = mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux));
+ if (!safe_clk) {
+ if ((MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SUCCESS) &&
+ (MC_CGM_MUXn_CSS_SELSTAT(css) == source)) {
+ return 0;
+ }
+
+ ERROR("Failed to change the source of mux %" PRIu32 " to %" PRIu32 " (CGM=%lu)\n",
+ mux, source, cgm_addr);
+ } else {
+ if (((MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK) ||
+ (MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE)) &&
+ ((MC_CGM_MUXn_CSS_SAFE_SW & css) != 0U)) {
+ return 0;
+ }
+
+ ERROR("The switch of mux %" PRIu32 " (CGM=%lu) to safe clock failed\n",
+ mux, cgm_addr);
+ }
+
+ return -EINVAL;
+}
+
+static int enable_cgm_mux(const struct s32cc_clkmux *mux,
+ const struct s32cc_clk_drv *drv)
+{
+ uintptr_t cgm_addr = UL(0x0);
+ uint32_t mux_hw_clk;
+ int ret;
+
+ ret = get_base_addr(mux->module, drv, &cgm_addr);
+ if (ret != 0) {
+ return ret;
+ }
+
+ mux_hw_clk = (uint32_t)S32CC_CLK_ID(mux->source_id);
+
+ return cgm_mux_clk_config(cgm_addr, mux->index,
+ mux_hw_clk, false);
+}
+
+static int enable_mux(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module);
+ const struct s32cc_clk *clk;
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (mux == NULL) {
+ return -EINVAL;
+ }
+
+ clk = s32cc_get_arch_clk(mux->source_id);
+ if (clk == NULL) {
+ ERROR("Invalid parent (%lu) for mux %" PRIu8 "\n",
+ mux->source_id, mux->index);
+ return -EINVAL;
+ }
+
+ switch (mux->module) {
+ /* PLL mux will be enabled by PLL setup */
+ case S32CC_ARM_PLL:
+ break;
+ case S32CC_CGM1:
+ ret = enable_cgm_mux(mux, drv);
+ break;
+ case S32CC_CGM0:
+ ret = enable_cgm_mux(mux, drv);
+ break;
+ default:
+ ERROR("Unknown mux parent type: %d\n", mux->module);
+ ret = -EINVAL;
+ break;
+ };
+
+ return ret;
+}
+
+static int enable_dfs(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct s32cc_dfs *get_div_dfs(const struct s32cc_dfs_div *dfs_div)
+{
+ const struct s32cc_clk_obj *parent = dfs_div->parent;
+
+ if (parent->type != s32cc_dfs_t) {
+ ERROR("DFS DIV doesn't have a DFS as parent\n");
+ return NULL;
+ }
+
+ return s32cc_obj2dfs(parent);
+}
+
+static struct s32cc_pll *dfsdiv2pll(const struct s32cc_dfs_div *dfs_div)
+{
+ const struct s32cc_clk_obj *parent;
+ const struct s32cc_dfs *dfs;
+
+ dfs = get_div_dfs(dfs_div);
+ if (dfs == NULL) {
+ return NULL;
+ }
+
+ parent = dfs->parent;
+ if (parent->type != s32cc_pll_t) {
+ return NULL;
+ }
+
+ return s32cc_obj2pll(parent);
+}
+
+static int get_dfs_mfi_mfn(unsigned long dfs_freq, const struct s32cc_dfs_div *dfs_div,
+ uint32_t *mfi, uint32_t *mfn)
+{
+ uint64_t factor64, tmp64, ofreq;
+ uint32_t factor32;
+
+ unsigned long in = dfs_freq;
+ unsigned long out = dfs_div->freq;
+
+ /**
+ * factor = (IN / OUT) / 2
+ * MFI = integer(factor)
+ * MFN = (factor - MFI) * 36
+ */
+ factor64 = ((((uint64_t)in) * FP_PRECISION) / ((uint64_t)out)) / 2ULL;
+ tmp64 = factor64 / FP_PRECISION;
+ if (tmp64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ factor32 = (uint32_t)tmp64;
+ *mfi = factor32;
+
+ tmp64 = ((factor64 - ((uint64_t)*mfi * FP_PRECISION)) * 36UL) / FP_PRECISION;
+ if (tmp64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ *mfn = (uint32_t)tmp64;
+
+ /* div_freq = in / (2 * (*mfi + *mfn / 36.0)) */
+ factor64 = (((uint64_t)*mfn) * FP_PRECISION) / 36ULL;
+ factor64 += ((uint64_t)*mfi) * FP_PRECISION;
+ factor64 *= 2ULL;
+ ofreq = (((uint64_t)in) * FP_PRECISION) / factor64;
+
+ if (ofreq != dfs_div->freq) {
+ ERROR("Failed to find MFI and MFN settings for DFS DIV freq %lu\n",
+ dfs_div->freq);
+ ERROR("Nearest freq = %" PRIx64 "\n", ofreq);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int init_dfs_port(uintptr_t dfs_addr, uint32_t port,
+ uint32_t mfi, uint32_t mfn)
+{
+ uint32_t portsr, portolsr;
+ uint32_t mask, old_mfi, old_mfn;
+ uint32_t dvport;
+ bool init_dfs;
+
+ dvport = mmio_read_32(DFS_DVPORTn(dfs_addr, port));
+
+ old_mfi = DFS_DVPORTn_MFI(dvport);
+ old_mfn = DFS_DVPORTn_MFN(dvport);
+
+ portsr = mmio_read_32(DFS_PORTSR(dfs_addr));
+ portolsr = mmio_read_32(DFS_PORTOLSR(dfs_addr));
+
+ /* Skip configuration if it's not needed */
+ if (((portsr & BIT_32(port)) != 0U) &&
+ ((portolsr & BIT_32(port)) == 0U) &&
+ (mfi == old_mfi) && (mfn == old_mfn)) {
+ return 0;
+ }
+
+ init_dfs = (portsr == 0U);
+
+ if (init_dfs) {
+ mask = DFS_PORTRESET_MASK;
+ } else {
+ mask = DFS_PORTRESET_SET(BIT_32(port));
+ }
+
+ mmio_write_32(DFS_PORTOLSR(dfs_addr), mask);
+ mmio_write_32(DFS_PORTRESET(dfs_addr), mask);
+
+ while ((mmio_read_32(DFS_PORTSR(dfs_addr)) & mask) != 0U) {
+ }
+
+ if (init_dfs) {
+ mmio_write_32(DFS_CTL(dfs_addr), DFS_CTL_RESET);
+ }
+
+ mmio_write_32(DFS_DVPORTn(dfs_addr, port),
+ DFS_DVPORTn_MFI_SET(mfi) | DFS_DVPORTn_MFN_SET(mfn));
+
+ if (init_dfs) {
+ /* DFS clk enable programming */
+ mmio_clrbits_32(DFS_CTL(dfs_addr), DFS_CTL_RESET);
+ }
+
+ mmio_clrbits_32(DFS_PORTRESET(dfs_addr), BIT_32(port));
+
+ while ((mmio_read_32(DFS_PORTSR(dfs_addr)) & BIT_32(port)) != BIT_32(port)) {
+ }
+
+ portolsr = mmio_read_32(DFS_PORTOLSR(dfs_addr));
+ if ((portolsr & DFS_PORTOLSR_LOL(port)) != 0U) {
+ ERROR("Failed to lock DFS divider\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int enable_dfs_div(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+ const struct s32cc_pll *pll;
+ const struct s32cc_dfs *dfs;
+ uintptr_t dfs_addr = 0UL;
+ uint32_t mfi, mfn;
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ dfs = get_div_dfs(dfs_div);
+ if (dfs == NULL) {
+ return -EINVAL;
+ }
+
+ pll = dfsdiv2pll(dfs_div);
+ if (pll == NULL) {
+ ERROR("Failed to identify DFS divider's parent\n");
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(dfs->instance, drv, &dfs_addr);
+ if ((ret != 0) || (dfs_addr == 0UL)) {
+ return -EINVAL;
+ }
+
+ ret = get_dfs_mfi_mfn(pll->vco_freq, dfs_div, &mfi, &mfn);
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ return init_dfs_port(dfs_addr, dfs_div->index, mfi, mfn);
+}
+
static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth)
{
const struct s32cc_clk_drv *drv = get_drv();
@@ -142,19 +778,27 @@
case s32cc_clk_t:
ret = enable_clk_module(module, drv, depth);
break;
+ case s32cc_pll_t:
+ ret = enable_pll(module, drv, depth);
+ break;
+ case s32cc_pll_out_div_t:
+ ret = enable_pll_div(module, drv, depth);
+ break;
case s32cc_clkmux_t:
- ret = -ENOTSUP;
+ ret = enable_mux(module, drv, depth);
break;
case s32cc_shared_clkmux_t:
- ret = -ENOTSUP;
+ ret = enable_mux(module, drv, depth);
break;
- case s32cc_pll_t:
- ret = -ENOTSUP;
- break;
- case s32cc_pll_out_div_t:
case s32cc_fixed_div_t:
ret = -ENOTSUP;
break;
+ case s32cc_dfs_t:
+ ret = enable_dfs(module, drv, depth);
+ break;
+ case s32cc_dfs_div_t:
+ ret = enable_dfs_div(module, drv, depth);
+ break;
default:
ret = -EINVAL;
break;
@@ -340,6 +984,63 @@
return ret;
}
+static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module);
+ const struct s32cc_clk *clk = s32cc_get_arch_clk(mux->source_id);
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (clk == NULL) {
+ ERROR("Mux (id:%" PRIu8 ") without a valid source (%lu)\n",
+ mux->index, mux->source_id);
+ return -EINVAL;
+ }
+
+ return set_module_rate(&clk->desc, rate, orate, depth);
+}
+
+static int set_dfs_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+ const struct s32cc_dfs *dfs;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (dfs_div->parent == NULL) {
+ ERROR("Failed to identify DFS divider's parent\n");
+ return -EINVAL;
+ }
+
+ /* Sanity check */
+ dfs = s32cc_obj2dfs(dfs_div->parent);
+ if (dfs->parent == NULL) {
+ ERROR("Failed to identify DFS's parent\n");
+ return -EINVAL;
+ }
+
+ if ((dfs_div->freq != 0U) && (dfs_div->freq != rate)) {
+ ERROR("DFS DIV frequency was already set to %lu\n",
+ dfs_div->freq);
+ return -EINVAL;
+ }
+
+ dfs_div->freq = rate;
+ *orate = rate;
+
+ return ret;
+}
+
static int set_module_rate(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate,
unsigned int *depth)
@@ -351,6 +1052,8 @@
return ret;
}
+ ret = -EINVAL;
+
switch (module->type) {
case s32cc_clk_t:
ret = set_clk_freq(module, rate, orate, depth);
@@ -368,11 +1071,18 @@
ret = set_fixed_div_freq(module, rate, orate, depth);
break;
case s32cc_clkmux_t:
+ ret = set_mux_freq(module, rate, orate, depth);
+ break;
case s32cc_shared_clkmux_t:
- ret = -ENOTSUP;
+ ret = set_mux_freq(module, rate, orate, depth);
+ break;
+ case s32cc_dfs_t:
+ ERROR("Setting the frequency of a DFS is not allowed!");
+ break;
+ case s32cc_dfs_div_t:
+ ret = set_dfs_div_freq(module, rate, orate, depth);
break;
default:
- ret = -EINVAL;
break;
}
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index 039db2a..c4c73c7 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -43,6 +43,45 @@
static struct s32cc_clk arm_pll_phi0_clk =
S32CC_FREQ_MODULE_CLK(arm_pll_phi0_div, 0, GHZ);
+/* ARM DFS */
+static struct s32cc_dfs armdfs =
+ S32CC_DFS_INIT(armpll, S32CC_ARM_DFS);
+static struct s32cc_dfs_div arm_dfs1_div =
+ S32CC_DFS_DIV_INIT(armdfs, 0);
+static struct s32cc_clk arm_dfs1_clk =
+ S32CC_FREQ_MODULE_CLK(arm_dfs1_div, 0, 800 * MHZ);
+
+/* MC_CGM0 */
+static struct s32cc_clkmux cgm0_mux0 =
+ S32CC_SHARED_CLKMUX_INIT(S32CC_CGM0, 0, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_ARM_PLL_DFS1, 0, 0, 0);
+static struct s32cc_clk cgm0_mux0_clk = S32CC_MODULE_CLK(cgm0_mux0);
+
+/* XBAR */
+static struct s32cc_clk xbar_2x_clk =
+ S32CC_CHILD_CLK(cgm0_mux0_clk, 48 * MHZ, 800 * MHZ);
+static struct s32cc_fixed_div xbar_div2 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 2);
+static struct s32cc_clk xbar_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div2, 24 * MHZ, 400 * MHZ);
+static struct s32cc_fixed_div xbar_div4 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 4);
+static struct s32cc_clk xbar_div2_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div4, 12 * MHZ, 200 * MHZ);
+static struct s32cc_fixed_div xbar_div6 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 6);
+static struct s32cc_clk xbar_div3_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div6, 8 * MHZ, 133333333);
+static struct s32cc_fixed_div xbar_div8 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 8);
+static struct s32cc_clk xbar_div4_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div8, 6 * MHZ, 100 * MHZ);
+static struct s32cc_fixed_div xbar_div12 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 12);
+static struct s32cc_clk xbar_div6_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div12, 4 * MHZ, 66666666);
+
/* MC_CGM1 */
static struct s32cc_clkmux cgm1_mux0 =
S32CC_SHARED_CLKMUX_INIT(S32CC_CGM1, 0, 3,
@@ -68,13 +107,15 @@
S32CC_FREQ_MODULE_CLK(a53_core_div10, S32CC_A53_MIN_FREQ / 10,
S32CC_A53_MAX_FREQ / 10);
-static struct s32cc_clk *s32cc_hw_clk_list[5] = {
+static struct s32cc_clk *s32cc_hw_clk_list[13] = {
/* Oscillators */
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
[S32CC_CLK_ID(S32CC_CLK_SIRC)] = &sirc_clk,
[S32CC_CLK_ID(S32CC_CLK_FXOSC)] = &fxosc_clk,
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_PHI0)] = &arm_pll_phi0_clk,
+ /* ARM DFS */
+ [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk,
};
static struct s32cc_clk_array s32cc_hw_clocks = {
@@ -83,10 +124,19 @@
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
};
-static struct s32cc_clk *s32cc_arch_clk_list[6] = {
+static struct s32cc_clk *s32cc_arch_clk_list[13] = {
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk,
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk,
+ /* MC_CGM0 */
+ [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX0)] = &cgm0_mux0_clk,
+ /* XBAR */
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_2X)] = &xbar_2x_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR)] = &xbar_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV2)] = &xbar_div2_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV3)] = &xbar_div3_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV4)] = &xbar_div4_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV6)] = &xbar_div6_clk,
/* MC_CGM1 */
[S32CC_CLK_ID(S32CC_CLK_MC_CGM1_MUX0)] = &cgm1_mux0_clk,
/* A53 */
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index ac1f7d0..2c256a5 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -11,39 +11,129 @@
#define S32CC_FXOSC_FREQ (40U * MHZ)
#define S32CC_ARM_PLL_VCO_FREQ (2U * GHZ)
#define S32CC_ARM_PLL_PHI0_FREQ (1U * GHZ)
+#define S32CC_A53_FREQ (1U * GHZ)
+#define S32CC_XBAR_2X_FREQ (800U * MHZ)
-int s32cc_init_early_clks(void)
+static int enable_fxosc_clk(void)
{
int ret;
- s32cc_clk_register_drv();
+ ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_FXOSC);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+static int enable_arm_pll(void)
+{
+ int ret;
ret = clk_set_parent(S32CC_CLK_ARM_PLL_MUX, S32CC_CLK_FXOSC);
if (ret != 0) {
return ret;
}
+ ret = clk_set_rate(S32CC_CLK_ARM_PLL_VCO, S32CC_ARM_PLL_VCO_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_ARM_PLL_PHI0, S32CC_ARM_PLL_PHI0_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_VCO);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_PHI0);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+static int enable_a53_clk(void)
+{
+ int ret;
+
ret = clk_set_parent(S32CC_CLK_MC_CGM1_MUX0, S32CC_CLK_ARM_PLL_PHI0);
if (ret != 0) {
return ret;
}
- ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
+ ret = clk_set_rate(S32CC_CLK_A53_CORE, S32CC_A53_FREQ, NULL);
if (ret != 0) {
return ret;
}
- ret = clk_set_rate(S32CC_CLK_ARM_PLL_VCO, S32CC_ARM_PLL_VCO_FREQ, NULL);
+ ret = clk_enable(S32CC_CLK_A53_CORE);
if (ret != 0) {
return ret;
}
- ret = clk_set_rate(S32CC_CLK_ARM_PLL_PHI0, S32CC_ARM_PLL_PHI0_FREQ, NULL);
+ return ret;
+}
+
+static int enable_xbar_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX0, S32CC_CLK_ARM_PLL_DFS1);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_FXOSC);
+ ret = clk_set_rate(S32CC_CLK_XBAR_2X, S32CC_XBAR_2X_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_DFS1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_XBAR_2X);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+int s32cc_init_early_clks(void)
+{
+ int ret;
+
+ s32cc_clk_register_drv();
+
+ ret = enable_fxosc_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_arm_pll();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_a53_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_xbar_clk();
if (ret != 0) {
return ret;
}
diff --git a/drivers/nxp/gpio/nxp_gpio.c b/drivers/nxp/gpio/nxp_gpio.c
index 28c9db9..b477b79 100644
--- a/drivers/nxp/gpio/nxp_gpio.c
+++ b/drivers/nxp/gpio/nxp_gpio.c
@@ -28,8 +28,8 @@
ERROR("GPIO is not initialized.\n");
return GPIO_FAILURE;
}
-
- gpdir = gpio_base_addr + GPDIR_REG_OFFSET;
+ /* Divide by 4 since we're operating on 32-bit pointer addresses. */
+ gpdir = gpio_base_addr + (GPDIR_REG_OFFSET >> 2);
gpdat = gpio_base_addr + (GPDAT_REG_OFFSET >> 2);
/*
@@ -67,8 +67,9 @@
return GPIO_FAILURE;
}
- gpdir = gpio_base_addr + GPDIR_REG_OFFSET;
- gpdat = gpio_base_addr + GPDAT_REG_OFFSET;
+ /* Divide by 4 since we're operating on 32-bit pointer addresses. */
+ gpdir = gpio_base_addr + (GPDIR_REG_OFFSET >> 2);
+ gpdat = gpio_base_addr + (GPDAT_REG_OFFSET >> 2);
/*
* Reset the corresponding bit in direction and data register
diff --git a/fdts/cca_cot_descriptors.dtsi b/fdts/cca_cot_descriptors.dtsi
index 821f600..93d60ea 100644
--- a/fdts/cca_cot_descriptors.dtsi
+++ b/fdts/cca_cot_descriptors.dtsi
@@ -15,7 +15,7 @@
cca_content_cert: cca_content_cert {
root-certificate;
image-id =<CCA_CONTENT_CERT_ID>;
- antirollback-counter = <&cca_nv_counter>;
+ antirollback-counter = <&cca_nv_ctr>;
tb_fw_hash: tb_fw_hash {
oid = TRUSTED_BOOT_FW_HASH_OID;
@@ -44,7 +44,7 @@
root-certificate;
image-id = <CORE_SWD_KEY_CERT_ID>;
signing-key = <&swd_rot_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
core_swd_pk: core_swd_pk {
oid = CORE_SWD_PK_OID;
@@ -55,7 +55,7 @@
image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
parent = <&core_swd_key_cert>;
signing-key = <&core_swd_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -69,7 +69,7 @@
root-certificate;
image-id = <PLAT_KEY_CERT_ID>;
signing-key = <&prot_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
plat_pk: plat_pk {
oid = PLAT_PK_OID;
@@ -80,7 +80,7 @@
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
parent = <&plat_key_cert>;
signing-key = <&plat_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -95,7 +95,7 @@
image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&core_swd_key_cert>;
signing-key = <&core_swd_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
sp_pkg1_hash: sp_pkg1_hash {
oid = SP_PKG1_HASH_OID;
@@ -115,7 +115,7 @@
image-id = <PLAT_SP_CONTENT_CERT_ID>;
parent = <&plat_key_cert>;
signing-key = <&plat_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
sp_pkg5_hash: sp_pkg5_hash {
oid = SP_PKG5_HASH_OID;
@@ -242,17 +242,17 @@
#address-cells = <1>;
#size-cells = <0>;
- cca_nv_counter: cca_nv_counter {
+ cca_nv_ctr: cca_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = CCA_FW_NVCOUNTER_OID;
};
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/dualroot_cot_descriptors.dtsi b/fdts/dualroot_cot_descriptors.dtsi
index 459a1dd..bea7af5 100644
--- a/fdts/dualroot_cot_descriptors.dtsi
+++ b/fdts/dualroot_cot_descriptors.dtsi
@@ -15,7 +15,7 @@
trusted_boot_fw_cert: trusted_boot_fw_cert {
root-certificate;
image-id =<TRUSTED_BOOT_FW_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tb_fw_hash: tb_fw_hash {
oid = TRUSTED_BOOT_FW_HASH_OID;
@@ -34,7 +34,7 @@
trusted_key_cert: trusted_key_cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted_world_pk: trusted_world_pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -45,7 +45,7 @@
image-id = <SCP_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_content_pk: scp_fw_content_pk {
oid = SCP_FW_CONTENT_CERT_PK_OID;
@@ -56,7 +56,7 @@
image-id = <SCP_FW_CONTENT_CERT_ID>;
parent = <&scp_fw_key_cert>;
signing-key = <&scp_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_hash: scp_fw_hash {
oid = SCP_FW_HASH_OID;
@@ -67,7 +67,7 @@
image-id = <SOC_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_content_pk: soc_fw_content_pk {
oid = SOC_FW_CONTENT_CERT_PK_OID;
};
@@ -77,7 +77,7 @@
image-id = <SOC_FW_CONTENT_CERT_ID>;
parent = <&soc_fw_key_cert>;
signing-key = <&soc_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_hash: soc_fw_hash {
oid = SOC_AP_FW_HASH_OID;
@@ -91,7 +91,7 @@
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_content_pk: tos_fw_content_pk {
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
@@ -102,7 +102,7 @@
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>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -122,7 +122,7 @@
root-certificate;
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
signing-key = <&prot_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -137,7 +137,7 @@
image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
sp_pkg1_hash: sp_pkg1_hash {
oid = SP_PKG1_HASH_OID;
@@ -157,7 +157,7 @@
root-certificate;
image-id = <PLAT_SP_CONTENT_CERT_ID>;
signing-key = <&prot_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
sp_pkg5_hash: sp_pkg5_hash {
oid = SP_PKG5_HASH_OID;
@@ -296,12 +296,12 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/stm32mp1-cot-descriptors.dtsi b/fdts/stm32mp1-cot-descriptors.dtsi
index eb632ff..05326be 100644
--- a/fdts/stm32mp1-cot-descriptors.dtsi
+++ b/fdts/stm32mp1-cot-descriptors.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2022, ARM Limited. All rights reserved.
+ * Copyright (c) 2020-2024, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,7 +15,7 @@
stm32mp_cfg_cert: stm32mp_cfg_cert {
root-certificate;
image-id = <STM32MP_CONFIG_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
hw_config_hash: hw_config_hash {
oid = HW_CONFIG_HASH_OID;
@@ -29,7 +29,7 @@
trusted_key_cert: trusted_key_cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted_world_pk: trusted_world_pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -43,7 +43,7 @@
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_content_pk: tos_fw_content_pk {
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
@@ -54,7 +54,7 @@
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>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -74,7 +74,7 @@
image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&non_trusted_world_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_fw_content_pk: nt_fw_content_pk {
oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
@@ -85,7 +85,7 @@
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>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -144,12 +144,12 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/tbbr_cot_descriptors.dtsi b/fdts/tbbr_cot_descriptors.dtsi
index d11e2be..b3c0ca7 100644
--- a/fdts/tbbr_cot_descriptors.dtsi
+++ b/fdts/tbbr_cot_descriptors.dtsi
@@ -4,7 +4,12 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#if USE_TBBR_DEFS
#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
#include <common/tbbr/tbbr_img_def.h>
#include <common/nv_cntr_ids.h>
@@ -15,7 +20,7 @@
trusted_boot_fw_cert: trusted_boot_fw_cert {
root-certificate;
image-id =<TRUSTED_BOOT_FW_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tb_fw_hash: tb_fw_hash {
oid = TRUSTED_BOOT_FW_HASH_OID;
@@ -34,7 +39,7 @@
trusted_key_cert: trusted_key_cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted_world_pk: trusted_world_pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -48,7 +53,7 @@
image-id = <SCP_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_content_pk: scp_fw_content_pk {
oid = SCP_FW_CONTENT_CERT_PK_OID;
@@ -59,7 +64,7 @@
image-id = <SCP_FW_CONTENT_CERT_ID>;
parent = <&scp_fw_key_cert>;
signing-key = <&scp_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_hash: scp_fw_hash {
oid = SCP_FW_HASH_OID;
@@ -70,7 +75,7 @@
image-id = <SOC_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_content_pk: soc_fw_content_pk {
oid = SOC_FW_CONTENT_CERT_PK_OID;
};
@@ -80,7 +85,7 @@
image-id = <SOC_FW_CONTENT_CERT_ID>;
parent = <&soc_fw_key_cert>;
signing-key = <&soc_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_hash: soc_fw_hash {
oid = SOC_AP_FW_HASH_OID;
@@ -94,7 +99,7 @@
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_content_pk: tos_fw_content_pk {
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
@@ -105,7 +110,7 @@
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>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -125,7 +130,7 @@
image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&non_trusted_world_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_fw_content_pk: nt_fw_content_pk {
oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
@@ -136,7 +141,7 @@
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>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -151,7 +156,7 @@
image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
sp_pkg1_hash: sp_pkg1_hash {
oid = SP_PKG1_HASH_OID;
@@ -302,12 +307,12 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index 2e03be2..fc6fe78 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -265,9 +265,22 @@
method = "smc";
};
- cpu-pmu {
- compatible = "arm,armv8-pmuv3";
- interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ cpu-pmu-little {
+ compatible = LIT_CPU_PMU_COMPATIBLE;
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition_little>;
+ status = "okay";
+ };
+
+ cpu-pmu-mid {
+ compatible = MID_CPU_PMU_COMPATIBLE;
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition_mid>;
+ status = "okay";
+ };
+
+ cpu-pmu-big {
+ compatible = BIG_CPU_PMU_COMPATIBLE;
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition_big>;
+ status = "okay";
};
sram: sram@6000000 {
@@ -290,7 +303,7 @@
clocks = <&soc_refclk>;
clock-names = "apb_pclk";
#mbox-cells = <MHU_MBOX_CELLS>;
- interrupts = <GIC_SPI MHU_RX_INT_NUM IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI MHU_RX_INT_NUM IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = MHU_RX_INT_NAME;
};
@@ -332,23 +345,35 @@
gic: interrupt-controller@GIC_CTRL_ADDR {
compatible = "arm,gic-v3";
#address-cells = <2>;
- #interrupt-cells = <3>;
+ #interrupt-cells = <4>;
#size-cells = <2>;
ranges;
interrupt-controller;
reg = <0x0 0x30000000 0 0x10000>, /* GICD */
<0x0 0x30080000 0 GIC_GICR_OFFSET>; /* GICR */
- interrupts = <GIC_PPI 0x9 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_PPI 0x9 IRQ_TYPE_LEVEL_LOW 0>;
};
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>;
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
};
+ spe-pmu-mid {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_HIGH &ppi_partition_mid>;
+ status = "disabled";
+ };
+
+ spe-pmu-big {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_HIGH &ppi_partition_big>;
+ status = "disabled";
+ };
+
soc_refclk: refclk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -374,7 +399,7 @@
os_uart: serial@2a400000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2A400000 0x0 UART_OFFSET>;
- interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&soc_uartclk>, <&soc_refclk>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
@@ -414,7 +439,7 @@
ethernet: ethernet@18000000 {
reg = <0x0 0x18000000 0x0 0x10000>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>;
reg-io-width = <2>;
smsc,irq-push-pull;
@@ -446,8 +471,8 @@
mmci: mmci@1c050000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x0 0x001c050000 0x0 0x1000>;
- interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>;
wp-gpios = <&sysreg 1 0>;
bus-width = <4>;
max-frequency = <25000000>;
@@ -471,9 +496,9 @@
gpu: gpu@2d000000 {
compatible = "arm,mali-midgard";
reg = <0x0 0x2d000000 0x0 0x200000>;
- interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "JOB", "MMU", "GPU";
clocks = <&gpu_core_clk>;
clock-names = "shadercores";
@@ -507,10 +532,10 @@
smmu_600: smmu@2ce00000 {
compatible = "arm,smmu-v3";
reg = <0 0x2ce00000 0 0x20000>;
- interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 74 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 76 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 77 IRQ_TYPE_EDGE_RISING 0>;
interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
#iommu-cells = <1>;
status = "disabled";
@@ -520,9 +545,9 @@
#iommu-cells = <1>;
compatible = "arm,smmu-v3";
reg = <0x0 0x3f000000 0x0 0x5000000>;
- interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 229 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 230 IRQ_TYPE_EDGE_RISING 0>;
interrupt-names = "eventq", "cmdq-sync", "gerror";
dma-coherent;
status = "disabled";
@@ -532,9 +557,9 @@
#iommu-cells = <1>;
compatible = "arm,smmu-v3";
reg = <HI(0x4002a00000) LO(0x4002a00000) 0x0 0x5000000>;
- interrupts = <GIC_SPI 481 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 482 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 483 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 481 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 482 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 483 IRQ_TYPE_EDGE_RISING 0>;
interrupt-names = "eventq", "cmdq-sync", "gerror";
dma-coherent;
status = "disabled";
@@ -545,7 +570,7 @@
#size-cells = <0>;
compatible = "arm,mali-d71";
reg = <HI(ADDRESSIFY(DPU_ADDR)) LO(ADDRESSIFY(DPU_ADDR)) 0 0x20000>;
- interrupts = <GIC_SPI DPU_IRQ IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI DPU_IRQ IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "DPU";
DPU_CLK_ATTR1;
@@ -630,7 +655,7 @@
trbe {
compatible = "arm,trace-buffer-extension";
- interrupts = <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW 0>;
};
trusty {
diff --git a/fdts/tc-fvp.dtsi b/fdts/tc-fvp.dtsi
index 9f3a9ac..1e14f0b 100644
--- a/fdts/tc-fvp.dtsi
+++ b/fdts/tc-fvp.dtsi
@@ -54,7 +54,7 @@
rtc@1c170000 {
compatible = "arm,pl031", "arm,primecell";
reg = <0x0 0x1C170000 0x0 0x1000>;
- interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&soc_refclk>;
clock-names = "apb_pclk";
};
@@ -62,7 +62,7 @@
kmi@1c060000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x0 0x001c060000 0x0 0x1000>;
- interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
@@ -70,7 +70,7 @@
kmi@1c070000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x0 0x001c070000 0x0 0x1000>;
- interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
@@ -79,6 +79,6 @@
compatible = "virtio,mmio";
reg = <0x0 0x1c130000 0x0 0x200>;
/* spec lists this wrong */
- interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH 0>;
};
};
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index 4946aca..ae37ce3 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -31,6 +31,10 @@
#define MHU_RX_INT_NUM 317
#define MHU_RX_INT_NAME "mhu_rx"
+#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu"
+#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a720-pmu"
+#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x4-pmu"
+
#define MPAM_ADDR 0x1 0x00010000 /* 0x1_0001_0000 */
#define UARTCLK_FREQ 5000000
@@ -193,22 +197,10 @@
};
#endif /* TARGET_FLAVOUR_FPGA */
- cpu-pmu {
-#if TARGET_FLAVOUR_FPGA
- interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>,
- <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>,
- <&CPU8>, <&CPU9>, <&CPU10>, <&CPU11>,
- <&CPU12>, <&CPU13>;
-#else
- interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>,
- <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
-#endif
- };
-
cmn-pmu {
compatible = "arm,ci-700";
reg = <0x0 0x50000000 0x0 0x10000000>;
- interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH 0>;
};
mbox_db_rx: mhu@MHU_RX_ADDR {
@@ -237,6 +229,36 @@
};
};
+ gic: interrupt-controller@GIC_CTRL_ADDR {
+ ppi-partitions {
+ ppi_partition_little: interrupt-partition-0 {
+ affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>;
+ };
+
+#if TARGET_FLAVOUR_FVP
+ ppi_partition_mid: interrupt-partition-1 {
+ affinity = <&CPU4>, <&CPU5>, <&CPU6>;
+ };
+
+ ppi_partition_big: interrupt-partition-2 {
+ affinity = <&CPU7>;
+ };
+#elif TARGET_FLAVOUR_FPGA
+ ppi_partition_mid: interrupt-partition-1 {
+ affinity = <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>, <&CPU8>;
+ };
+
+ ppi_partition_big: interrupt-partition-2 {
+ affinity = <&CPU9>, <&CPU10>, <&CPU11>, <&CPU12>, <&CPU13>;
+ };
+#endif
+ };
+ };
+
+ spe-pmu-big {
+ status = "okay";
+ };
+
smmu_700: iommu@3f000000 {
status = "okay";
};
diff --git a/fdts/tc3.dts b/fdts/tc3.dts
index c741be0..58c8edc 100644
--- a/fdts/tc3.dts
+++ b/fdts/tc3.dts
@@ -25,6 +25,10 @@
#define MHU_RX_INT_NUM 300
#define MHU_RX_INT_NAME "combined-mbx"
+#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu"
+#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a725-pmu"
+#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x925-pmu"
+
#define MPAM_ADDR 0x0 0x5f010000 /* 0x5f01_0000 */
#define UARTCLK_FREQ 3750000
@@ -67,11 +71,6 @@
};
};
- cpu-pmu {
- interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>,
- <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
- };
-
cs-pmu@0 {
compatible = "arm,coresight-pmu";
reg = <0x0 MCN_PMU_ADDR(0) 0x0 0xffc>;
@@ -92,6 +91,24 @@
reg = <0x0 MCN_PMU_ADDR(3) 0x0 0xffc>;
};
+ spe-pmu-mid {
+ status = "okay";
+ };
+
+ spe-pmu-big {
+ status = "okay";
+ };
+
+ dsu-pmu {
+ compatible = "arm,dsu-pmu";
+ cpus = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
+ };
+
+ ni-pmu {
+ compatible = "arm,ni-tower";
+ reg = <0x0 0x4f000000 0x0 0x4000000>;
+ };
+
sram: sram@6000000 {
cpu_scp_scmi_p2a: scp-shmem@80 {
compatible = "arm,scmi-shmem";
@@ -106,6 +123,22 @@
};
};
+ gic: interrupt-controller@GIC_CTRL_ADDR {
+ ppi-partitions {
+ ppi_partition_little: interrupt-partition-0 {
+ affinity = <&CPU0>, <&CPU1>;
+ };
+
+ ppi_partition_mid: interrupt-partition-1 {
+ affinity = <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>;
+ };
+
+ ppi_partition_big: interrupt-partition-2 {
+ affinity = <&CPU6>, <&CPU7>;
+ };
+ };
+ };
+
#if TARGET_FLAVOUR_FVP
smmu_700: iommu@3f000000 {
status = "okay";
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index 8e39529..abe34a4 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -16,6 +16,7 @@
((unsigned int)(((reg) >> (feat)) & mask))
#define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _supported(void) \
{ \
if ((guard) == FEAT_STATE_DISABLED) { \
@@ -28,6 +29,7 @@
}
#define CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _present(void) \
{ \
return (ISOLATE_FIELD(read_ ## idreg(), idfield, mask) >= idval) \
@@ -68,6 +70,7 @@
*/
/* GENTIMER */
+__attribute__((always_inline))
static inline bool is_armv7_gentimer_present(void)
{
return ISOLATE_FIELD(read_id_pfr1(), ID_PFR1_GENTIMER_SHIFT,
@@ -111,6 +114,7 @@
ID_DFR0_PERFMON_MASK, 3U)
/* FEAT_MTPMU */
+__attribute__((always_inline))
static inline bool is_feat_mtpmu_present(void)
{
unsigned int mtpmu = ISOLATE_FIELD(read_id_dfr1(), ID_DFR1_MTPMU_SHIFT,
@@ -124,39 +128,71 @@
* code. In fact, EL2 context switching is only needed for AArch64 (since
* there is no secure AArch32 EL2), so just disable these features here.
*/
+__attribute__((always_inline))
static inline bool is_feat_twed_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ecv_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ecv_v2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_csv2_2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_csv2_3_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ras_supported(void) { return false; }
/* The following features are supported in AArch64 only. */
+__attribute__((always_inline))
static inline bool is_feat_vhe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sel2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_fgt_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_tcr2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_spe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_rng_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_gcs_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_mte2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_mpam_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_hcx_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sve_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_brbe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_trbe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_nv2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sme_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sme2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s2poe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s1poe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sxpoe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s2pie_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s1pie_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sxpie_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_uao_present(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_nmi_present(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ebep_present(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sebep_present(void) { return false; }
#endif /* ARCH_FEATURES_H */
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index e4e8e71..52ed2b9 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -114,9 +114,14 @@
* Definitions for EL2 system registers for save/restore routine
******************************************************************************/
#define CNTPOFF_EL2 S3_4_C14_C0_6
-#define HAFGRTR_EL2 S3_4_C3_C1_6
+#define HDFGRTR2_EL2 S3_4_C3_C1_0
+#define HDFGWTR2_EL2 S3_4_C3_C1_1
+#define HFGRTR2_EL2 S3_4_C3_C1_2
+#define HFGWTR2_EL2 S3_4_C3_C1_3
#define HDFGRTR_EL2 S3_4_C3_C1_4
#define HDFGWTR_EL2 S3_4_C3_C1_5
+#define HAFGRTR_EL2 S3_4_C3_C1_6
+#define HFGITR2_EL2 S3_4_C3_C1_7
#define HFGITR_EL2 S3_4_C1_C1_6
#define HFGRTR_EL2 S3_4_C1_C1_4
#define HFGWTR_EL2 S3_4_C1_C1_5
@@ -331,6 +336,7 @@
#define ID_AA64MMFR0_EL1_FGT_SHIFT U(56)
#define ID_AA64MMFR0_EL1_FGT_MASK ULL(0xf)
+#define FGT2_IMPLEMENTED ULL(0x2)
#define FGT_IMPLEMENTED ULL(0x1)
#define FGT_NOT_IMPLEMENTED ULL(0x0)
@@ -574,6 +580,7 @@
/* SCR definitions */
#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5))
#define SCR_NSE_SHIFT U(62)
+#define SCR_FGTEN2_BIT (UL(1) << 59)
#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT)
#define SCR_GPF_BIT (UL(1) << 48)
#define SCR_TWEDEL_SHIFT U(30)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 24b48bb..f03c9d5 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -16,6 +16,7 @@
((unsigned int)(((reg) >> (feat)) & mask))
#define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _supported(void) \
{ \
if ((guard) == FEAT_STATE_DISABLED) { \
@@ -28,6 +29,7 @@
}
#define CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _present(void) \
{ \
return (ISOLATE_FIELD(read_ ## idreg(), idfield, mask) >= idval) \
@@ -130,8 +132,11 @@
* +----------------------------+
* | FEAT_MTPMU |
* +----------------------------+
+ * | FEAT_FGT2 |
+ * +----------------------------+
*/
+__attribute__((always_inline))
static inline bool is_armv7_gentimer_present(void)
{
/* The Generic Timer is always present in an ARMv8-A implementation */
@@ -160,6 +165,7 @@
(ID_AA64ISAR2_APA3_MASK << ID_AA64ISAR2_APA3_SHIFT)), 1U)
/* PAUTH */
+__attribute__((always_inline))
static inline bool is_armv8_3_pauth_present(void)
{
uint64_t mask_id_aa64isar1 =
@@ -216,6 +222,10 @@
CREATE_FEATURE_FUNCS(feat_fgt, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
ID_AA64MMFR0_EL1_FGT_MASK, 1U, ENABLE_FEAT_FGT)
+/* FEAT_FGT2: Fine-grained traps extended */
+CREATE_FEATURE_FUNCS(feat_fgt2, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
+ ID_AA64MMFR0_EL1_FGT_MASK, FGT2_IMPLEMENTED, ENABLE_FEAT_FGT2)
+
/* FEAT_ECV: Enhanced Counter Virtualization */
CREATE_FEATURE_FUNCS(feat_ecv, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV_SHIFT,
ID_AA64MMFR0_EL1_ECV_MASK, 1U, ENABLE_FEAT_ECV)
@@ -238,6 +248,7 @@
CREATE_FEATURE_FUNCS(feat_s1poe, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1POE_SHIFT,
ID_AA64MMFR3_EL1_S1POE_MASK, 1U, ENABLE_FEAT_S1POE)
+__attribute__((always_inline))
static inline bool is_feat_sxpoe_supported(void)
{
return is_feat_s1poe_supported() || is_feat_s2poe_supported();
@@ -251,6 +262,7 @@
CREATE_FEATURE_FUNCS(feat_s1pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1PIE_SHIFT,
ID_AA64MMFR3_EL1_S1PIE_MASK, 1U, ENABLE_FEAT_S1PIE)
+__attribute__((always_inline))
static inline bool is_feat_sxpie_supported(void)
{
return is_feat_s1pie_supported() || is_feat_s2pie_supported();
@@ -277,6 +289,7 @@
* 0x11: v1.1 Armv8.4 or later
*
*/
+__attribute__((always_inline))
static inline bool is_feat_mpam_present(void)
{
unsigned int ret = (unsigned int)((((read_id_aa64pfr0_el1() >>
@@ -392,6 +405,7 @@
* Function to get hardware granularity support
******************************************************************************/
+__attribute__((always_inline))
static inline bool is_feat_tgran4K_present(void)
{
unsigned int tgranx = ISOLATE_FIELD(read_id_aa64mmfr0_el1(),
@@ -402,6 +416,7 @@
CREATE_FEATURE_PRESENT(feat_tgran16K, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_TGRAN16_SHIFT,
ID_AA64MMFR0_EL1_TGRAN16_MASK, TGRAN16_IMPLEMENTED)
+__attribute__((always_inline))
static inline bool is_feat_tgran64K_present(void)
{
unsigned int tgranx = ISOLATE_FIELD(read_id_aa64mmfr0_el1(),
@@ -414,6 +429,7 @@
ID_AA64DFR0_PMUVER_MASK, 1U)
/* FEAT_MTPMU */
+__attribute__((always_inline))
static inline bool is_feat_mtpmu_present(void)
{
unsigned int mtpmu = ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_MTPMU_SHIFT,
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 1e2f84b..a892654 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -639,6 +639,13 @@
/* Armv8.9 system registers */
DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr3_el1, ID_AA64MMFR3_EL1)
+/* Armv8.9 FEAT_FGT2 Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgrtr2_el2, HDFGRTR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgwtr2_el2, HDFGWTR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hfgitr2_el2, HFGITR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hfgrtr2_el2, HFGRTR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hfgwtr2_el2, HFGWTR2_EL2)
+
/* FEAT_TCR2 Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(tcr2_el1, TCR2_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(tcr2_el2, TCR2_EL2)
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
index 9f82399..b9b0e3d 100644
--- a/include/arch/aarch64/el2_common_macros.S
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -408,7 +408,7 @@
* -----------------------------------------------------------
*/
isb
- ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+ ldp x28, x29, [sp, #CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index b4c5c1b..60c5a0c 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -437,7 +437,7 @@
* -----------------------------------------------------------
*/
isb
- ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+ ldp x28, x29, [sp, #CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index bfda31b..ca46eb1 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -150,6 +150,7 @@
/* GICD_TYPER shifts and masks */
#define TYPER_ESPI U(1 << 8)
#define TYPER_DVIS U(1 << 18)
+#define TYPER_LPIS U(1 << 17)
#define TYPER_ESPI_RANGE_MASK U(0x1f)
#define TYPER_ESPI_RANGE_SHIFT U(27)
#define TYPER_ESPI_RANGE U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT)
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
index 633f173..b95cd32 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
@@ -78,4 +78,13 @@
#define S32CC_CLK_A53_CORE_DIV2 S32CC_ARCH_CLK(4)
#define S32CC_CLK_A53_CORE_DIV10 S32CC_ARCH_CLK(5)
+/* XBAR clock*/
+#define S32CC_CLK_MC_CGM0_MUX0 S32CC_ARCH_CLK(6)
+#define S32CC_CLK_XBAR_2X S32CC_ARCH_CLK(7)
+#define S32CC_CLK_XBAR S32CC_ARCH_CLK(8)
+#define S32CC_CLK_XBAR_DIV2 S32CC_ARCH_CLK(9)
+#define S32CC_CLK_XBAR_DIV3 S32CC_ARCH_CLK(10)
+#define S32CC_CLK_XBAR_DIV4 S32CC_ARCH_CLK(11)
+#define S32CC_CLK_XBAR_DIV6 S32CC_ARCH_CLK(12)
+
#endif /* S32CC_CLK_IDS_H */
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
index 41fc6f4..703713b 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -17,6 +17,8 @@
s32cc_clk_t,
s32cc_pll_t,
s32cc_pll_out_div_t,
+ s32cc_dfs_t,
+ s32cc_dfs_div_t,
s32cc_clkmux_t,
s32cc_shared_clkmux_t,
s32cc_fixed_div_t,
@@ -27,6 +29,8 @@
S32CC_FXOSC,
S32CC_SIRC,
S32CC_ARM_PLL,
+ S32CC_ARM_DFS,
+ S32CC_CGM0,
S32CC_CGM1,
};
@@ -122,6 +126,38 @@
.index = (INDEX), \
}
+struct s32cc_dfs {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ enum s32cc_clk_source instance;
+ uintptr_t base;
+};
+
+#define S32CC_DFS_INIT(PARENT, INSTANCE) \
+{ \
+ .desc = { \
+ .type = s32cc_dfs_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .instance = (INSTANCE), \
+}
+
+struct s32cc_dfs_div {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ uint32_t index;
+ unsigned long freq;
+};
+
+#define S32CC_DFS_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_dfs_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .index = (INDEX), \
+}
+
struct s32cc_fixed_div {
struct s32cc_clk_obj desc;
struct s32cc_clk_obj *parent;
@@ -151,22 +187,26 @@
size_t n_clks;
};
-#define S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) \
-{ \
- .desc = { \
- .type = s32cc_clk_t, \
- }, \
- .module = &(PARENT_MODULE).desc, \
- .min_freq = (MIN_F), \
- .max_freq = (MAX_F), \
+#define S32CC_FREQ_CLK(PARENT_MODULE, PARENT, MIN_F, MAX_F) \
+{ \
+ .desc = { \
+ .type = s32cc_clk_t, \
+ }, \
+ .pclock = (PARENT), \
+ .module = (PARENT_MODULE), \
+ .min_freq = (MIN_F), \
+ .max_freq = (MAX_F), \
}
#define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \
- S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F)
+ S32CC_FREQ_CLK(&(PARENT_MODULE).desc, NULL, MIN_F, MAX_F)
#define S32CC_MODULE_CLK(PARENT_MODULE) \
S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0)
+#define S32CC_CHILD_CLK(PARENT, MIN_F, MAX_F) \
+ S32CC_FREQ_CLK(NULL, &(PARENT), MIN_F, MAX_F)
+
static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
{
uintptr_t osc_addr;
@@ -237,4 +277,20 @@
return (struct s32cc_fixed_div *)fdiv_addr;
}
+static inline struct s32cc_dfs *s32cc_obj2dfs(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t dfs_addr;
+
+ dfs_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs, desc);
+ return (struct s32cc_dfs *)dfs_addr;
+}
+
+static inline struct s32cc_dfs_div *s32cc_obj2dfsdiv(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t dfs_div_addr;
+
+ dfs_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs_div, desc);
+ return (struct s32cc_dfs_div *)dfs_div_addr;
+}
+
#endif /* S32CC_CLK_MODULES_H */
diff --git a/include/lib/cpus/aarch64/cortex_a520.h b/include/lib/cpus/aarch64/cortex_a520.h
index 619a15d..ed3401d 100644
--- a/include/lib/cpus/aarch64/cortex_a520.h
+++ b/include/lib/cpus/aarch64/cortex_a520.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,6 +15,7 @@
#define CORTEX_A520_CPUACTLR_EL1 S3_0_C15_C1_0
#define CORTEX_A520_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_A520_CPUECTLR_EL1_EXTLLC_BIT U(0)
/*******************************************************************************
* CPU Auxiliary Control register 1 specific definitions.
diff --git a/include/lib/cpus/aarch64/cortex_a720.h b/include/lib/cpus/aarch64/cortex_a720.h
index fb27f79..129c1ee 100644
--- a/include/lib/cpus/aarch64/cortex_a720.h
+++ b/include/lib/cpus/aarch64/cortex_a720.h
@@ -23,6 +23,11 @@
#define CORTEX_A720_CPUACTLR2_EL1 S3_0_C15_C1_1
/*******************************************************************************
+ * CPU Auxiliary Control register 4 specific definitions.
+ ******************************************************************************/
+#define CORTEX_A720_CPUACTLR4_EL1 S3_0_C15_C1_3
+
+/*******************************************************************************
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_A720_CPUECTLR_EL1 S3_0_C15_C1_4
diff --git a/include/lib/cpus/aarch64/cortex_a725.h b/include/lib/cpus/aarch64/cortex_a725.h
index 123c5ab..cb1c099 100644
--- a/include/lib/cpus/aarch64/cortex_a725.h
+++ b/include/lib/cpus/aarch64/cortex_a725.h
@@ -13,6 +13,7 @@
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_A725_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_A725_CPUECTLR_EL1_EXTLLC_BIT U(0)
/*******************************************************************************
* CPU Power Control register specific definitions
diff --git a/include/lib/cpus/aarch64/cortex_x4.h b/include/lib/cpus/aarch64/cortex_x4.h
index 433687b..d81c3ca 100644
--- a/include/lib/cpus/aarch64/cortex_x4.h
+++ b/include/lib/cpus/aarch64/cortex_x4.h
@@ -28,4 +28,10 @@
******************************************************************************/
#define CORTEX_X4_CPUACTLR3_EL1 S3_0_C15_C1_2
+/*******************************************************************************
+ * CPU Auxiliary control register 5 specific definitions
+ ******************************************************************************/
+#define CORTEX_X4_CPUACTLR5_EL1 S3_0_C15_C8_0
+#define CORTEX_X4_CPUACTLR5_EL1_BIT_14 (ULL(1) << 14)
+
#endif /* CORTEX_X4_H */
diff --git a/include/lib/cpus/aarch64/cortex_x925.h b/include/lib/cpus/aarch64/cortex_x925.h
index 38aafcf..b0d0ca4 100644
--- a/include/lib/cpus/aarch64/cortex_x925.h
+++ b/include/lib/cpus/aarch64/cortex_x925.h
@@ -13,6 +13,7 @@
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_X925_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_X925_CPUECTLR_EL1_EXTLLC_BIT U(0)
/*******************************************************************************
* CPU Power Control register specific definitions
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 6faef5d..d49d82e 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -456,6 +456,14 @@
msr \_reg, x0
.endm
+.macro sysreg_bitfield_insert_from_gpr _reg:req, _gpr:req, _lsb:req, _width:req
+ /* Source value in register for BFI */
+ mov x1, \_gpr
+ mrs x0, \_reg
+ bfi x0, x1, #\_lsb, #\_width
+ msr \_reg, x0
+.endm
+
/*
* Apply erratum
*
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index acf111b..7c10506 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -7,6 +7,7 @@
#ifndef CONTEXT_H
#define CONTEXT_H
+#include <lib/el3_runtime/context_el1.h>
#include <lib/el3_runtime/context_el2.h>
#include <lib/el3_runtime/cpu_data.h>
#include <lib/utils_def.h>
@@ -82,151 +83,10 @@
#endif /* FFH_SUPPORT */
/*******************************************************************************
- * Constants that allow assembler code to access members of and the
- * 'el1_sys_regs' structure at their correct offsets. Note that some of the
- * registers are only 32-bits wide but are stored as 64-bit values for
- * convenience
- ******************************************************************************/
-#define CTX_EL1_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
-#define CTX_SPSR_EL1 U(0x0)
-#define CTX_ELR_EL1 U(0x8)
-#define CTX_SCTLR_EL1 U(0x10)
-#define CTX_TCR_EL1 U(0x18)
-#define CTX_CPACR_EL1 U(0x20)
-#define CTX_CSSELR_EL1 U(0x28)
-#define CTX_SP_EL1 U(0x30)
-#define CTX_ESR_EL1 U(0x38)
-#define CTX_TTBR0_EL1 U(0x40)
-#define CTX_TTBR1_EL1 U(0x48)
-#define CTX_MAIR_EL1 U(0x50)
-#define CTX_AMAIR_EL1 U(0x58)
-#define CTX_ACTLR_EL1 U(0x60)
-#define CTX_TPIDR_EL1 U(0x68)
-#define CTX_TPIDR_EL0 U(0x70)
-#define CTX_TPIDRRO_EL0 U(0x78)
-#define CTX_PAR_EL1 U(0x80)
-#define CTX_FAR_EL1 U(0x88)
-#define CTX_AFSR0_EL1 U(0x90)
-#define CTX_AFSR1_EL1 U(0x98)
-#define CTX_CONTEXTIDR_EL1 U(0xa0)
-#define CTX_VBAR_EL1 U(0xa8)
-#define CTX_MDCCINT_EL1 U(0xb0)
-#define CTX_MDSCR_EL1 U(0xb8)
-
-#define CTX_AARCH64_END U(0xc0) /* Align to the next 16 byte boundary */
-
-/*
- * If the platform is AArch64-only, there is no need to save and restore these
- * AArch32 registers.
- */
-#if CTX_INCLUDE_AARCH32_REGS
-#define CTX_SPSR_ABT (CTX_AARCH64_END + U(0x0))
-#define CTX_SPSR_UND (CTX_AARCH64_END + U(0x8))
-#define CTX_SPSR_IRQ (CTX_AARCH64_END + U(0x10))
-#define CTX_SPSR_FIQ (CTX_AARCH64_END + U(0x18))
-#define CTX_DACR32_EL2 (CTX_AARCH64_END + U(0x20))
-#define CTX_IFSR32_EL2 (CTX_AARCH64_END + U(0x28))
-#define CTX_AARCH32_END (CTX_AARCH64_END + U(0x30)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_AARCH32_END CTX_AARCH64_END
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-
-/*
- * If the timer registers aren't saved and restored, we don't have to reserve
- * space for them in the context
- */
-#if NS_TIMER_SWITCH
-#define CTX_CNTP_CTL_EL0 (CTX_AARCH32_END + U(0x0))
-#define CTX_CNTP_CVAL_EL0 (CTX_AARCH32_END + U(0x8))
-#define CTX_CNTV_CTL_EL0 (CTX_AARCH32_END + U(0x10))
-#define CTX_CNTV_CVAL_EL0 (CTX_AARCH32_END + U(0x18))
-#define CTX_CNTKCTL_EL1 (CTX_AARCH32_END + U(0x20))
-#define CTX_TIMER_SYSREGS_END (CTX_AARCH32_END + U(0x30)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END
-#endif /* NS_TIMER_SWITCH */
-
-#if ENABLE_FEAT_MTE2
-#define CTX_TFSRE0_EL1 (CTX_TIMER_SYSREGS_END + U(0x0))
-#define CTX_TFSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x8))
-#define CTX_RGSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x10))
-#define CTX_GCR_EL1 (CTX_TIMER_SYSREGS_END + U(0x18))
-#define CTX_MTE_REGS_END (CTX_TIMER_SYSREGS_END + U(0x20)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_MTE_REGS_END CTX_TIMER_SYSREGS_END
-#endif /* ENABLE_FEAT_MTE2 */
-
-#if ENABLE_FEAT_RAS
-#define CTX_DISR_EL1 (CTX_MTE_REGS_END + U(0x0))
-#define CTX_RAS_REGS_END (CTX_MTE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_RAS_REGS_END CTX_MTE_REGS_END
-#endif /* ENABLE_FEAT_RAS */
-
-#if ENABLE_FEAT_S1PIE
-#define CTX_PIRE0_EL1 (CTX_RAS_REGS_END + U(0x0))
-#define CTX_PIR_EL1 (CTX_RAS_REGS_END + U(0x8))
-#define CTX_S1PIE_REGS_END (CTX_RAS_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_S1PIE_REGS_END CTX_RAS_REGS_END
-#endif /* ENABLE_FEAT_S1PIE */
-
-#if ENABLE_FEAT_S1POE
-#define CTX_POR_EL1 (CTX_S1PIE_REGS_END + U(0x0))
-#define CTX_S1POE_REGS_END (CTX_S1PIE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_S1POE_REGS_END CTX_S1PIE_REGS_END
-#endif /* ENABLE_FEAT_S1POE */
-
-#if ENABLE_FEAT_S2POE
-#define CTX_S2POR_EL1 (CTX_S1POE_REGS_END + U(0x0))
-#define CTX_S2POE_REGS_END (CTX_S1POE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_S2POE_REGS_END CTX_S1POE_REGS_END
-#endif /* ENABLE_FEAT_S2POE */
-
-#if ENABLE_FEAT_TCR2
-#define CTX_TCR2_EL1 (CTX_S2POE_REGS_END + U(0x0))
-#define CTX_TCR2_REGS_END (CTX_S2POE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_TCR2_REGS_END CTX_S2POE_REGS_END
-#endif /* ENABLE_FEAT_TCR2 */
-
-#if ENABLE_TRF_FOR_NS
-#define CTX_TRFCR_EL1 (CTX_TCR2_REGS_END + U(0x0))
-#define CTX_TRF_REGS_END (CTX_TCR2_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_TRF_REGS_END CTX_TCR2_REGS_END
-#endif /* ENABLE_TRF_FOR_NS */
-
-#if ENABLE_FEAT_CSV2_2
-#define CTX_SCXTNUM_EL0 (CTX_TRF_REGS_END + U(0x0))
-#define CTX_SCXTNUM_EL1 (CTX_TRF_REGS_END + U(0x8))
-#define CTX_CSV2_2_REGS_END (CTX_TRF_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_CSV2_2_REGS_END CTX_TRF_REGS_END
-#endif /* ENABLE_FEAT_CSV2_2 */
-
-#if ENABLE_FEAT_GCS
-#define CTX_GCSCR_EL1 (CTX_CSV2_2_REGS_END + U(0x0))
-#define CTX_GCSCRE0_EL1 (CTX_CSV2_2_REGS_END + U(0x8))
-#define CTX_GCSPR_EL1 (CTX_CSV2_2_REGS_END + U(0x10))
-#define CTX_GCSPR_EL0 (CTX_CSV2_2_REGS_END + U(0x18))
-#define CTX_GCS_REGS_END (CTX_CSV2_2_REGS_END + U(0x20)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_GCS_REGS_END CTX_CSV2_2_REGS_END
-#endif /* ENABLE_FEAT_GCS */
-
-/*
- * End of EL1 system registers.
- */
-#define CTX_EL1_SYSREGS_END CTX_GCS_REGS_END
-
-/*******************************************************************************
* Constants that allow assembler code to access members of and the 'fp_regs'
* structure at their correct offsets.
******************************************************************************/
-# define CTX_FPREGS_OFFSET (CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END)
+# define CTX_FPREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
#if CTX_INCLUDE_FPREGS
#define CTX_FP_Q0 U(0x0)
#define CTX_FP_Q1 U(0x10)
@@ -280,9 +140,53 @@
#define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */
/*******************************************************************************
+ * Registers related to ERRATA_SPECULATIVE_AT
+ *
+ * This is essential as with EL1 and EL2 context registers being decoupled,
+ * both will not be present for a given build configuration.
+ * As ERRATA_SPECULATIVE_AT errata requires SCTLR_EL1 and TCR_EL1 registers
+ * independent of the above logic, we need explicit context entries to be
+ * reserved for these registers.
+ *
+ * NOTE: Based on this we end up with following different configurations depending
+ * on the presence of errata and inclusion of EL1 or EL2 context.
+ *
+ * ============================================================================
+ * | ERRATA_SPECULATIVE_AT | EL1 context| Memory allocation(Sctlr_el1,Tcr_el1)|
+ * ============================================================================
+ * | 0 | 0 | None |
+ * | 0 | 1 | EL1 C-Context structure |
+ * | 1 | 0 | Errata Context Offset Entries |
+ * | 1 | 1 | Errata Context Offset Entries |
+ * ============================================================================
+ *
+ * In the above table, when ERRATA_SPECULATIVE_AT=1, EL1_Context=0, it implies
+ * there is only EL2 context and memory for SCTLR_EL1 and TCR_EL1 registers is
+ * reserved explicitly under ERRATA_SPECULATIVE_AT build flag here.
+ *
+ * In situations when EL1_Context=1 and ERRATA_SPECULATIVE_AT=1, since SCTLR_EL1
+ * and TCR_EL1 registers will be modified under errata and it happens at the
+ * early in the codeflow prior to el1 context (save and restore operations),
+ * context memory still will be reserved under the errata logic here explicitly.
+ * These registers will not be part of EL1 context save & restore routines.
+ *
+ * Only when ERRATA_SPECULATIVE_AT=0, EL1_Context=1, for this combination,
+ * SCTLR_EL1 and TCR_EL1 will be part of EL1 context structure (context_el1.h)
+ * -----------------------------------------------------------------------------
+ ******************************************************************************/
+#define CTX_ERRATA_SPEC_AT_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
+#if ERRATA_SPECULATIVE_AT
+#define CTX_ERRATA_SPEC_AT_SCTLR_EL1 U(0x0)
+#define CTX_ERRATA_SPEC_AT_TCR_EL1 U(0x8)
+#define CTX_ERRATA_SPEC_AT_END U(0x10) /* Align to the next 16 byte boundary */
+#else
+#define CTX_ERRATA_SPEC_AT_END U(0x0)
+#endif /* ERRATA_SPECULATIVE_AT */
+
+/*******************************************************************************
* Registers related to ARMv8.3-PAuth.
******************************************************************************/
-#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
+#define CTX_PAUTH_REGS_OFFSET (CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_END)
#if CTX_INCLUDE_PAUTH_REGS
#define CTX_PACIAKEY_LO U(0x0)
#define CTX_PACIAKEY_HI U(0x8)
@@ -325,13 +229,16 @@
/* Constants to determine the size of individual context structures */
#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT)
-#define CTX_EL1_SYSREGS_ALL (CTX_EL1_SYSREGS_END >> DWORD_SHIFT)
#if CTX_INCLUDE_FPREGS
# define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT)
#endif
#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT)
#define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT)
+
+#if ERRATA_SPECULATIVE_AT
+#define CTX_ERRATA_SPEC_AT_ALL (CTX_ERRATA_SPEC_AT_END >> DWORD_SHIFT)
+#endif
#if CTX_INCLUDE_PAUTH_REGS
# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT)
#endif
@@ -346,12 +253,6 @@
DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL);
/*
- * AArch64 EL1 system register context structure for preserving the
- * architectural state during world switches.
- */
-DEFINE_REG_STRUCT(el1_sysregs, CTX_EL1_SYSREGS_ALL);
-
-/*
* AArch64 floating point register context structure for preserving
* the floating point state during switches from one security state to
* another.
@@ -369,6 +270,11 @@
/* Function pointer used by CVE-2018-3639 dynamic mitigation */
DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL);
+/* Registers associated to Errata_Speculative */
+#if ERRATA_SPECULATIVE_AT
+DEFINE_REG_STRUCT(errata_speculative_at, CTX_ERRATA_SPEC_AT_ALL);
+#endif
+
/* Registers associated to ARMv8.3-PAuth */
#if CTX_INCLUDE_PAUTH_REGS
DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL);
@@ -393,17 +299,22 @@
typedef struct cpu_context {
gp_regs_t gpregs_ctx;
el3_state_t el3state_ctx;
- el1_sysregs_t el1_sysregs_ctx;
#if CTX_INCLUDE_FPREGS
fp_regs_t fpregs_ctx;
#endif
cve_2018_3639_t cve_2018_3639_ctx;
+#if ERRATA_SPECULATIVE_AT
+ errata_speculative_at_t errata_speculative_at_ctx;
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
pauth_t pauth_ctx;
#endif
+ el1_sysregs_t el1_sysregs_ctx;
+
#if CTX_INCLUDE_EL2_REGS
el2_sysregs_t el2_sysregs_ctx;
#endif
@@ -433,6 +344,11 @@
#endif
#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx)
#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx)
+
+#if ERRATA_SPECULATIVE_AT
+#define get_errata_speculative_at_ctx(h) (&((cpu_context_t *) h)->errata_speculative_at_ctx)
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx)
#endif
@@ -448,9 +364,6 @@
CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx),
assert_core_context_el3state_offset_mismatch);
-CASSERT(CTX_EL1_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el1_sysregs_ctx),
- assert_core_context_el1_sys_offset_mismatch);
-
#if CTX_INCLUDE_FPREGS
CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx),
assert_core_context_fp_offset_mismatch);
@@ -459,6 +372,11 @@
CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx),
assert_core_context_cve_2018_3639_offset_mismatch);
+#if ERRATA_SPECULATIVE_AT
+CASSERT(CTX_ERRATA_SPEC_AT_OFFSET == __builtin_offsetof(cpu_context_t, errata_speculative_at_ctx),
+ assert_core_context_errata_speculative_at_offset_mismatch);
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx),
assert_core_context_pauth_offset_mismatch);
diff --git a/include/lib/el3_runtime/context_el1.h b/include/lib/el3_runtime/context_el1.h
new file mode 100644
index 0000000..038de25
--- /dev/null
+++ b/include/lib/el3_runtime/context_el1.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CONTEXT_EL1_H
+#define CONTEXT_EL1_H
+
+#ifndef __ASSEMBLER__
+
+/*******************************************************************************
+ * EL1 Registers:
+ * AArch64 EL1 system register context structure for preserving the
+ * architectural state during world switches.
+ ******************************************************************************/
+
+typedef struct el1_common_regs {
+ uint64_t spsr_el1;
+ uint64_t elr_el1;
+
+#if (!ERRATA_SPECULATIVE_AT)
+ uint64_t sctlr_el1;
+ uint64_t tcr_el1;
+#endif /* ERRATA_SPECULATIVE_AT=0 */
+
+ uint64_t cpacr_el1;
+ uint64_t csselr_el1;
+ uint64_t sp_el1;
+ uint64_t esr_el1;
+ uint64_t ttbr0_el1;
+ uint64_t ttbr1_el1;
+ uint64_t mair_el1;
+ uint64_t amair_el1;
+ uint64_t actlr_el1;
+ uint64_t tpidr_el1;
+ uint64_t tpidr_el0;
+ uint64_t tpidrro_el0;
+ uint64_t par_el1;
+ uint64_t far_el1;
+ uint64_t afsr0_el1;
+ uint64_t afsr1_el1;
+ uint64_t contextidr_el1;
+ uint64_t vbar_el1;
+ uint64_t mdccint_el1;
+ uint64_t mdscr_el1;
+} el1_common_regs_t;
+
+typedef struct el1_aarch32_regs {
+ uint64_t spsr_abt;
+ uint64_t spsr_und;
+ uint64_t spsr_irq;
+ uint64_t spsr_fiq;
+ uint64_t dacr32_el2;
+ uint64_t ifsr32_el2;
+} el1_aarch32_regs_t;
+
+typedef struct el1_arch_timer_regs {
+ uint64_t cntp_ctl_el0;
+ uint64_t cntp_cval_el0;
+ uint64_t cntv_ctl_el0;
+ uint64_t cntv_cval_el0;
+ uint64_t cntkctl_el1;
+} el1_arch_timer_regs_t;
+
+typedef struct el1_mte2_regs {
+ uint64_t tfsre0_el1;
+ uint64_t tfsr_el1;
+ uint64_t rgsr_el1;
+ uint64_t gcr_el1;
+} el1_mte2_regs_t;
+
+typedef struct el1_ras_regs {
+ uint64_t disr_el1;
+} el1_ras_regs_t;
+
+typedef struct el1_s1pie_regs {
+ uint64_t pire0_el1;
+ uint64_t pir_el1;
+} el1_s1pie_regs_t;
+
+typedef struct el1_s1poe_regs {
+ uint64_t por_el1;
+} el1_s1poe_regs_t;
+
+typedef struct el1_s2poe_regs {
+ uint64_t s2por_el1;
+} el1_s2poe_regs_t;
+
+typedef struct el1_tcr2_regs {
+ uint64_t tcr2_el1;
+} el1_tcr2_regs_t;
+
+typedef struct el1_trf_regs {
+ uint64_t trfcr_el1;
+} el1_trf_regs_t;
+
+typedef struct el1_csv2_2_regs {
+ uint64_t scxtnum_el0;
+ uint64_t scxtnum_el1;
+} el1_csv2_2_regs_t;
+
+typedef struct el1_gcs_regs {
+ uint64_t gcscr_el1;
+ uint64_t gcscre0_el1;
+ uint64_t gcspr_el1;
+ uint64_t gcspr_el0;
+} el1_gcs_regs_t;
+
+typedef struct el1_sysregs {
+
+ el1_common_regs_t common;
+
+#if CTX_INCLUDE_AARCH32_REGS
+ el1_aarch32_regs_t el1_aarch32;
+#endif
+
+#if NS_TIMER_SWITCH
+ el1_arch_timer_regs_t arch_timer;
+#endif
+
+#if ENABLE_FEAT_MTE2
+ el1_mte2_regs_t mte2;
+#endif
+
+#if ENABLE_FEAT_RAS
+ el1_ras_regs_t ras;
+#endif
+
+#if ENABLE_FEAT_S1PIE
+ el1_s1pie_regs_t s1pie;
+#endif
+
+#if ENABLE_FEAT_S1POE
+ el1_s1poe_regs_t s1poe;
+#endif
+
+#if ENABLE_FEAT_S2POE
+ el1_s2poe_regs_t s2poe;
+#endif
+
+#if ENABLE_FEAT_TCR2
+ el1_tcr2_regs_t tcr2;
+#endif
+
+#if ENABLE_TRF_FOR_NS
+ el1_trf_regs_t trf;
+#endif
+
+#if ENABLE_FEAT_CSV2_2
+ el1_csv2_2_regs_t csv2_2;
+#endif
+
+#if ENABLE_FEAT_GCS
+ el1_gcs_regs_t gcs;
+#endif
+
+} el1_sysregs_t;
+
+
+/*
+ * Macros to access members related to individual features of the el1_sysregs_t
+ * structures.
+ */
+
+#define read_el1_ctx_common(ctx, reg) (((ctx)->common).reg)
+
+#define write_el1_ctx_common(ctx, reg, val) ((((ctx)->common).reg) \
+ = (uint64_t) (val))
+
+#if NS_TIMER_SWITCH
+#define read_el1_ctx_arch_timer(ctx, reg) (((ctx)->arch_timer).reg)
+#define write_el1_ctx_arch_timer(ctx, reg, val) ((((ctx)->arch_timer).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_arch_timer(ctx, reg) ULL(0)
+#define write_el1_ctx_arch_timer(ctx, reg, val)
+#endif /* NS_TIMER_SWITCH */
+
+#if CTX_INCLUDE_AARCH32_REGS
+#define read_el1_ctx_aarch32(ctx, reg) (((ctx)->el1_aarch32).reg)
+#define write_el1_ctx_aarch32(ctx, reg, val) ((((ctx)->el1_aarch32).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_aarch32(ctx, reg) ULL(0)
+#define write_el1_ctx_aarch32(ctx, reg, val)
+#endif /* CTX_INCLUDE_AARCH32_REGS */
+
+#if ENABLE_FEAT_MTE2
+#define read_el1_ctx_mte2(ctx, reg) (((ctx)->mte2).reg)
+#define write_el1_ctx_mte2(ctx, reg, val) ((((ctx)->mte2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_mte2(ctx, reg) ULL(0)
+#define write_el1_ctx_mte2(ctx, reg, val)
+#endif /* ENABLE_FEAT_MTE2 */
+
+#if ENABLE_FEAT_RAS
+#define read_el1_ctx_ras(ctx, reg) (((ctx)->ras).reg)
+#define write_el1_ctx_ras(ctx, reg, val) ((((ctx)->ras).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_ras(ctx, reg) ULL(0)
+#define write_el1_ctx_ras(ctx, reg, val)
+#endif /* ENABLE_FEAT_RAS */
+
+#if ENABLE_FEAT_S1PIE
+#define read_el1_ctx_s1pie(ctx, reg) (((ctx)->s1pie).reg)
+#define write_el1_ctx_s1pie(ctx, reg, val) ((((ctx)->s1pie).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_s1pie(ctx, reg) ULL(0)
+#define write_el1_ctx_s1pie(ctx, reg, val)
+#endif /* ENABLE_FEAT_S1PIE */
+
+#if ENABLE_FEAT_S1POE
+#define read_el1_ctx_s1poe(ctx, reg) (((ctx)->s1poe).reg)
+#define write_el1_ctx_s1poe(ctx, reg, val) ((((ctx)->s1poe).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_s1poe(ctx, reg) ULL(0)
+#define write_el1_ctx_s1poe(ctx, reg, val)
+#endif /* ENABLE_FEAT_S1POE */
+
+#if ENABLE_FEAT_S2POE
+#define read_el1_ctx_s2poe(ctx, reg) (((ctx)->s2poe).reg)
+#define write_el1_ctx_s2poe(ctx, reg, val) ((((ctx)->s2poe).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_s2poe(ctx, reg) ULL(0)
+#define write_el1_ctx_s2poe(ctx, reg, val)
+#endif /* ENABLE_FEAT_S2POE */
+
+#if ENABLE_FEAT_TCR2
+#define read_el1_ctx_tcr2(ctx, reg) (((ctx)->tcr2).reg)
+#define write_el1_ctx_tcr2(ctx, reg, val) ((((ctx)->tcr2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_tcr2(ctx, reg) ULL(0)
+#define write_el1_ctx_tcr2(ctx, reg, val)
+#endif /* ENABLE_FEAT_TCR2 */
+
+#if ENABLE_TRF_FOR_NS
+#define read_el1_ctx_trf(ctx, reg) (((ctx)->trf).reg)
+#define write_el1_ctx_trf(ctx, reg, val) ((((ctx)->trf).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_trf(ctx, reg) ULL(0)
+#define write_el1_ctx_trf(ctx, reg, val)
+#endif /* ENABLE_TRF_FOR_NS */
+
+#if ENABLE_FEAT_CSV2_2
+#define read_el1_ctx_csv2_2(ctx, reg) (((ctx)->csv2_2).reg)
+#define write_el1_ctx_csv2_2(ctx, reg, val) ((((ctx)->csv2_2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_csv2_2(ctx, reg) ULL(0)
+#define write_el1_ctx_csv2_2(ctx, reg, val)
+#endif /* ENABLE_FEAT_CSV2_2 */
+
+#if ENABLE_FEAT_GCS
+#define read_el1_ctx_gcs(ctx, reg) (((ctx)->gcs).reg)
+#define write_el1_ctx_gcs(ctx, reg, val) ((((ctx)->gcs).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_gcs(ctx, reg) ULL(0)
+#define write_el1_ctx_gcs(ctx, reg, val)
+#endif /* ENABLE_FEAT_GCS */
+/******************************************************************************/
+#endif /* __ASSEMBLER__ */
+
+#endif /* CONTEXT_EL1_H */
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index d25ab81..ca1ea4e 100644
--- a/include/lib/el3_runtime/context_el2.h
+++ b/include/lib/el3_runtime/context_el2.h
@@ -62,6 +62,14 @@
uint64_t hfgwtr_el2;
} el2_fgt_regs_t;
+typedef struct el2_fgt2_regs {
+ uint64_t hdfgrtr2_el2;
+ uint64_t hdfgwtr2_el2;
+ uint64_t hfgitr2_el2;
+ uint64_t hfgrtr2_el2;
+ uint64_t hfgwtr2_el2;
+} el2_fgt2_regs_t;
+
typedef struct el2_ecv_regs {
uint64_t cntpoff_el2;
} el2_ecv_regs_t;
@@ -140,6 +148,10 @@
el2_fgt_regs_t fgt;
#endif
+#if ENABLE_FEAT_FGT2
+ el2_fgt2_regs_t fgt2;
+#endif
+
#if ENABLE_FEAT_ECV
el2_ecv_regs_t ecv;
#endif
@@ -221,6 +233,15 @@
#define write_el2_ctx_fgt(ctx, reg, val)
#endif /* ENABLE_FEAT_FGT */
+#if ENABLE_FEAT_FGT2
+#define read_el2_ctx_fgt2(ctx, reg) (((ctx)->fgt2).reg)
+#define write_el2_ctx_fgt2(ctx, reg, val) ((((ctx)->fgt2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el2_ctx_fgt2(ctx, reg) ULL(0)
+#define write_el2_ctx_fgt2(ctx, reg, val)
+#endif /* ENABLE_FEAT_FGT */
+
#if ENABLE_FEAT_ECV
#define read_el2_ctx_ecv(ctx, reg) (((ctx)->ecv).reg)
#define write_el2_ctx_ecv(ctx, reg, val) ((((ctx)->ecv).reg) \
diff --git a/include/lib/extensions/fgt2.h b/include/lib/extensions/fgt2.h
new file mode 100644
index 0000000..0388d18
--- /dev/null
+++ b/include/lib/extensions/fgt2.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FGT2_H
+#define FGT2_H
+
+#include <context.h>
+
+#if ENABLE_FEAT_FGT2
+void fgt2_enable(cpu_context_t *ctx);
+#else
+static inline void fgt2_enable(cpu_context_t *ctx)
+{
+}
+#endif /* ENABLE_FEAT_FGT2 */
+
+#endif /* FGT2_H */
diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h
index c6e44f9..4801a22 100644
--- a/include/lib/extensions/spe.h
+++ b/include/lib/extensions/spe.h
@@ -12,16 +12,20 @@
#if ENABLE_SPE_FOR_NS
void spe_enable(cpu_context_t *ctx);
+void spe_disable(cpu_context_t *ctx);
void spe_init_el2_unused(void);
-void spe_disable(void);
+void spe_stop(void);
#else
static inline void spe_enable(cpu_context_t *ctx)
{
}
+static inline void spe_disable(cpu_context_t *ctx)
+{
+}
static inline void spe_init_el2_unused(void)
{
}
-static inline void spe_disable(void)
+static inline void spe_stop(void)
{
}
#endif /* ENABLE_SPE_FOR_NS */
diff --git a/include/lib/extensions/trbe.h b/include/lib/extensions/trbe.h
index 5db3316..2c488e0 100644
--- a/include/lib/extensions/trbe.h
+++ b/include/lib/extensions/trbe.h
@@ -10,9 +10,13 @@
#include <context.h>
#if ENABLE_TRBE_FOR_NS
+void trbe_disable(cpu_context_t *ctx);
void trbe_enable(cpu_context_t *ctx);
void trbe_init_el2_unused(void);
#else
+static inline void trbe_disable(cpu_context_t *ctx)
+{
+}
static inline void trbe_enable(cpu_context_t *ctx)
{
}
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index 5bea270..1b5ec2d 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -29,7 +29,22 @@
* Version of the register convention used.
* Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
*/
-#define REGISTER_CONVENTION_VERSION_MASK (1 << 24)
+#define REGISTER_CONVENTION_VERSION_SHIFT_64 UL(32)
+#define REGISTER_CONVENTION_VERSION_SHIFT_32 UL(24)
+#define REGISTER_CONVENTION_VERSION_MASK UL(0xff)
+#define REGISTER_CONVENTION_VERSION UL(1)
+
+#define TRANSFER_LIST_HANDOFF_X1_VALUE(__version) \
+ ((TRANSFER_LIST_SIGNATURE & \
+ ((1UL << REGISTER_CONVENTION_VERSION_SHIFT_64) - 1)) | \
+ (((__version) & REGISTER_CONVENTION_VERSION_MASK) << \
+ REGISTER_CONVENTION_VERSION_SHIFT_64))
+
+#define TRANSFER_LIST_HANDOFF_R1_VALUE(__version) \
+ ((TRANSFER_LIST_SIGNATURE & \
+ ((1UL << REGISTER_CONVENTION_VERSION_SHIFT_32) - 1)) | \
+ (((__version) & REGISTER_CONVENTION_VERSION_MASK) << \
+ REGISTER_CONVENTION_VERSION_SHIFT_32))
#ifndef __ASSEMBLER__
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 2d0949b..5434a9a 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -171,8 +171,10 @@
#define SHAREABILITY_SHIFT 8
/* The Access Flag, AF. */
#define ACCESS_FLAG_SHIFT 10
-/* The not global bit, nG. */
+/* The not global bit, nG */
#define NOT_GLOBAL_SHIFT 11
+/* The Non-secure Extension bit, NSE */
+#define NSE_SHIFT 11
/* Contiguous hint bit. */
#define CONT_HINT_SHIFT 52
/* Execute-never bits, XN. */
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index cb11dac..43a77e3 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -17,6 +17,7 @@
/* V2M motherboard system registers & offsets */
#define V2M_SYSREGS_BASE UL(0x1c010000)
+#define V2M_SYSREGS_SIZE UL(0x00010000)
#define V2M_SYS_ID UL(0x0)
#define V2M_SYS_SWITCH UL(0x4)
#define V2M_SYS_LED UL(0x8)
@@ -78,6 +79,8 @@
/* NOR Flash */
#define V2M_FLASH0_BASE (V2M_OFFSET + UL(0x08000000))
#define V2M_FLASH0_SIZE UL(0x04000000)
+#define V2M_FLASH1_BASE (V2M_OFFSET + UL(0x0c000000))
+#define V2M_FLASH1_SIZE UL(0x04000000)
#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */
#define V2M_IOFPGA_BASE (V2M_OFFSET + UL(0x1c000000))
@@ -126,6 +129,14 @@
V2M_FLASH0_SIZE, \
MT_RO_DATA | MT_SECURE)
+#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\
+ V2M_FLASH1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\
+ V2M_FLASH1_SIZE, \
+ MT_RO_DATA | MT_SECURE)
+
#define V2M_MAP_IOFPGA MAP_REGION_FLAT(V2M_IOFPGA_BASE,\
V2M_IOFPGA_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
@@ -136,5 +147,19 @@
V2M_IOFPGA_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+#define V2M_MAP_SECURE_SYSTEMREG_EL0 MAP_REGION_FLAT( \
+ V2M_SYSREGS_BASE, \
+ V2M_SYSREGS_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+#define V2M_MAP_FLASH0_RW_EL0 MAP_REGION_FLAT( \
+ V2M_FLASH0_BASE, \
+ V2M_FLASH0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+#define V2M_MAP_FLASH1_RW_EL0 MAP_REGION_FLAT( \
+ V2M_FLASH1_BASE, \
+ V2M_FLASH1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
#endif /* V2M_DEF_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index ba8df2a..83a5cd2 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -284,10 +284,7 @@
/* Firmware Handoff utility functions */
void arm_transfer_list_dyn_cfg_init(struct transfer_list_header *secure_tl);
void arm_transfer_list_populate_ep_info(bl_mem_params_node_t *next_param_node,
- struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl);
-void arm_transfer_list_copy_hw_config(struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl);
+ struct transfer_list_header *secure_tl);
/* TSP utility functions */
void arm_tsp_early_platform_setup(void);
@@ -365,6 +362,7 @@
void plat_arm_interconnect_exit_coherency(void);
void plat_arm_program_trusted_mailbox(uintptr_t address);
bool plat_arm_bl1_fwu_needed(void);
+int plat_arm_ni_setup(uintptr_t global_cfg);
__dead2 void plat_arm_error_handler(int err);
__dead2 void plat_arm_system_reset(void);
diff --git a/lib/cpus/aarch64/cortex_a720.S b/lib/cpus/aarch64/cortex_a720.S
index 53a1b78..3e2927b 100644
--- a/lib/cpus/aarch64/cortex_a720.S
+++ b/lib/cpus/aarch64/cortex_a720.S
@@ -26,6 +26,12 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A720_BHB_LOOP_COUNT, cortex_a720
#endif /* WORKAROUND_CVE_2022_23960 */
+workaround_reset_start cortex_a720, ERRATUM(2844092), ERRATA_A720_2844092
+ sysreg_bit_set CORTEX_A720_CPUACTLR4_EL1, BIT(11)
+workaround_reset_end cortex_a720, ERRATUM(2844092)
+
+check_erratum_ls cortex_a720, ERRATUM(2844092), CPU_REV(0, 1)
+
workaround_reset_start cortex_a720, ERRATUM(2926083), ERRATA_A720_2926083
/* Erratum 2926083 workaround is required only if SPE is enabled */
#if ENABLE_SPE_FOR_NS != 0
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index 20f1ae1..9f822af 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -39,6 +39,16 @@
check_erratum_ls cortex_x4, ERRATUM(2763018), CPU_REV(0, 1)
+workaround_reset_start cortex_x4, ERRATUM(2816013), ERRATA_X4_2816013
+ mrs x1, id_aa64pfr1_el1
+ ubfx x2, x1, ID_AA64PFR1_EL1_MTE_SHIFT, #4
+ cbz x2, #1f
+ sysreg_bit_set CORTEX_X4_CPUACTLR5_EL1, BIT(14)
+1:
+workaround_reset_end cortex_x4, ERRATUM(2816013)
+
+check_erratum_ls cortex_x4, ERRATUM(2816013), CPU_REV(0, 1)
+
workaround_reset_start cortex_x4, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
#if IMAGE_BL31
/*
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index f736b5a..c9ff110 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -831,6 +831,10 @@
# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_2763018
+# Flag to apply erratum 2816013 workaround on reset. This erratum applies
+# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_X4_2816013
+
# Flag to apply erratum 1922240 workaround during reset. This erratum applies
# to revision r0p0 of the Cortex-A510 cpu and is fixed in r0p1.
CPU_FLAG_LIST += ERRATA_A510_1922240
@@ -952,6 +956,10 @@
# only to revision r0p0, r1p0 and r1p1. It is fixed in r1p2.
CPU_FLAG_LIST += ERRATA_A715_2728106
+# Flag to apply erratum 2844092 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_A720_2844092
+
# Flag to apply erratum 2926083 workaround during reset. This erratum applies
# to revisions r0p0 and r0p1. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_A720_2926083
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 1fce1bf..62895ff 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -14,9 +14,13 @@
.global fpregs_context_save
.global fpregs_context_restore
#endif /* CTX_INCLUDE_FPREGS */
+
+#if ERRATA_SPECULATIVE_AT
+ .global save_and_update_ptw_el1_sys_regs
+#endif /* ERRATA_SPECULATIVE_AT */
+
.global prepare_el3_entry
.global restore_gp_pmcr_pauth_regs
- .global save_and_update_ptw_el1_sys_regs
.global el3_exit
/* ------------------------------------------------------------------
@@ -329,10 +333,12 @@
ret
endfunc restore_gp_pmcr_pauth_regs
-/*
+#if ERRATA_SPECULATIVE_AT
+/* --------------------------------------------------------------------
* In case of ERRATA_SPECULATIVE_AT, save SCTLR_EL1 and TCR_EL1
* registers and update EL1 registers to disable stage1 and stage2
- * page table walk
+ * page table walk.
+ * --------------------------------------------------------------------
*/
func save_and_update_ptw_el1_sys_regs
/* ----------------------------------------------------------
@@ -340,9 +346,9 @@
* ----------------------------------------------------------
*/
mrs x29, sctlr_el1
- str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1)]
+ str x29, [sp, #(CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1)]
mrs x29, tcr_el1
- str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_TCR_EL1)]
+ str x29, [sp, #(CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_TCR_EL1)]
/* ------------------------------------------------------------
* Must follow below order in order to disable page table
@@ -367,10 +373,11 @@
orr x29, x29, #SCTLR_M_BIT
msr sctlr_el1, x29
isb
-
ret
endfunc save_and_update_ptw_el1_sys_regs
+#endif /* ERRATA_SPECULATIVE_AT */
+
/* -----------------------------------------------------------------
* The below macro returns the address of the per_world context for
* the security state, retrieved through "get_security_state" macro.
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 1e40fb3..15db9e5 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -25,6 +25,7 @@
#include <lib/extensions/amu.h>
#include <lib/extensions/brbe.h>
#include <lib/extensions/debug_v8p9.h>
+#include <lib/extensions/fgt2.h>
#include <lib/extensions/mpam.h>
#include <lib/extensions/pmuv3.h>
#include <lib/extensions/sme.h>
@@ -91,8 +92,13 @@
*/
sctlr_elx |= SCTLR_IESB_BIT;
#endif
+
/* Store the initialised SCTLR_EL1 value in the cpu_context */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx), CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_elx);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, sctlr_elx);
+#endif /* ERRATA_SPECULATIVE_AT */
/*
* Base the context ACTLR_EL1 on the current value, as it is
@@ -102,7 +108,7 @@
* be zero.
*/
actlr_elx = read_actlr_el1();
- write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), actlr_el1, actlr_elx);
}
/******************************************************************************
@@ -335,6 +341,12 @@
u_register_t icc_sre_el2_val = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT |
ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT;
write_el2_ctx_common(el2_ctx, icc_sre_el2, icc_sre_el2_val);
+
+ /*
+ * The actlr_el2 register can be initialized in platform's reset handler
+ * and it may contain access control bits (e.g. CLUSTERPMUEN bit).
+ */
+ write_el2_ctx_common(el2_ctx, actlr_el2, read_actlr_el2());
#endif /* CTX_INCLUDE_EL2_REGS */
/* Start with a clean SCR_EL3 copy as all relevant values are set */
@@ -773,6 +785,10 @@
sme_enable(ctx);
}
+ if (is_feat_fgt2_supported()) {
+ fgt2_enable(ctx);
+ }
+
if (is_feat_debugv8p9_supported()) {
debugv8p9_extended_bp_wp_enable(ctx);
}
@@ -1103,6 +1119,24 @@
write_hfgwtr_el2(read_el2_ctx_fgt(ctx, hfgwtr_el2));
}
+static void el2_sysregs_context_save_fgt2(el2_sysregs_t *ctx)
+{
+ write_el2_ctx_fgt2(ctx, hdfgrtr2_el2, read_hdfgrtr2_el2());
+ write_el2_ctx_fgt2(ctx, hdfgwtr2_el2, read_hdfgwtr2_el2());
+ write_el2_ctx_fgt2(ctx, hfgitr2_el2, read_hfgitr2_el2());
+ write_el2_ctx_fgt2(ctx, hfgrtr2_el2, read_hfgrtr2_el2());
+ write_el2_ctx_fgt2(ctx, hfgwtr2_el2, read_hfgwtr2_el2());
+}
+
+static void el2_sysregs_context_restore_fgt2(el2_sysregs_t *ctx)
+{
+ write_hdfgrtr2_el2(read_el2_ctx_fgt2(ctx, hdfgrtr2_el2));
+ write_hdfgwtr2_el2(read_el2_ctx_fgt2(ctx, hdfgwtr2_el2));
+ write_hfgitr2_el2(read_el2_ctx_fgt2(ctx, hfgitr2_el2));
+ write_hfgrtr2_el2(read_el2_ctx_fgt2(ctx, hfgrtr2_el2));
+ write_hfgwtr2_el2(read_el2_ctx_fgt2(ctx, hfgwtr2_el2));
+}
+
static void el2_sysregs_context_save_mpam(el2_sysregs_t *ctx)
{
u_register_t mpam_idr = read_mpamidr_el1();
@@ -1342,6 +1376,10 @@
el2_sysregs_context_save_fgt(el2_sysregs_ctx);
}
+ if (is_feat_fgt2_supported()) {
+ el2_sysregs_context_save_fgt2(el2_sysregs_ctx);
+ }
+
if (is_feat_ecv_v2_supported()) {
write_el2_ctx_ecv(el2_sysregs_ctx, cntpoff_el2, read_cntpoff_el2());
}
@@ -1425,6 +1463,10 @@
el2_sysregs_context_restore_fgt(el2_sysregs_ctx);
}
+ if (is_feat_fgt2_supported()) {
+ el2_sysregs_context_restore_fgt2(el2_sysregs_ctx);
+ }
+
if (is_feat_ecv_v2_supported()) {
write_cntpoff_el2(read_el2_ctx_ecv(el2_sysregs_ctx, cntpoff_el2));
}
@@ -1511,220 +1553,192 @@
static void el1_sysregs_context_save(el1_sysregs_t *ctx)
{
- write_ctx_reg(ctx, CTX_SPSR_EL1, read_spsr_el1());
- write_ctx_reg(ctx, CTX_ELR_EL1, read_elr_el1());
+ write_el1_ctx_common(ctx, spsr_el1, read_spsr_el1());
+ write_el1_ctx_common(ctx, elr_el1, read_elr_el1());
-#if !ERRATA_SPECULATIVE_AT
- write_ctx_reg(ctx, CTX_SCTLR_EL1, read_sctlr_el1());
- write_ctx_reg(ctx, CTX_TCR_EL1, read_tcr_el1());
+#if (!ERRATA_SPECULATIVE_AT)
+ write_el1_ctx_common(ctx, sctlr_el1, read_sctlr_el1());
+ write_el1_ctx_common(ctx, tcr_el1, read_tcr_el1());
#endif /* (!ERRATA_SPECULATIVE_AT) */
- write_ctx_reg(ctx, CTX_CPACR_EL1, read_cpacr_el1());
- write_ctx_reg(ctx, CTX_CSSELR_EL1, read_csselr_el1());
- write_ctx_reg(ctx, CTX_SP_EL1, read_sp_el1());
- write_ctx_reg(ctx, CTX_ESR_EL1, read_esr_el1());
- write_ctx_reg(ctx, CTX_TTBR0_EL1, read_ttbr0_el1());
- write_ctx_reg(ctx, CTX_TTBR1_EL1, read_ttbr1_el1());
- write_ctx_reg(ctx, CTX_MAIR_EL1, read_mair_el1());
- write_ctx_reg(ctx, CTX_AMAIR_EL1, read_amair_el1());
- write_ctx_reg(ctx, CTX_ACTLR_EL1, read_actlr_el1());
- write_ctx_reg(ctx, CTX_TPIDR_EL1, read_tpidr_el1());
- write_ctx_reg(ctx, CTX_TPIDR_EL0, read_tpidr_el0());
- write_ctx_reg(ctx, CTX_TPIDRRO_EL0, read_tpidrro_el0());
- write_ctx_reg(ctx, CTX_PAR_EL1, read_par_el1());
- write_ctx_reg(ctx, CTX_FAR_EL1, read_far_el1());
- write_ctx_reg(ctx, CTX_AFSR0_EL1, read_afsr0_el1());
- write_ctx_reg(ctx, CTX_AFSR1_EL1, read_afsr1_el1());
- write_ctx_reg(ctx, CTX_CONTEXTIDR_EL1, read_contextidr_el1());
- write_ctx_reg(ctx, CTX_VBAR_EL1, read_vbar_el1());
- write_ctx_reg(ctx, CTX_MDCCINT_EL1, read_mdccint_el1());
- write_ctx_reg(ctx, CTX_MDSCR_EL1, read_mdscr_el1());
+ write_el1_ctx_common(ctx, cpacr_el1, read_cpacr_el1());
+ write_el1_ctx_common(ctx, csselr_el1, read_csselr_el1());
+ write_el1_ctx_common(ctx, sp_el1, read_sp_el1());
+ write_el1_ctx_common(ctx, esr_el1, read_esr_el1());
+ write_el1_ctx_common(ctx, ttbr0_el1, read_ttbr0_el1());
+ write_el1_ctx_common(ctx, ttbr1_el1, read_ttbr1_el1());
+ write_el1_ctx_common(ctx, mair_el1, read_mair_el1());
+ write_el1_ctx_common(ctx, amair_el1, read_amair_el1());
+ write_el1_ctx_common(ctx, actlr_el1, read_actlr_el1());
+ write_el1_ctx_common(ctx, tpidr_el1, read_tpidr_el1());
+ write_el1_ctx_common(ctx, tpidr_el0, read_tpidr_el0());
+ write_el1_ctx_common(ctx, tpidrro_el0, read_tpidrro_el0());
+ write_el1_ctx_common(ctx, par_el1, read_par_el1());
+ write_el1_ctx_common(ctx, far_el1, read_far_el1());
+ write_el1_ctx_common(ctx, afsr0_el1, read_afsr0_el1());
+ write_el1_ctx_common(ctx, afsr1_el1, read_afsr1_el1());
+ write_el1_ctx_common(ctx, contextidr_el1, read_contextidr_el1());
+ write_el1_ctx_common(ctx, vbar_el1, read_vbar_el1());
+ write_el1_ctx_common(ctx, mdccint_el1, read_mdccint_el1());
+ write_el1_ctx_common(ctx, mdscr_el1, read_mdscr_el1());
-#if CTX_INCLUDE_AARCH32_REGS
- write_ctx_reg(ctx, CTX_SPSR_ABT, read_spsr_abt());
- write_ctx_reg(ctx, CTX_SPSR_UND, read_spsr_und());
- write_ctx_reg(ctx, CTX_SPSR_IRQ, read_spsr_irq());
- write_ctx_reg(ctx, CTX_SPSR_FIQ, read_spsr_fiq());
- write_ctx_reg(ctx, CTX_DACR32_EL2, read_dacr32_el2());
- write_ctx_reg(ctx, CTX_IFSR32_EL2, read_ifsr32_el2());
-#endif /* CTX_INCLUDE_AARCH32_REGS */
+ if (CTX_INCLUDE_AARCH32_REGS) {
+ /* Save Aarch32 registers */
+ write_el1_ctx_aarch32(ctx, spsr_abt, read_spsr_abt());
+ write_el1_ctx_aarch32(ctx, spsr_und, read_spsr_und());
+ write_el1_ctx_aarch32(ctx, spsr_irq, read_spsr_irq());
+ write_el1_ctx_aarch32(ctx, spsr_fiq, read_spsr_fiq());
+ write_el1_ctx_aarch32(ctx, dacr32_el2, read_dacr32_el2());
+ write_el1_ctx_aarch32(ctx, ifsr32_el2, read_ifsr32_el2());
+ }
-#if NS_TIMER_SWITCH
- write_ctx_reg(ctx, CTX_CNTP_CTL_EL0, read_cntp_ctl_el0());
- write_ctx_reg(ctx, CTX_CNTP_CVAL_EL0, read_cntp_cval_el0());
- write_ctx_reg(ctx, CTX_CNTV_CTL_EL0, read_cntv_ctl_el0());
- write_ctx_reg(ctx, CTX_CNTV_CVAL_EL0, read_cntv_cval_el0());
- write_ctx_reg(ctx, CTX_CNTKCTL_EL1, read_cntkctl_el1());
-#endif /* NS_TIMER_SWITCH */
+ if (NS_TIMER_SWITCH) {
+ /* Save NS Timer registers */
+ write_el1_ctx_arch_timer(ctx, cntp_ctl_el0, read_cntp_ctl_el0());
+ write_el1_ctx_arch_timer(ctx, cntp_cval_el0, read_cntp_cval_el0());
+ write_el1_ctx_arch_timer(ctx, cntv_ctl_el0, read_cntv_ctl_el0());
+ write_el1_ctx_arch_timer(ctx, cntv_cval_el0, read_cntv_cval_el0());
+ write_el1_ctx_arch_timer(ctx, cntkctl_el1, read_cntkctl_el1());
+ }
-#if ENABLE_FEAT_MTE2
- write_ctx_reg(ctx, CTX_TFSRE0_EL1, read_tfsre0_el1());
- write_ctx_reg(ctx, CTX_TFSR_EL1, read_tfsr_el1());
- write_ctx_reg(ctx, CTX_RGSR_EL1, read_rgsr_el1());
- write_ctx_reg(ctx, CTX_GCR_EL1, read_gcr_el1());
-#endif /* ENABLE_FEAT_MTE2 */
+ if (is_feat_mte2_supported()) {
+ write_el1_ctx_mte2(ctx, tfsre0_el1, read_tfsre0_el1());
+ write_el1_ctx_mte2(ctx, tfsr_el1, read_tfsr_el1());
+ write_el1_ctx_mte2(ctx, rgsr_el1, read_rgsr_el1());
+ write_el1_ctx_mte2(ctx, gcr_el1, read_gcr_el1());
+ }
-#if ENABLE_FEAT_RAS
if (is_feat_ras_supported()) {
- write_ctx_reg(ctx, CTX_DISR_EL1, read_disr_el1());
+ write_el1_ctx_ras(ctx, disr_el1, read_disr_el1());
}
-#endif
-#if ENABLE_FEAT_S1PIE
if (is_feat_s1pie_supported()) {
- write_ctx_reg(ctx, CTX_PIRE0_EL1, read_pire0_el1());
- write_ctx_reg(ctx, CTX_PIR_EL1, read_pir_el1());
+ write_el1_ctx_s1pie(ctx, pire0_el1, read_pire0_el1());
+ write_el1_ctx_s1pie(ctx, pir_el1, read_pir_el1());
}
-#endif
-#if ENABLE_FEAT_S1POE
if (is_feat_s1poe_supported()) {
- write_ctx_reg(ctx, CTX_POR_EL1, read_por_el1());
+ write_el1_ctx_s1poe(ctx, por_el1, read_por_el1());
}
-#endif
-#if ENABLE_FEAT_S2POE
if (is_feat_s2poe_supported()) {
- write_ctx_reg(ctx, CTX_S2POR_EL1, read_s2por_el1());
+ write_el1_ctx_s2poe(ctx, s2por_el1, read_s2por_el1());
}
-#endif
-#if ENABLE_FEAT_TCR2
if (is_feat_tcr2_supported()) {
- write_ctx_reg(ctx, CTX_TCR2_EL1, read_tcr2_el1());
+ write_el1_ctx_tcr2(ctx, tcr2_el1, read_tcr2_el1());
}
-#endif
-#if ENABLE_TRF_FOR_NS
if (is_feat_trf_supported()) {
- write_ctx_reg(ctx, CTX_TRFCR_EL1, read_trfcr_el1());
+ write_el1_ctx_trf(ctx, trfcr_el1, read_trfcr_el1());
}
-#endif
-#if ENABLE_FEAT_CSV2_2
if (is_feat_csv2_2_supported()) {
- write_ctx_reg(ctx, CTX_SCXTNUM_EL0, read_scxtnum_el0());
- write_ctx_reg(ctx, CTX_SCXTNUM_EL1, read_scxtnum_el1());
+ write_el1_ctx_csv2_2(ctx, scxtnum_el0, read_scxtnum_el0());
+ write_el1_ctx_csv2_2(ctx, scxtnum_el1, read_scxtnum_el1());
}
-#endif
-#if ENABLE_FEAT_GCS
if (is_feat_gcs_supported()) {
- write_ctx_reg(ctx, CTX_GCSCR_EL1, read_gcscr_el1());
- write_ctx_reg(ctx, CTX_GCSCRE0_EL1, read_gcscre0_el1());
- write_ctx_reg(ctx, CTX_GCSPR_EL1, read_gcspr_el1());
- write_ctx_reg(ctx, CTX_GCSPR_EL0, read_gcspr_el0());
+ write_el1_ctx_gcs(ctx, gcscr_el1, read_gcscr_el1());
+ write_el1_ctx_gcs(ctx, gcscre0_el1, read_gcscre0_el1());
+ write_el1_ctx_gcs(ctx, gcspr_el1, read_gcspr_el1());
+ write_el1_ctx_gcs(ctx, gcspr_el0, read_gcspr_el0());
}
-#endif
}
static void el1_sysregs_context_restore(el1_sysregs_t *ctx)
{
- write_spsr_el1(read_ctx_reg(ctx, CTX_SPSR_EL1));
- write_elr_el1(read_ctx_reg(ctx, CTX_ELR_EL1));
+ write_spsr_el1(read_el1_ctx_common(ctx, spsr_el1));
+ write_elr_el1(read_el1_ctx_common(ctx, elr_el1));
-#if !ERRATA_SPECULATIVE_AT
- write_sctlr_el1(read_ctx_reg(ctx, CTX_SCTLR_EL1));
- write_tcr_el1(read_ctx_reg(ctx, CTX_TCR_EL1));
+#if (!ERRATA_SPECULATIVE_AT)
+ write_sctlr_el1(read_el1_ctx_common(ctx, sctlr_el1));
+ write_tcr_el1(read_el1_ctx_common(ctx, tcr_el1));
#endif /* (!ERRATA_SPECULATIVE_AT) */
- write_cpacr_el1(read_ctx_reg(ctx, CTX_CPACR_EL1));
- write_csselr_el1(read_ctx_reg(ctx, CTX_CSSELR_EL1));
- write_sp_el1(read_ctx_reg(ctx, CTX_SP_EL1));
- write_esr_el1(read_ctx_reg(ctx, CTX_ESR_EL1));
- write_ttbr0_el1(read_ctx_reg(ctx, CTX_TTBR0_EL1));
- write_ttbr1_el1(read_ctx_reg(ctx, CTX_TTBR1_EL1));
- write_mair_el1(read_ctx_reg(ctx, CTX_MAIR_EL1));
- write_amair_el1(read_ctx_reg(ctx, CTX_AMAIR_EL1));
- write_actlr_el1(read_ctx_reg(ctx, CTX_ACTLR_EL1));
- write_tpidr_el1(read_ctx_reg(ctx, CTX_TPIDR_EL1));
- write_tpidr_el0(read_ctx_reg(ctx, CTX_TPIDR_EL0));
- write_tpidrro_el0(read_ctx_reg(ctx, CTX_TPIDRRO_EL0));
- write_par_el1(read_ctx_reg(ctx, CTX_PAR_EL1));
- write_far_el1(read_ctx_reg(ctx, CTX_FAR_EL1));
- write_afsr0_el1(read_ctx_reg(ctx, CTX_AFSR0_EL1));
- write_afsr1_el1(read_ctx_reg(ctx, CTX_AFSR1_EL1));
- write_contextidr_el1(read_ctx_reg(ctx, CTX_CONTEXTIDR_EL1));
- write_vbar_el1(read_ctx_reg(ctx, CTX_VBAR_EL1));
- write_mdccint_el1(read_ctx_reg(ctx, CTX_MDCCINT_EL1));
- write_mdscr_el1(read_ctx_reg(ctx, CTX_MDSCR_EL1));
+ write_cpacr_el1(read_el1_ctx_common(ctx, cpacr_el1));
+ write_csselr_el1(read_el1_ctx_common(ctx, csselr_el1));
+ write_sp_el1(read_el1_ctx_common(ctx, sp_el1));
+ write_esr_el1(read_el1_ctx_common(ctx, esr_el1));
+ write_ttbr0_el1(read_el1_ctx_common(ctx, ttbr0_el1));
+ write_ttbr1_el1(read_el1_ctx_common(ctx, ttbr1_el1));
+ write_mair_el1(read_el1_ctx_common(ctx, mair_el1));
+ write_amair_el1(read_el1_ctx_common(ctx, amair_el1));
+ write_actlr_el1(read_el1_ctx_common(ctx, actlr_el1));
+ write_tpidr_el1(read_el1_ctx_common(ctx, tpidr_el1));
+ write_tpidr_el0(read_el1_ctx_common(ctx, tpidr_el0));
+ write_tpidrro_el0(read_el1_ctx_common(ctx, tpidrro_el0));
+ write_par_el1(read_el1_ctx_common(ctx, par_el1));
+ write_far_el1(read_el1_ctx_common(ctx, far_el1));
+ write_afsr0_el1(read_el1_ctx_common(ctx, afsr0_el1));
+ write_afsr1_el1(read_el1_ctx_common(ctx, afsr1_el1));
+ write_contextidr_el1(read_el1_ctx_common(ctx, contextidr_el1));
+ write_vbar_el1(read_el1_ctx_common(ctx, vbar_el1));
+ write_mdccint_el1(read_el1_ctx_common(ctx, mdccint_el1));
+ write_mdscr_el1(read_el1_ctx_common(ctx, mdscr_el1));
-#if CTX_INCLUDE_AARCH32_REGS
- write_spsr_abt(read_ctx_reg(ctx, CTX_SPSR_ABT));
- write_spsr_und(read_ctx_reg(ctx, CTX_SPSR_UND));
- write_spsr_irq(read_ctx_reg(ctx, CTX_SPSR_IRQ));
- write_spsr_fiq(read_ctx_reg(ctx, CTX_SPSR_FIQ));
- write_dacr32_el2(read_ctx_reg(ctx, CTX_DACR32_EL2));
- write_ifsr32_el2(read_ctx_reg(ctx, CTX_IFSR32_EL2));
-#endif /* CTX_INCLUDE_AARCH32_REGS */
+ if (CTX_INCLUDE_AARCH32_REGS) {
+ /* Restore Aarch32 registers */
+ write_spsr_abt(read_el1_ctx_aarch32(ctx, spsr_abt));
+ write_spsr_und(read_el1_ctx_aarch32(ctx, spsr_und));
+ write_spsr_irq(read_el1_ctx_aarch32(ctx, spsr_irq));
+ write_spsr_fiq(read_el1_ctx_aarch32(ctx, spsr_fiq));
+ write_dacr32_el2(read_el1_ctx_aarch32(ctx, dacr32_el2));
+ write_ifsr32_el2(read_el1_ctx_aarch32(ctx, ifsr32_el2));
+ }
-#if NS_TIMER_SWITCH
- write_cntp_ctl_el0(read_ctx_reg(ctx, CTX_CNTP_CTL_EL0));
- write_cntp_cval_el0(read_ctx_reg(ctx, CTX_CNTP_CVAL_EL0));
- write_cntv_ctl_el0(read_ctx_reg(ctx, CTX_CNTV_CTL_EL0));
- write_cntv_cval_el0(read_ctx_reg(ctx, CTX_CNTV_CVAL_EL0));
- write_cntkctl_el1(read_ctx_reg(ctx, CTX_CNTKCTL_EL1));
-#endif /* NS_TIMER_SWITCH */
+ if (NS_TIMER_SWITCH) {
+ /* Restore NS Timer registers */
+ write_cntp_ctl_el0(read_el1_ctx_arch_timer(ctx, cntp_ctl_el0));
+ write_cntp_cval_el0(read_el1_ctx_arch_timer(ctx, cntp_cval_el0));
+ write_cntv_ctl_el0(read_el1_ctx_arch_timer(ctx, cntv_ctl_el0));
+ write_cntv_cval_el0(read_el1_ctx_arch_timer(ctx, cntv_cval_el0));
+ write_cntkctl_el1(read_el1_ctx_arch_timer(ctx, cntkctl_el1));
+ }
-#if ENABLE_FEAT_MTE2
- write_tfsre0_el1(read_ctx_reg(ctx, CTX_TFSRE0_EL1));
- write_tfsr_el1(read_ctx_reg(ctx, CTX_TFSR_EL1));
- write_rgsr_el1(read_ctx_reg(ctx, CTX_RGSR_EL1));
- write_gcr_el1(read_ctx_reg(ctx, CTX_GCR_EL1));
-#endif /* ENABLE_FEAT_MTE2 */
+ if (is_feat_mte2_supported()) {
+ write_tfsre0_el1(read_el1_ctx_mte2(ctx, tfsre0_el1));
+ write_tfsr_el1(read_el1_ctx_mte2(ctx, tfsr_el1));
+ write_rgsr_el1(read_el1_ctx_mte2(ctx, rgsr_el1));
+ write_gcr_el1(read_el1_ctx_mte2(ctx, gcr_el1));
+ }
-#if ENABLE_FEAT_RAS
if (is_feat_ras_supported()) {
- write_disr_el1(read_ctx_reg(ctx, CTX_DISR_EL1));
+ write_disr_el1(read_el1_ctx_ras(ctx, disr_el1));
}
-#endif
-#if ENABLE_FEAT_S1PIE
if (is_feat_s1pie_supported()) {
- write_pire0_el1(read_ctx_reg(ctx, CTX_PIRE0_EL1));
- write_pir_el1(read_ctx_reg(ctx, CTX_PIR_EL1));
+ write_pire0_el1(read_el1_ctx_s1pie(ctx, pire0_el1));
+ write_pir_el1(read_el1_ctx_s1pie(ctx, pir_el1));
}
-#endif
-#if ENABLE_FEAT_S1POE
if (is_feat_s1poe_supported()) {
- write_por_el1(read_ctx_reg(ctx, CTX_POR_EL1));
+ write_por_el1(read_el1_ctx_s1poe(ctx, por_el1));
}
-#endif
-#if ENABLE_FEAT_S2POE
if (is_feat_s2poe_supported()) {
- write_s2por_el1(read_ctx_reg(ctx, CTX_S2POR_EL1));
+ write_s2por_el1(read_el1_ctx_s2poe(ctx, s2por_el1));
}
-#endif
-#if ENABLE_FEAT_TCR2
if (is_feat_tcr2_supported()) {
- write_tcr2_el1(read_ctx_reg(ctx, CTX_TCR2_EL1));
+ write_tcr2_el1(read_el1_ctx_tcr2(ctx, tcr2_el1));
}
-#endif
-#if ENABLE_TRF_FOR_NS
if (is_feat_trf_supported()) {
- write_trfcr_el1(read_ctx_reg(ctx, CTX_TRFCR_EL1));
+ write_trfcr_el1(read_el1_ctx_trf(ctx, trfcr_el1));
}
-#endif
-#if ENABLE_FEAT_CSV2_2
if (is_feat_csv2_2_supported()) {
- write_scxtnum_el0(read_ctx_reg(ctx, CTX_SCXTNUM_EL0));
- write_scxtnum_el1(read_ctx_reg(ctx, CTX_SCXTNUM_EL1));
+ write_scxtnum_el0(read_el1_ctx_csv2_2(ctx, scxtnum_el0));
+ write_scxtnum_el1(read_el1_ctx_csv2_2(ctx, scxtnum_el1));
}
-#endif
-#if ENABLE_FEAT_GCS
if (is_feat_gcs_supported()) {
- write_gcscr_el1(read_ctx_reg(ctx, CTX_GCSCR_EL1));
- write_gcscre0_el1(read_ctx_reg(ctx, CTX_GCSCRE0_EL1));
- write_gcspr_el1(read_ctx_reg(ctx, CTX_GCSPR_EL1));
- write_gcspr_el0(read_ctx_reg(ctx, CTX_GCSPR_EL0));
+ write_gcscr_el1(read_el1_ctx_gcs(ctx, gcscr_el1));
+ write_gcscre0_el1(read_el1_ctx_gcs(ctx, gcscre0_el1));
+ write_gcspr_el1(read_el1_ctx_gcs(ctx, gcspr_el1));
+ write_gcspr_el0(read_el1_ctx_gcs(ctx, gcspr_el0));
}
-#endif
}
/*******************************************************************************
diff --git a/lib/extensions/fgt/fgt2.c b/lib/extensions/fgt/fgt2.c
new file mode 100644
index 0000000..78f1a82
--- /dev/null
+++ b/lib/extensions/fgt/fgt2.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/extensions/fgt2.h>
+
+void fgt2_enable(cpu_context_t *context)
+{
+ u_register_t reg;
+ el3_state_t *state;
+
+ state = get_el3state_ctx(context);
+
+ /* Set the FGTEN2 bit in SCR_EL3 to enable access to HFGITR2_EL2,
+ * HFGRTR2_EL2, HFGWTR_EL2, HDFGRTR2_EL2, and HDFGWTR2_EL2.
+ */
+
+ reg = read_ctx_reg(state, CTX_SCR_EL3);
+ reg |= SCR_FGTEN2_BIT;
+ write_ctx_reg(state, CTX_SCR_EL3, reg);
+}
+
diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c
index c6076fe..d653222 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -52,6 +52,27 @@
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
}
+void spe_disable(cpu_context_t *ctx)
+{
+ el3_state_t *state = get_el3state_ctx(ctx);
+ u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
+
+ /*
+ * MDCR_EL3.NSPB: Clear these bits to disable SPE feature, as it was enabled
+ * for Non-secure state only. After clearing these bits Secure state owns
+ * the Profiling Buffer and accesses to Statistical Profiling and Profiling
+ * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3
+ *
+ * MDCR_EL3.NSPBE: Don't care as it was cleared during spe_enable and setting
+ * this to 1 does not make sense as NSPBE{1} and NSPB{0b0x} is RESERVED.
+ *
+ * MDCR_EL3.EnPMSN (ARM v8.7): Clear the bit to trap access of PMSNEVFR_EL1
+ * from EL2/EL1 to EL3.
+ */
+ mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT);
+ write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
+}
+
void spe_init_el2_unused(void)
{
uint64_t v;
@@ -70,7 +91,7 @@
write_mdcr_el2(v);
}
-void spe_disable(void)
+void spe_stop(void)
{
uint64_t v;
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
index 9157734..8c1c421 100644
--- a/lib/extensions/trbe/trbe.c
+++ b/lib/extensions/trbe/trbe.c
@@ -39,6 +39,25 @@
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
}
+void trbe_disable(cpu_context_t *ctx)
+{
+ el3_state_t *state = get_el3state_ctx(ctx);
+ u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
+
+ /*
+ * MDCR_EL3.NSTBE = 0b0
+ * Trace Buffer owning Security state is secure state. If FEAT_RME
+ * is not implemented, this field is RES0.
+ *
+ * MDCR_EL3.NSTB = 0b00
+ * Clear these bits to disable access of trace buffer control registers
+ * from lower ELs in any security state.
+ */
+ mdcr_el3_val &= ~(MDCR_NSTB(MDCR_NSTB_EL1));
+ mdcr_el3_val &= ~(MDCR_NSTBE_BIT);
+ write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
+}
+
void trbe_init_el2_unused(void)
{
/*
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 60449f6..375cdba 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -182,9 +182,9 @@
}
my_idx = plat_my_core_pos();
-
- for (lvl = PSCI_CPU_PWR_LVL; lvl <= end_pwrlvl; lvl++) {
- parent_idx = psci_cpu_pd_nodes[my_idx].parent_node;
+ parent_idx = psci_cpu_pd_nodes[my_idx].parent_node;
+ for (lvl = PSCI_CPU_PWR_LVL + U(1); lvl < end_pwrlvl; lvl++) {
+ parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
}
cpu_start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx;
@@ -1303,7 +1303,7 @@
* before exiting coherency.
*/
if (is_feat_spe_supported()) {
- spe_disable();
+ spe_stop();
}
}
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index 8c8a110..29fbf78 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -10,6 +10,7 @@
toolchains := aarch64
endif
+include ../../make_helpers/build-rules.mk
include ../../make_helpers/common.mk
include ../../make_helpers/toolchain.mk
@@ -46,45 +47,45 @@
all: $(BUILD_DIR)/romlib.bin $(BUILD_DIR)/romlib.ldflags $(LIB_DIR)/libwrappers.a
-%.o: %.s
+%.o: %.s | $$(@D)/
$(s)echo " AS $@"
$(q)$(aarch64-as) -c $(ASFLAGS) -o $@ $<
-$(BUILD_DIR)/%.o: %.s
+$(BUILD_DIR)/%.o: %.s | $$(@D)/
$(s)echo " AS $@"
$(q)$(aarch64-as) -c $(ASFLAGS) -o $@ $<
-$(BUILD_DIR)/romlib.ld: romlib.ld.S
+$(BUILD_DIR)/romlib.ld: romlib.ld.S | $$(@D)/
$(s)echo " PP $@"
$(q)$(aarch64-cpp) -E $(PPFLAGS) -o $@ romlib.ld.S
-$(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld
+$(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld | $$(@D)/
$(s)echo " LD $@"
$(q)$(aarch64-ld) -T $(BUILD_DIR)/romlib.ld -L$(LIB_DIR) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf
+$(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf | $$(@D)/
$(s)echo " BIN $@"
$(q)$(aarch64-oc) -O binary $(BUILD_DIR)/romlib.elf $@
-$(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf
+$(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf | $$(@D)/
$(s)echo " VAR $@"
$(q)$(ROMLIB_GEN) genvar --output $@ $<
-$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
+$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) | $$(@D)/
$(s)echo " AR $@"
$(q)$(aarch64-ar) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
-$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i
+$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i | $$(@D)/
$(s)echo " PRE $@"
$(q)$(ROMLIB_GEN) pre --output $@ --deps $(BUILD_DIR)/jmptbl.d $<
-$(WRAPPER_SOURCES) &: $(BUILD_DIR)/jmptbl.i
+$(WRAPPER_SOURCES) &: $(BUILD_DIR)/jmptbl.i | $$(@D)/
$(s)echo " WRP $<"
$(q)$(ROMLIB_GEN) genwrappers --bti=$(ENABLE_BTI) -b $(WRAPPER_DIR) $<
-$(WRAPPER_OBJS): $(WRAPPER_DIR)/%.o: $(WRAPPER_DIR)/%.s
+$(WRAPPER_OBJS): $(WRAPPER_DIR)/%.o: $(WRAPPER_DIR)/%.s | $$(@D)/
-$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i
+$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i | $$(@D)/
$(s)echo " TBL $@"
$(q)$(ROMLIB_GEN) gentbl --output $@ --bti=$(ENABLE_BTI) $<
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index b7fedfa..8d82d25 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -63,20 +63,21 @@
te = transfer_list_find(tl, TL_TAG_FDT);
dt = transfer_list_entry_data(te);
- ep_info->args.arg1 = TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
- ep_info->args.arg3 = (uintptr_t)tl;
-
- if (GET_RW(ep_info->spsr) == MODE_RW_32) {
- /* aarch32 */
- ep_info->args.arg0 = 0;
- ep_info->args.arg2 = (uintptr_t)dt;
- } else {
- /* aarch64 */
+#ifdef __aarch64__
+ if (GET_RW(ep_info->spsr) == MODE_RW_64) {
ep_info->args.arg0 = (uintptr_t)dt;
+ ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
ep_info->args.arg2 = 0;
+ } else
+#endif
+ {
+ ep_info->args.arg0 = 0;
+ ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+ ep_info->args.arg2 = (uintptr_t)dt;
}
+ ep_info->args.arg3 = (uintptr_t)tl;
+
return ep_info;
}
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index f3a53cc..a3b913c 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,7 @@
#include <platform_def.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/utils_def.h>
@@ -419,10 +420,59 @@
*attributes |= MT_USER;
}
- uint64_t ns_bit = (desc >> NS_SHIFT) & 1U;
+ uint64_t ns_bit = (desc >> NS_SHIFT) & 1ULL;
- if (ns_bit == 1U)
+#if ENABLE_RME
+ uint64_t nse_bit = (desc >> NSE_SHIFT) & 1ULL;
+ uint32_t sec_state = (uint32_t)(ns_bit | (nse_bit << 1ULL));
+
+/*
+ * =========================================================
+ * NSE NS | Output PA space
+ * =========================================================
+ * 0 0 | Secure (if S-EL2 is present, else invalid)
+ * 0 1 | Non-secure
+ * 1 0 | Root
+ * 1 1 | Realm
+ *==========================================================
+ */
+ switch (sec_state) {
+ case 0U:
+ /*
+ * We expect to get Secure mapping on an RME system only if
+ * S-EL2 is enabled.
+ * Hence panic() if we hit the case without EEL2 being enabled.
+ */
+ if ((read_scr_el3() & SCR_EEL2_BIT) == 0ULL) {
+ ERROR("A secure descriptor is not supported when"
+ "FEAT_RME is implemented and FEAT_SEL2 is"
+ "not enabled\n");
+ panic();
+ } else {
+ *attributes |= MT_SECURE;
+ }
+ break;
+ case 1U:
*attributes |= MT_NS;
+ break;
+ case 2U:
+ *attributes |= MT_ROOT;
+ break;
+ case 3U:
+ *attributes |= MT_REALM;
+ break;
+ default:
+ /* unreachable code */
+ assert(false);
+ break;
+ }
+#else /* !ENABLE_RME */
+ if (ns_bit == 1ULL) {
+ *attributes |= MT_NS;
+ } else {
+ *attributes |= MT_SECURE;
+ }
+#endif /* ENABLE_RME */
uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index b51ed27..ceff4ba 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -280,7 +280,7 @@
ENABLE_FEAT_AMU ?= 0
ENABLE_AMU_AUXILIARY_COUNTERS ?= 0
ENABLE_AMU_FCONF ?= 0
-AMU_RESTRICT_COUNTERS ?= 0
+AMU_RESTRICT_COUNTERS ?= 1
# Build option to enable MPAM for lower ELs.
# Enabling it by default
@@ -337,6 +337,9 @@
# Disable MTPMU if FEAT_MTPMU is supported.
DISABLE_MTPMU ?= 0
+# Flag to enable FEAT_FGT2 (Fine Granular Traps 2)
+ENABLE_FEAT_FGT2 ?= 0
+
#----
# 8.9
#----
diff --git a/make_helpers/build-rules.mk b/make_helpers/build-rules.mk
new file mode 100644
index 0000000..d325b3a
--- /dev/null
+++ b/make_helpers/build-rules.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifndef build-rules-mk
+ build-rules-mk := $(lastword $(MAKEFILE_LIST))
+
+ include $(dir $(build-rules-mk))common.mk
+ include $(dir $(build-rules-mk))utilities.mk
+
+ .SECONDEXPANSION:
+
+ %/:
+ $(s)echo ' MD '$(call escape-shell,$(abspath $@))
+ $(q)mkdir -p $(call escape-shell,$@)
+endif
diff --git a/make_helpers/build_env.mk b/make_helpers/build_env.mk
index a545cd0..13acaae 100644
--- a/make_helpers/build_env.mk
+++ b/make_helpers/build_env.mk
@@ -15,8 +15,6 @@
COPY := $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.")
CP := $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.")
DEL := $$(error "Replace DEL with call to SHELL_DELETE.")
- MD := $$(error "Replace MD with call to MAKE_PREREQ_DIR.")
- MKDIR := $$(error "Replace MKDIR with call to MAKE_PREREQ_DIR.")
RD := $$(error "Replace RD with call to SHELL_REMOVE_DIR.")
RM := $$(error "Replace RM with call to SHELL_DELETE.")
RMDIR := $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.")
@@ -62,9 +60,6 @@
ifndef SHELL_DELETE
$(error "SHELL_DELETE not defined for build environment.")
endif
- ifndef MAKE_PREREQ_DIR
- $(error "MAKE_PREREQ_DIR not defined for build environment.")
- endif
ifndef SHELL_REMOVE_DIR
$(error "SHELL_REMOVE_DIR not defined for build environment.")
endif
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 23dd592..f523074 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -289,7 +289,7 @@
$(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
$(eval LIB := $(call uppercase, $(notdir $(1))))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " CC $$<"
$$(q)$($(ARCH)-cc) $$($(LIB)_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -305,7 +305,7 @@
$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
$(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " AS $$<"
$$(q)$($(ARCH)-as) -x assembler-with-cpp $$(TF_CFLAGS_$(ARCH)) $$(ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -328,7 +328,7 @@
$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)) $(PLAT_BL_COMMON_CPPFLAGS))
$(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS) $(PLAT_BL_COMMON_CFLAGS))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " CC $$<"
$$(q)$($(ARCH)-cc) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -351,7 +351,7 @@
$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)) $(PLAT_BL_COMMON_CPPFLAGS))
$(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS) $(PLAT_BL_COMMON_ASFLAGS))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " AS $$<"
$$(q)$($(ARCH)-as) -x assembler-with-cpp $$(TF_CFLAGS_$(ARCH)) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -372,7 +372,7 @@
$(eval BL_INCLUDE_DIRS := $($(call uppercase,$(3))_INCLUDE_DIRS) $(PLAT_BL_COMMON_INCLUDE_DIRS))
$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)) $(PLAT_BL_COMMON_CPPFLAGS))
-$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
+$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " PP $$<"
$$(q)$($(ARCH)-cpp) -E $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$<
@@ -424,17 +424,6 @@
.PHONY: libraries
-# MAKE_LIB_DIRS macro defines the target for the directory where
-# libraries are created
-define MAKE_LIB_DIRS
- $(eval LIB_DIR := ${BUILD_PLAT}/lib)
- $(eval ROMLIB_DIR := ${BUILD_PLAT}/romlib)
- $(eval LIBWRAPPER_DIR := ${BUILD_PLAT}/libwrapper)
- $(eval $(call MAKE_PREREQ_DIR,${LIB_DIR},${BUILD_PLAT}))
- $(eval $(call MAKE_PREREQ_DIR,${ROMLIB_DIR},${BUILD_PLAT}))
- $(eval $(call MAKE_PREREQ_DIR,${LIBWRAPPER_DIR},${BUILD_PLAT}))
-endef
-
# MAKE_LIB macro defines the targets and options to build each BL image.
# Arguments:
# $(1) = Library name
@@ -445,11 +434,8 @@
$(eval SOURCES := $(LIB$(call uppercase,$(1))_SRCS))
$(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT}))
$(eval $(call MAKE_LIB_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
-.PHONY : lib${1}_dirs
-lib${1}_dirs: | ${BUILD_DIR} ${LIB_DIR} ${ROMLIB_DIR} ${LIBWRAPPER_DIR}
libraries: ${LIB_DIR}/lib$(1).a
ifeq ($($(ARCH)-ld-id),arm-link)
LDPATHS = --userlibpath=${LIB_DIR}
@@ -465,7 +451,7 @@
all: ${LIB_DIR}/lib$(1).a
-${LIB_DIR}/lib$(1).a: $(OBJS)
+${LIB_DIR}/lib$(1).a: $(OBJS) | $$$$(@D)/
$$(s)echo " AR $$@"
$$(q)$($(ARCH)-ar) cr $$@ $$?
endef
@@ -507,26 +493,6 @@
$(eval LINKER_SCRIPT_SOURCES := $($(call uppercase,$(1))_LINKER_SCRIPT_SOURCES))
$(eval LINKER_SCRIPTS := $(call linker_script_path,$(LINKER_SCRIPT_SOURCES)))
- # We use sort only to get a list of unique object directory names.
- # ordering is not relevant but sort removes duplicates.
- $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS} ${DEFAULT_LINKER_SCRIPT} ${LINKER_SCRIPTS})))
- # The $(dir ) function leaves a trailing / on the directory names
- # Rip off the / to match directory names with make rule targets.
- $(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS)))
-
-# Create generators for object directory structure
-
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT}))
-
-$(eval $(foreach objd,${OBJ_DIRS},
- $(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-
-.PHONY : ${1}_dirs
-
-# We use order-only prerequisites to ensure that directories are created,
-# but do not cause re-builds every time a file is written.
-${1}_dirs: | ${OBJ_DIRS}
-
$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
# Generate targets to preprocess each required linker script
@@ -536,14 +502,14 @@
$(eval BL_LDFLAGS := $($(call uppercase,$(1))_LDFLAGS))
ifeq ($(USE_ROMLIB),1)
-$(ELF): romlib.bin
+$(ELF): romlib.bin | $$$$(@D)/
endif
# MODULE_OBJS can be assigned by vendors with different compiled
# object file path, and prebuilt object file path.
$(eval OBJS += $(MODULE_OBJS))
-$(ELF): $(OBJS) $(DEFAULT_LINKER_SCRIPT) $(LINKER_SCRIPTS) | $(1)_dirs libraries $(BL_LIBS)
+$(ELF): $(OBJS) $(DEFAULT_LINKER_SCRIPT) $(LINKER_SCRIPTS) | $$$$(@D)/ libraries $(BL_LIBS)
$$(s)echo " LD $$@"
ifeq ($($(ARCH)-ld-id),arm-link)
$$(q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \
@@ -566,11 +532,11 @@
$(s)echo
endif
-$(DUMP): $(ELF)
+$(DUMP): $(ELF) | $$$$(@D)/
$$(s)echo " OD $$@"
$$(q)$($(ARCH)-od) -dx $$< > $$@
-$(BIN): $(ELF)
+$(BIN): $(ELF) | $$$$(@D)/
$$(s)echo " BIN $$@"
$$(q)$($(ARCH)-oc) -O binary $$< $$@
$(s)echo
@@ -602,22 +568,6 @@
$(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1))))
endef
-# MAKE_FDT_DIRS macro creates the prerequisite directories that host the
-# FDT binaries
-# $(1) = output directory
-# $(2) = input dts
-define MAKE_FDT_DIRS
- $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
- $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS})))
- # The $(dir ) function leaves a trailing / on the directory names
- # Rip off the / to match directory names with make rule targets.
- $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS)))
-
-$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-
-fdt_dirs: ${DTB_DIRS}
-endef
-
# MAKE_DTB generate the Flattened device tree binary
# $(1) = output directory
# $(2) = input dts
@@ -632,12 +582,12 @@
# Dependencies of the DT compilation on its pre-compiled DTS
$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DOBJ)))
-$(DPRE): $(2) | fdt_dirs
+$(DPRE): $(2) | $$$$(@D)/
$$(s)echo " CPP $$<"
$(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
$$(q)$($(ARCH)-cpp) -E $$(TF_CFLAGS_$(ARCH)) $$(DTC_CPPFLAGS) -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$<
-$(DOBJ): $(DPRE) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs
+$(DOBJ): $(DPRE) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " DTC $$<"
$$(q)$($(ARCH)-dtc) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $$<
@@ -655,8 +605,6 @@
$(and $(REMAIN),$(error FDT_SOURCES contain non-DTS files: $(REMAIN)))
$(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj))))
- $(eval $(call MAKE_FDT_DIRS,$(1),$(2)))
-
-dtbs: $(DTBS)
+dtbs: $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))
all: dtbs
endef
diff --git a/make_helpers/unix.mk b/make_helpers/unix.mk
index 4fd819a..fa7722a 100644
--- a/make_helpers/unix.mk
+++ b/make_helpers/unix.mk
@@ -38,18 +38,6 @@
-$(q)rm -rf ${1}
endef
- # ${1} is the directory to be generated.
- # ${2} is optional, and allows a prerequisite to be specified.
- # Do nothing if $1 == $2, to ignore self dependencies.
- define MAKE_PREREQ_DIR
- ifneq (${1},${2})
-
-${1} : ${2}
- $(q)mkdir -p "${1}"
-
- endif
- endef
-
define SHELL_REMOVE_DIR
-$(q)rm -rf "${1}"
endef
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
index 2f5d51b..c24aa08 100644
--- a/make_helpers/windows.mk
+++ b/make_helpers/windows.mk
@@ -47,19 +47,6 @@
$(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename})))
endef
- # ${1} is the directory to be generated.
- # ${2} is optional, and allows prerequisites to be specified.
- # Do nothing if $1 == $2, to ignore self dependencies.
- define MAKE_PREREQ_DIR
- ifneq (${1},${2})
-
-${1} : ${2}
- $(eval tmp_dir:=$(subst /,\,${1}))
- -@if not exist "$(tmp_dir)" mkdir "${tmp_dir}"
-
- endif
- endef
-
# ${1} is the directory to be removed.
define SHELL_REMOVE_DIR
$(eval tmp_dir:=$(subst /,\,${1}))
diff --git a/package-lock.json b/package-lock.json
index a6bb905..26caae4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1172,12 +1172,12 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -2395,9 +2395,9 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -4903,7 +4903,7 @@
}
},
"tools/conventional-changelog-tf-a": {
- "version": "2.10.0",
+ "version": "2.11.0",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h
index 6a38657..b9ca3f6 100644
--- a/plat/allwinner/common/include/sunxi_private.h
+++ b/plat/allwinner/common/include/sunxi_private.h
@@ -58,4 +58,12 @@
}
#endif
+#ifdef PLAT_sun50i_h616
+void sunxi_soc_fdt_fixup(void *dtb);
+#else
+static inline void sunxi_soc_fdt_fixup(void *dtb)
+{
+}
+#endif
+
#endif /* SUNXI_PRIVATE_H */
diff --git a/plat/allwinner/common/sunxi_prepare_dtb.c b/plat/allwinner/common/sunxi_prepare_dtb.c
index 66af35a..0f68974 100644
--- a/plat/allwinner/common/sunxi_prepare_dtb.c
+++ b/plat/allwinner/common/sunxi_prepare_dtb.c
@@ -34,6 +34,8 @@
}
#endif
+ sunxi_soc_fdt_fixup(fdt);
+
if (sunxi_psci_is_scpi()) {
ret = fdt_add_cpu_idle_states(fdt, sunxi_idle_states);
if (ret < 0) {
diff --git a/plat/allwinner/sun50i_h616/platform.mk b/plat/allwinner/sun50i_h616/platform.mk
index de494a2..6f44e8c 100644
--- a/plat/allwinner/sun50i_h616/platform.mk
+++ b/plat/allwinner/sun50i_h616/platform.mk
@@ -18,5 +18,8 @@
$(error "H616 does not support SCPI PSCI ops")
endif
-BL31_SOURCES += drivers/allwinner/axp/axp805.c \
+BL31_SOURCES += common/fdt_wrappers.c \
+ drivers/allwinner/axp/axp805.c \
drivers/allwinner/sunxi_rsb.c \
+ drivers/mentor/i2c/mi2cv.c \
+ ${AW_PLAT}/${PLAT}/sunxi_h616_dtb.c
diff --git a/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c b/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c
new file mode 100644
index 0000000..58bad53
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Amend the device tree to adjust the L2 cache size, which is different
+ * between the revisions of the H616 chips: earlier versions have 256 KB of L2,
+ * later versions 1 MB.
+ * Read the cache ID registers and adjust the size and number of sets entries
+ * in the L2 cache DT node.
+ */
+
+#include <common/fdt_wrappers.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#define CACHE_L1D 0x0
+#define CACHE_L1I 0x1
+#define CACHE_L2U 0x2
+
+#define CCSIDR_SETS_SHIFT 13
+#define CCSIDR_SETS_MASK GENMASK(14, 0)
+#define CCSIDR_ASSOC_SHIFT 3
+#define CCSIDR_ASSOC_MASK GENMASK(9, 0)
+#define CCSIDR_LSIZE_SHIFT 0
+#define CCSIDR_LSIZE_MASK GENMASK(2, 0)
+
+static uint32_t armv8_get_ccsidr(unsigned int sel)
+{
+ uint32_t reg;
+
+ __asm__ volatile ("msr CSSELR_EL1, %0\n" :: "r" (sel));
+ __asm__ volatile ("mrs %0, CCSIDR_EL1\n" : "=r" (reg));
+
+ return reg;
+}
+
+void sunxi_soc_fdt_fixup(void *dtb)
+{
+ int node = fdt_path_offset(dtb, "/cpus/cpu@0");
+ uint32_t phandle, ccsidr, cell;
+ int sets, line_size, assoc;
+ int ret;
+
+ if (node < 0) {
+ return;
+ }
+
+ ret = fdt_read_uint32(dtb, node, "next-level-cache", &phandle);
+ if (ret != 0) {
+ return;
+ }
+
+ node = fdt_node_offset_by_phandle(dtb, phandle);
+ if (node < 0) {
+ return;
+ }
+
+ ccsidr = armv8_get_ccsidr(CACHE_L2U);
+ sets = ((ccsidr >> CCSIDR_SETS_SHIFT) & CCSIDR_SETS_MASK) + 1;
+ line_size = 16U << ((ccsidr >> CCSIDR_LSIZE_SHIFT) & CCSIDR_LSIZE_MASK);
+ assoc = ((ccsidr >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK) + 1;
+
+ cell = cpu_to_fdt32(sets);
+ fdt_setprop(dtb, node, "cache-sets", &cell, sizeof(cell));
+
+ cell = cpu_to_fdt32(line_size);
+ fdt_setprop(dtb, node, "cache-line-size", &cell, sizeof(cell));
+
+ cell = cpu_to_fdt32(sets * assoc * line_size);
+ fdt_setprop(dtb, node, "cache-size", &cell, sizeof(cell));
+}
diff --git a/plat/allwinner/sun50i_h616/sunxi_power.c b/plat/allwinner/sun50i_h616/sunxi_power.c
index dd6ebba..cab7e46 100644
--- a/plat/allwinner/sun50i_h616/sunxi_power.c
+++ b/plat/allwinner/sun50i_h616/sunxi_power.c
@@ -10,97 +10,254 @@
#include <arch_helpers.h>
#include <common/debug.h>
+#include <common/fdt_wrappers.h>
#include <drivers/allwinner/axp.h>
#include <drivers/allwinner/sunxi_rsb.h>
+#include <drivers/mentor/mi2cv.h>
#include <lib/mmio.h>
+#include <libfdt.h>
#include <sunxi_cpucfg.h>
#include <sunxi_def.h>
#include <sunxi_mmap.h>
#include <sunxi_private.h>
-#define AXP305_I2C_ADDR 0x36
-#define AXP305_HW_ADDR 0x745
-#define AXP305_RT_ADDR 0x3a
+static uint16_t pmic_bus_addr;
+static uint8_t rsb_rt_addr;
+
+static bool is_using_rsb(void)
+{
+ return rsb_rt_addr != 0;
+}
static enum pmic_type {
UNKNOWN,
AXP305,
+ AXP313,
+ AXP717,
} pmic;
+static uint8_t get_rsb_rt_address(uint16_t hw_addr)
+{
+ switch (hw_addr) {
+ case 0x3a3: return 0x2d;
+ case 0x745: return 0x3a;
+ }
+
+ return 0;
+}
+
int axp_read(uint8_t reg)
{
- return rsb_read(AXP305_RT_ADDR, reg);
+ uint8_t val;
+ int ret;
+
+ if (is_using_rsb()) {
+ return rsb_read(rsb_rt_addr, reg);
+ }
+
+ ret = i2c_write(pmic_bus_addr, 0, 0, ®, 1);
+ if (ret == 0) {
+ ret = i2c_read(pmic_bus_addr, 0, 0, &val, 1);
+ }
+ if (ret) {
+ ERROR("PMIC: Cannot read PMIC register %02x\n", reg);
+ return ret;
+ }
+
+ return val;
}
int axp_write(uint8_t reg, uint8_t val)
{
- return rsb_write(AXP305_RT_ADDR, reg, val);
+ int ret;
+
+ if (is_using_rsb()) {
+ return rsb_write(rsb_rt_addr, reg, val);
+ }
+
+ ret = i2c_write(pmic_bus_addr, reg, 1, &val, 1);
+ if (ret) {
+ ERROR("PMIC: Cannot write PMIC register %02x\n", reg);
+ }
+
+ return ret;
}
-static int rsb_init(void)
+static int rsb_init(int rsb_hw_addr)
{
int ret;
ret = rsb_init_controller();
- if (ret)
+ if (ret) {
return ret;
+ }
/* Switch to the recommended 3 MHz bus clock. */
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
- if (ret)
+ if (ret) {
return ret;
+ }
/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
- if (ret)
+ if (ret) {
return ret;
+ }
/* Associate the 8-bit runtime address with the 12-bit bus address. */
- ret = rsb_assign_runtime_address(AXP305_HW_ADDR, AXP305_RT_ADDR);
- if (ret)
+ ret = rsb_assign_runtime_address(rsb_hw_addr, rsb_rt_addr);
+ if (ret) {
return ret;
+ }
- return axp_check_id();
+ return 0;
}
-int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+static int pmic_bus_init(uint16_t socid, uint16_t rsb_hw_addr)
{
int ret;
- INFO("PMIC: Probing AXP305 on RSB\n");
-
- ret = sunxi_init_platform_r_twi(socid, true);
+ ret = sunxi_init_platform_r_twi(socid, is_using_rsb());
if (ret) {
INFO("Could not init platform bus: %d\n", ret);
+ pmic = UNKNOWN;
return ret;
}
+ if (is_using_rsb()) {
+ ret = rsb_init(rsb_hw_addr);
+ if (ret) {
+ pmic = UNKNOWN;
+ return ret;
+ }
+ } else {
+ /* initialise mi2cv driver */
+ i2c_init((void *)SUNXI_R_I2C_BASE);
+ }
+
+ return 0;
+}
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ int node, parent, ret;
+ uint32_t reg;
+
+ node = fdt_node_offset_by_compatible(fdt, 0, "x-powers,axp806");
+ if (node >= 0) {
+ pmic = AXP305;
+ }
+
+ if (pmic == UNKNOWN) {
+ node = fdt_node_offset_by_compatible(fdt, 0, "x-powers,axp313a");
+ if (node >= 0) {
+ pmic = AXP313;
+ }
+ }
+
+ if (pmic == UNKNOWN) {
+ node = fdt_node_offset_by_compatible(fdt, 0, "x-powers,axp717");
+ if (node >= 0) {
+ pmic = AXP717;
+ }
+ }
+
+ if (pmic == UNKNOWN) {
+ INFO("PMIC: No known PMIC in DT, skipping setup.\n");
+ return -ENODEV;
+ }
+
- ret = rsb_init();
+ if (fdt_read_uint32(fdt, node, "reg", ®)) {
+ ERROR("PMIC: PMIC DT node does not contain reg property.\n");
+ return -EINVAL;
+ }
+
+ pmic_bus_addr = reg;
+ parent = fdt_parent_offset(fdt, node);
+ ret = fdt_node_check_compatible(fdt, parent, "allwinner,sun8i-a23-rsb");
+ if (ret == 0) {
+ rsb_rt_addr = get_rsb_rt_address(pmic_bus_addr);
+ if (rsb_rt_addr == 0) {
+ ERROR("PMIC: no mapping for RSB address 0x%x\n",
+ pmic_bus_addr);
+ return -EINVAL;
+ }
+ }
+
+ INFO("Probing for PMIC on %s:\n", is_using_rsb() ? "RSB" : "I2C");
+
+ ret = pmic_bus_init(socid, pmic_bus_addr);
if (ret) {
- INFO("Could not init RSB: %d\n", ret);
return ret;
}
- pmic = AXP305;
- axp_setup_regulators(fdt);
+ ret = axp_read(0x03);
+ switch (ret & 0xcf) {
+ case 0x40: /* AXP305 */
+ if (pmic == AXP305) {
+ INFO("PMIC: found AXP305, setting up regulators\n");
+ axp_setup_regulators(fdt);
+ } else {
+ pmic = UNKNOWN;
+ }
+ break;
+ case 0x48: /* AXP1530 */
+ case 0x4b: /* AXP313A */
+ case 0x4c: /* AXP313B */
+ if (pmic == AXP313) {
+ INFO("PMIC: found AXP313\n");
+ /* no regulators to set up */
+ } else {
+ pmic = UNKNOWN;
+ }
+ break;
+ case 0xcf: /* version reg not implemented on AXP717 */
+ if (pmic == AXP717) {
+ INFO("PMIC: found AXP717\n");
+ /* no regulators to set up, U-Boot takes care of this */
+ } else {
+ pmic = UNKNOWN;
+ }
+ break;
+ }
- /* Switch the PMIC back to I2C mode. */
- ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
- if (ret)
- return ret;
+ if (is_using_rsb()) {
+ /* Switch the PMIC back to I2C mode. */
+ return rsb_write(rsb_rt_addr, AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ }
+
+ if (pmic == UNKNOWN) {
+ INFO("Incompatible or unknown PMIC found.\n");
+ return -ENODEV;
+ }
return 0;
}
void sunxi_power_down(void)
{
+ int ret;
+
+ if (pmic == UNKNOWN) {
+ return;
+ }
+
+ /* Re-initialise after rich OS might have used it. */
+ ret = pmic_bus_init(SUNXI_SOC_H616, pmic_bus_addr);
+ if (ret) {
+ return;
+ }
+
switch (pmic) {
case AXP305:
- /* Re-initialise after rich OS might have used it. */
- sunxi_init_platform_r_twi(SUNXI_SOC_H616, true);
- rsb_init();
- axp_power_off();
+ axp_setbits(0x32, BIT(7));
+ break;
+ case AXP313:
+ axp_setbits(0x1a, BIT(7));
+ break;
+ case AXP717:
+ axp_setbits(0x27, BIT(0));
break;
default:
break;
diff --git a/plat/amd/versal2/include/def.h b/plat/amd/versal2/include/def.h
index a8cbaaf..67244a4 100644
--- a/plat/amd/versal2/include/def.h
+++ b/plat/amd/versal2/include/def.h
@@ -125,6 +125,10 @@
#define APU_CLUSTER_STEP U(0x100000)
#define SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL U(0xF1060504)
+#define PMXC_IOU_SLCR_SRAM_CSR U(0xF106104C)
+#define PMXC_IOU_SLCR_PHY_RESET U(0xF1061050)
+#define PMXC_IOU_SLCR_TX_RX_CONFIG_RDY U(0xF1061054)
+#define PMXC_CRP_RST_UFS U(0xF1260340)
/*******************************************************************************
* IRQ constants
diff --git a/plat/amd/versal2/include/versal2-scmi.h b/plat/amd/versal2/include/versal2-scmi.h
index 4d581e4..c08b4b1 100644
--- a/plat/amd/versal2/include/versal2-scmi.h
+++ b/plat/amd/versal2/include/versal2-scmi.h
@@ -136,5 +136,9 @@
#define RESET_I3C6_0 32
#define RESET_I3C7_0 33
#define RESET_I3C8_0 34
+#define RESET_UFSPHY_0 35
+
+#define PD_USB0 0
+#define PD_USB1 1
#endif /* _VERSAL2_SCMI_H */
diff --git a/plat/amd/versal2/plat_psci.c b/plat/amd/versal2/plat_psci.c
index 4faa434..6f0cbcb 100644
--- a/plat/amd/versal2/plat_psci.c
+++ b/plat/amd/versal2/plat_psci.c
@@ -161,12 +161,29 @@
static int32_t no_pm_ioctl(uint32_t device_id, uint32_t ioctl_id,
uint32_t arg1, uint32_t arg2)
{
+ int32_t ret = 0;
VERBOSE("%s: ioctl_id: %x, arg1: %x\n", __func__, ioctl_id, arg1);
- if (ioctl_id == IOCTL_OSPI_MUX_SELECT) {
+
+ switch (ioctl_id) {
+ case IOCTL_OSPI_MUX_SELECT:
mmio_write_32(SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL, arg1);
- return 0;
+ break;
+ case IOCTL_UFS_TXRX_CFGRDY_GET:
+ ret = (int32_t) mmio_read_32(PMXC_IOU_SLCR_TX_RX_CONFIG_RDY);
+ break;
+ case IOCTL_UFS_SRAM_CSR_SEL:
+ if (arg1 == 1) {
+ ret = (int32_t) mmio_read_32(PMXC_IOU_SLCR_SRAM_CSR);
+ } else if (arg1 == 0) {
+ mmio_write_32(PMXC_IOU_SLCR_SRAM_CSR, arg2);
+ }
+ break;
+ default:
+ ret = PM_RET_ERROR_NOFEATURE;
+ break;
}
- return PM_RET_ERROR_NOFEATURE;
+
+ return ret;
}
static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
@@ -187,7 +204,13 @@
case PM_IOCTL:
{
ret = no_pm_ioctl(arg[0], arg[1], arg[2], arg[3]);
- SMC_RET1(handle, (uint64_t)ret);
+ /* Firmware driver expects return code in upper 32 bits and
+ * status in lower 32 bits.
+ * status is always SUCCESS(0) for mmio low level register
+ * r/w calls and return value is the value returned from
+ * no_pm_ioctl
+ */
+ SMC_RET1(handle, ((uint64_t)ret << 32));
}
case PM_GET_CHIPID:
{
diff --git a/plat/amd/versal2/scmi.c b/plat/amd/versal2/scmi.c
index c3c517a..7f4b6df 100644
--- a/plat/amd/versal2/scmi.c
+++ b/plat/amd/versal2/scmi.c
@@ -10,6 +10,7 @@
#include <drivers/scmi-msg.h>
#include <drivers/scmi.h>
+#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <platform_def.h>
#include <scmi.h>
@@ -179,14 +180,40 @@
RESET_CELL(RESET_I3C6_0, RESET_I3C6_0, "i3c6"),
RESET_CELL(RESET_I3C7_0, RESET_I3C7_0, "i3c7"),
RESET_CELL(RESET_I3C8_0, RESET_I3C8_0, "i3c8"),
+ RESET_CELL(RESET_UFSPHY_0, RESET_UFSPHY_0, "ufsphy0"),
};
+/**
+ * struct scmi_pd - Data for the exposed power domain controller
+ * @pd_id: pd identifier in RCC reset driver
+ * @name: pd string ID exposed to agent
+ * @state: keep state setting
+ */
+struct scmi_pd {
+ unsigned long pd_id;
+ const char *name;
+ unsigned int state;
+};
+
+#define PD_CELL(_scmi_id, _id, _name, _state) \
+ [_scmi_id] = { \
+ .pd_id = _id, \
+ .name = _name, \
+ .state = _state, \
+ }
+
+static struct scmi_pd scmi0_pd[] = {
+ PD_CELL(PD_USB0, PD_USB0, "usb0", 0),
+ PD_CELL(PD_USB1, PD_USB1, "usb1", 0),
+};
+
struct scmi_resources {
struct scmi_clk *clock;
size_t clock_count;
struct scmi_reset *reset;
size_t reset_count;
-
+ struct scmi_pd *pd;
+ size_t pd_count;
};
static const struct scmi_resources resources[] = {
@@ -195,6 +222,8 @@
.clock_count = ARRAY_SIZE(scmi0_clock),
.reset = scmi0_reset,
.reset_count = ARRAY_SIZE(scmi0_reset),
+ .pd = scmi0_pd,
+ .pd_count = ARRAY_SIZE(scmi0_pd),
},
};
@@ -433,14 +462,122 @@
if (assert_not_deassert) {
NOTICE("SCMI reset %lu/%s set\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
+
+ switch (scmi_id) {
+ case RESET_UFS0_0:
+ mmio_write_32(PMXC_CRP_RST_UFS, 1);
+ break;
+ case RESET_UFSPHY_0:
+ mmio_write_32(PMXC_IOU_SLCR_PHY_RESET, 1);
+ break;
+ default:
+ break;
+ }
} else {
NOTICE("SCMI reset %lu/%s release\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
+
+ switch (scmi_id) {
+ case RESET_UFS0_0:
+ mmio_write_32(PMXC_CRP_RST_UFS, 0);
+ break;
+ case RESET_UFSPHY_0:
+ mmio_write_32(PMXC_IOU_SLCR_PHY_RESET, 0);
+ break;
+ default:
+ break;
+ }
}
return SCMI_SUCCESS;
}
+/*
+ * Platform SCMI reset domains
+ */
+static struct scmi_pd *find_pd(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_resources *resource = find_resource(agent_id);
+ size_t n;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->pd_count; n++) {
+ if (n == pd_id) {
+ return &resource->pd[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+size_t plat_scmi_pd_count(unsigned int agent_id)
+{
+ const struct scmi_resources *resource = find_resource(agent_id);
+ size_t ret;
+
+ if (resource == NULL) {
+ ret = 0U;
+ } else {
+ ret = resource->pd_count;
+
+ NOTICE("SCMI: PD: %d\n", (unsigned int)ret);
+ }
+ return ret;
+}
+
+const char *plat_scmi_pd_get_name(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return NULL;
+ }
+
+ return pd->name;
+}
+
+unsigned int plat_scmi_pd_statistics(unsigned int agent_id, unsigned long *pd_id)
+{
+ return 0U;
+}
+
+unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id, unsigned int pd_id)
+{
+ return 0U;
+}
+
+unsigned int plat_scmi_pd_get_state(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ NOTICE("SCMI: PD: get id: %d, state: %x\n", pd_id, pd->state);
+
+ return pd->state;
+}
+
+int32_t plat_scmi_pd_set_state(unsigned int agent_id, unsigned int flags, unsigned int pd_id,
+ unsigned int state)
+{
+ struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ NOTICE("SCMI: PD: set id: %d, orig state: %x, new state: %x, flags: %x\n",
+ pd_id, pd->state, state, flags);
+
+ pd->state = state;
+
+ return 0U;
+}
+
+
/* Currently only one channel is supported. Expectation is that channel 0 is used by NS SW */
static struct scmi_msg_channel scmi_channel[] = {
[0] = {
@@ -475,10 +612,8 @@
SCMI_PROTOCOL_ID_BASE,
SCMI_PROTOCOL_ID_CLOCK,
SCMI_PROTOCOL_ID_RESET_DOMAIN,
- /*
- *SCMI_PROTOCOL_ID_POWER_DOMAIN,
- *SCMI_PROTOCOL_ID_SENSOR,
- */
+ SCMI_PROTOCOL_ID_POWER_DOMAIN,
+ /* SCMI_PROTOCOL_ID_SENSOR, */
0U /* Null termination */
};
diff --git a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
index 457d181..de6a15a 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, 2024 ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -77,7 +77,8 @@
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
.ep_info.pc = BL33_BASE,
-
+ .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
.image_info.image_base = BL33_BASE,
diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c
index ed3801c..e388c82 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_plat.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,7 +23,6 @@
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
- ARM_MAP_NS_SHARED_RAM,
ARM_MAP_NS_DRAM1,
CORSTONE1000_MAP_DEVICE,
CORSTONE1000_EXTERNAL_FLASH,
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
index ee07605..bd3faec 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -7,6 +7,8 @@
#include <lib/psci/psci.h>
#include <plat/arm/common/plat_arm.h>
#include <platform_def.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/gicv2.h>
/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform layer will take care of registering the handlers with PSCI.
@@ -18,6 +20,15 @@
uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG;
uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG;
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt
+ * from waking up the AP from WFI.
+ */
+ gicv2_cpuif_disable();
+
+ /* Flush and invalidate data cache */
+ dcsw_op_all(DCCISW);
+
*(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL;
*watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
while (1) {
diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
index e3f3268..caf3d46 100644
--- a/plat/arm/board/corstone1000/common/include/platform_def.h
+++ b/plat/arm/board/corstone1000/common/include/platform_def.h
@@ -55,42 +55,42 @@
/* Memory related constants */
-/* SRAM (CVM) memory layout
+/* Memory mappings of where the BLs in the FIP are copied to
*
- * <ARM_TRUSTED_SRAM_BASE>
+ * <ARM_TRUSTED_SRAM_BASE> = 0x02000000
* partition size: sizeof(meminfo_t) = 16 bytes
* content: memory info area used by the next BL
*
- * <ARM_FW_CONFIG_BASE>
+ * <ARM_FW_CONFIG_BASE> = 0x02000010
* partition size: 4080 bytes
*
- * <ARM_BL2_MEM_DESC_BASE>
+ * <ARM_BL2_MEM_DESC_BASE> = 0x02001000
* partition size: 4 KB
* content: Area where BL2 copies the images descriptors
*
- * <ARM_BL_RAM_BASE> = <BL32_BASE>
- * partition size: 688 KB
+ * <ARM_BL_RAM_BASE> = <BL32_BASE> = 0x02002000
+ * partition size: 3752 KB
* content: BL32 (optee-os)
*
- * <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x20ae000
+ * <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x023AC000
* partition size: 8 KB
* content: BL32 config (TOS_FW_CONFIG)
*
- * <BL31_BASE>
+ * <BL31_BASE> = 0x023AE000
* partition size: 140 KB
* content: BL31
*
- * <BL2_SIGNATURE_BASE>
+ * <BL2_SIGNATURE_BASE> = 0x023D1000
* partition size: 4 KB
* content: MCUBOOT data needed to verify TF-A BL2
*
- * <BL2_BASE>
+ * <BL2_BASE> = 0x023D2000
* partition size: 176 KB
* content: BL2
*
- * <ARM_NS_SHARED_RAM_BASE> = <ARM_TRUSTED_SRAM_BASE> + 1 MB
- * partition size: 512 KB
- * content: BL33 (u-boot)
+ * <BL33_BASE> = 0x80000000
+ * partition size: 12 MB
+ * content: BL33 (U-Boot)
*/
/* DDR memory */
@@ -115,11 +115,8 @@
/* The remaining Trusted SRAM is used to load the BL images */
#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */
-/* Last 512KB of CVM is allocated for shared RAM as an example openAMP */
-#define ARM_NS_SHARED_RAM_SIZE (512 * SZ_1K)
#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \
- ARM_NS_SHARED_RAM_SIZE - \
ARM_SHARED_RAM_SIZE)
#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */
@@ -158,11 +155,6 @@
/* NS memory */
-/* The last 512KB of the SRAM is allocated as shared memory */
-#define ARM_NS_SHARED_RAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SRAM_SIZE - \
- (PLAT_ARM_MAX_BL31_SIZE + \
- PLAT_ARM_MAX_BL32_SIZE))
-
#define BL33_BASE ARM_DRAM1_BASE
#define PLAT_ARM_MAX_BL33_SIZE (12 * SZ_1M) /* 12 MB*/
#define BL33_LIMIT (ARM_DRAM1_BASE + PLAT_ARM_MAX_BL33_SIZE)
@@ -277,7 +269,7 @@
#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
-#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
+#define PLAT_ARM_NS_IMAGE_BASE (BL33_BASE)
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
@@ -306,11 +298,6 @@
ARM_SHARED_RAM_SIZE, \
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, \
ARM_NS_DRAM1_SIZE, \
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 9fba4af..bf0e7f3 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -99,12 +99,17 @@
memory@2 {
device_type = "device-memory";
- reg = <0x0 0x1c090000 0x0 0x40000>, /* UART */
+ reg = <0x0 0x1c0b0000 0x0 0x20000>, /* UART 2-3 */
<0x0 0x2bfe0000 0x0 0x20000>, /* SMMUv3TestEngine */
<0x0 0x2a490000 0x0 0x20000>, /* SP805 Trusted Watchdog */
<0x0 0x1c130000 0x0 0x10000>; /* Virtio block device */
};
+ memory@3 {
+ device_type = "ns-device-memory";
+ reg = <0x0 0x1c090000 0x0 0x20000>; /* UART 0-1 */
+ };
+
#if MEASURED_BOOT
#include "event_log.dtsi"
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index b1d3bc1..f5d7f65 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -117,16 +117,16 @@
#if defined(ARM_COT_cca)
/* FVP does not support the CCA NV Counter so use the Trusted one. */
-&cca_nv_counter {
+&cca_nv_ctr {
reg = <TFW_NVCTR_BASE>;
};
#endif
-&trusted_nv_counter {
+&trusted_nv_ctr {
reg = <TFW_NVCTR_BASE>;
};
-&non_trusted_nv_counter {
+&non_trusted_nv_ctr {
reg = <NTFW_CTR_BASE>;
};
#endif
diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index a6b4886..4611f80 100644
--- a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -46,6 +46,7 @@
base-address = <0x00000000 0x1c0a0000>;
pages-count = <1>;
attributes = <0x3>; /* read-write */
+ interrupts = <38 0x900>;
};
};
};
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 5557d59..0c5a76c 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -210,7 +210,7 @@
#ifdef MAP_FW_NS_HANDOFF
MAP_FW_NS_HANDOFF,
#endif
-#ifdef MAP_EL3_FW_HANDOFF
+#if defined(MAP_EL3_FW_HANDOFF) && !RESET_TO_BL31
MAP_EL3_FW_HANDOFF,
#endif
{ 0 }
@@ -219,6 +219,11 @@
#if defined(IMAGE_BL31) && SPM_MM
const mmap_region_t plat_arm_secure_partition_mmap[] = {
V2M_MAP_IOFPGA_EL0, /* for the UART */
+ V2M_MAP_SECURE_SYSTEMREG_EL0, /* for initializing flash */
+#if PSA_FWU_SUPPORT
+ V2M_MAP_FLASH0_RW_EL0, /* for firmware update service in standalone mm */
+#endif
+ V2M_MAP_FLASH1_RW_EL0, /* for secure variable service in standalone mm */
MAP_REGION_FLAT(DEVICE0_BASE,
DEVICE0_SIZE,
MT_DEVICE | MT_RO | MT_SECURE | MT_USER),
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 3c121c6..cef7bdf 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -66,6 +66,7 @@
ENABLE_TRF_FOR_NS := 2
ENABLE_FEAT_ECV := 2
ENABLE_FEAT_FGT := 2
+ENABLE_FEAT_FGT2 := 2
ENABLE_FEAT_TCR2 := 2
ENABLE_FEAT_S2PIE := 2
ENABLE_FEAT_S1PIE := 2
@@ -322,10 +323,6 @@
BL31_SOURCES += drivers/delay_timer/generic_delay_timer.c
endif
-ifeq (${TRANSFER_LIST}, 1)
-include lib/transfer_list/transfer_list.mk
-endif
-
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
ifdef UNIX_MK
FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
@@ -385,6 +382,17 @@
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
endif
+ifeq (${TRANSFER_LIST}, 1)
+include lib/transfer_list/transfer_list.mk
+
+ifeq ($(RESET_TO_BL31), 1)
+HW_CONFIG := ${FVP_HW_CONFIG}
+FW_HANDOFF_SIZE := 20000
+
+$(eval $(call add_define,ARM_PRELOADED_DTB_OFFSET))
+endif
+endif
+
# Enable dynamic mitigation support by default
DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
diff --git a/plat/arm/board/fvp_ve/fvp_ve_def.h b/plat/arm/board/fvp_ve/fvp_ve_def.h
index 98de5f6..cb4b74c 100644
--- a/plat/arm/board/fvp_ve/fvp_ve_def.h
+++ b/plat/arm/board/fvp_ve/fvp_ve_def.h
@@ -70,15 +70,4 @@
#define FVP_VE_IRQ_TZ_WDOG 56
#define FVP_VE_IRQ_SEC_SYS_TIMER 57
-#define V2M_FLASH1_BASE UL(0x0C000000)
-#define V2M_FLASH1_SIZE UL(0x04000000)
-
-#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\
- V2M_FLASH1_SIZE, \
- MT_DEVICE | MT_RW | MT_SECURE)
-
-#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\
- V2M_FLASH1_SIZE, \
- MT_RO_DATA | MT_SECURE)
-
#endif /* FVP_VE_DEF_H */
diff --git a/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c b/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
index 371bde6..cf1eb6f 100644
--- a/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
+++ b/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
@@ -62,37 +62,50 @@
cpu_info->SecurityState = security_state;
/* populate CPU EL1 context information. */
- cpu_info->ErrCtxEl1Reg[0] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_ELR_EL1);
- cpu_info->ErrCtxEl1Reg[1] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_ESR_EL1);
- cpu_info->ErrCtxEl1Reg[2] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_FAR_EL1);
+ cpu_info->ErrCtxEl1Reg[0] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ elr_el1);
+ cpu_info->ErrCtxEl1Reg[1] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ esr_el1);
+ cpu_info->ErrCtxEl1Reg[2] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ far_el1);
cpu_info->ErrCtxEl1Reg[3] = read_isr_el1();
- cpu_info->ErrCtxEl1Reg[4] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_MAIR_EL1);
+ cpu_info->ErrCtxEl1Reg[4] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ mair_el1);
cpu_info->ErrCtxEl1Reg[5] = read_midr_el1();
cpu_info->ErrCtxEl1Reg[6] = read_mpidr_el1();
- cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SCTLR_EL1);
+
+#if (ERRATA_SPECULATIVE_AT)
+ cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
+ cpu_info->ErrCtxEl1Reg[7] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ sctlr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
+
cpu_info->ErrCtxEl1Reg[8] = read_ctx_reg(get_gpregs_ctx(ctx),
CTX_GPREG_SP_EL0);
- cpu_info->ErrCtxEl1Reg[9] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SP_EL1);
- cpu_info->ErrCtxEl1Reg[10] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SPSR_EL1);
- cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TCR_EL1);
- cpu_info->ErrCtxEl1Reg[12] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TPIDR_EL0);
- cpu_info->ErrCtxEl1Reg[13] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TPIDR_EL1);
- cpu_info->ErrCtxEl1Reg[14] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TPIDRRO_EL0);
- cpu_info->ErrCtxEl1Reg[15] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TTBR0_EL1);
- cpu_info->ErrCtxEl1Reg[16] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TTBR1_EL1);
+ cpu_info->ErrCtxEl1Reg[9] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ sp_el1);
+ cpu_info->ErrCtxEl1Reg[10] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ spsr_el1);
+#if (ERRATA_SPECULATIVE_AT)
+ cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1);
+#else
+ cpu_info->ErrCtxEl1Reg[11] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ tcr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
+
+ cpu_info->ErrCtxEl1Reg[12] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ tpidr_el0);
+ cpu_info->ErrCtxEl1Reg[13] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ tpidr_el1);
+ cpu_info->ErrCtxEl1Reg[14] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ tpidrro_el0);
+ cpu_info->ErrCtxEl1Reg[15] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ ttbr0_el1);
+ cpu_info->ErrCtxEl1Reg[16] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ ttbr1_el1);
#if CTX_INCLUDE_EL2_REGS
cpu_info->ErrCtxEl2Reg[0] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
index 7d770f5..da96730 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
@@ -21,12 +21,6 @@
override ARM_ARCH_MAJOR := 8
override ARM_ARCH_MINOR := 7
-# Image flags
-override NEED_BL1 := yes
-override NEED_BL2 := yes
-override NEED_BL32 := no
-override NEED_RMM := no
-
# Misc options
override CTX_INCLUDE_AARCH32_REGS := 0
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 60c244b..45d17ba 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -7,6 +7,7 @@
#ifndef PLATFORM_DEF_H
#define PLATFORM_DEF_H
+#include <cortex_a520.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <plat/arm/board/common/board_css_def.h>
@@ -446,6 +447,21 @@
#define SLC_DONT_ALLOC 0
#define SLC_ALWAYS_ALLOC 1
#define SLC_ALLOC_BUS_SIGNAL_ATTR 2
+
+#define MCN_CONFIG_OFFSET 0x204
+#define MCN_CONFIG_ADDR (MCN_BASE_ADDR + MCN_CONFIG_OFFSET)
+#define MCN_CONFIG_SLC_PRESENT_BIT 3
+
+/*
+ * TC3 CPUs have the same definitions for:
+ * CORTEX_{A520|A725|X925}_CPUECTLR_EL1
+ * CORTEX_{A520|A725|X925}_CPUECTLR_EL1_EXTLLC_BIT
+ * Define the common macros for easier using.
+ */
+#define CPUECTLR_EL1 CORTEX_A520_CPUECTLR_EL1
+#define CPUECTLR_EL1_EXTLLC_BIT CORTEX_A520_CPUECTLR_EL1_EXTLLC_BIT
#endif /* TARGET_PLATFORM == 3 */
+#define CPUACTLR_CLUSTERPMUEN (ULL(1) << 12)
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
index 5f54856..29130ea 100644
--- a/plat/arm/board/tc/include/tc_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,9 @@
#include <platform_def.h>
#include <cpu_macros.S>
+#define TC_HANDLER(rev) plat_reset_handler_tc##rev
+#define PLAT_RESET_HANDLER(rev) TC_HANDLER(rev)
+
.globl plat_arm_calc_core_pos
.globl plat_reset_handler
@@ -49,13 +52,42 @@
ret
endfunc plat_arm_calc_core_pos
+func mark_extllc_presence
+#ifdef MCN_CONFIG_ADDR
+ mov_imm x0, (MCN_CONFIG_ADDR)
+ ldr w1, [x0]
+ ubfx x1, x1, #MCN_CONFIG_SLC_PRESENT_BIT, #1
+ sysreg_bitfield_insert_from_gpr CPUECTLR_EL1, x1, \
+ CPUECTLR_EL1_EXTLLC_BIT, 1
+#endif
+ ret
+endfunc mark_extllc_presence
+
+func enable_dsu_pmu_el1_access
+ sysreg_bit_set actlr_el2, CPUACTLR_CLUSTERPMUEN
+ sysreg_bit_set actlr_el3, CPUACTLR_CLUSTERPMUEN
+ ret
+endfunc enable_dsu_pmu_el1_access
+
+func TC_HANDLER(2)
+ ret
+endfunc TC_HANDLER(2)
+
+func TC_HANDLER(3)
+ mov x9, lr
+ bl mark_extllc_presence
+ bl enable_dsu_pmu_el1_access
+ mov lr, x9
+ ret
+endfunc TC_HANDLER(3)
+
/* -----------------------------------------------------
* void plat_reset_handler(void);
- *
- * Determine the CPU MIDR and disable power down bit for
- * that CPU.
* -----------------------------------------------------
*/
func plat_reset_handler
+ mov x8, lr
+ bl PLAT_RESET_HANDLER(TARGET_PLATFORM)
+ mov lr, x8
ret
endfunc plat_reset_handler
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 78b6945..fb70500 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -121,7 +121,8 @@
lib/cpus/aarch64/cortex_x925.S
endif
-INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c
+INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c \
+ plat/arm/common/arm_ni.c
PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \
${TC_BASE}/include/tc_helpers.S
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 7d1bc9c..53404df 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -110,6 +110,7 @@
#if TARGET_PLATFORM == 3
enable_ns_mcn_pmu();
set_mcn_slc_alloc_mode();
+ plat_arm_ni_setup(NCI_BASE_ADDR);
#endif
}
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 99243dc..b5a7db1 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -162,16 +162,6 @@
#if defined(PLAT_ARM_MEM_PROT_ADDR)
arm_nor_psci_do_static_mem_protect();
#endif
-
-#if TRANSFER_LIST
- ns_tl = transfer_list_init((void *)FW_NS_HANDOFF_BASE,
- PLAT_ARM_FW_HANDOFF_SIZE);
-
- if (ns_tl == NULL) {
- ERROR("Non-secure transfer list initialisation failed!");
- panic();
- }
-#endif
}
void bl2_platform_setup(void)
@@ -326,7 +316,8 @@
#if TRANSFER_LIST
if (image_id == HW_CONFIG_ID) {
- arm_transfer_list_copy_hw_config(secure_tl, ns_tl);
+ /* Refresh the now stale checksum following loading of HW_CONFIG into the TL. */
+ transfer_list_update_checksum(secure_tl);
}
#endif /* TRANSFER_LIST */
@@ -340,5 +331,5 @@
&next_param_node->ep_info);
assert(ep != NULL);
- arm_transfer_list_populate_ep_info(next_param_node, secure_tl, ns_tl);
+ arm_transfer_list_populate_ep_info(next_param_node, secure_tl);
}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index b7941ec..e91746b 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -25,6 +25,8 @@
#include <platform_def.h>
static struct transfer_list_header *secure_tl __unused;
+static struct transfer_list_header *ns_tl __unused;
+
/*
* Placeholder variables for copying the arguments that have been passed to
* BL31 from BL2.
@@ -95,7 +97,12 @@
assert(sec_state_is_valid(type));
if (type == NON_SECURE) {
+#if TRANSFER_LIST && !RESET_TO_BL31
+ next_image_info = transfer_list_set_handoff_args(
+ ns_tl, &bl33_image_ep_info);
+#else
next_image_info = &bl33_image_ep_info;
+#endif
}
#if ENABLE_RME
else if (type == REALM) {
@@ -128,6 +135,24 @@
void __init arm_bl31_early_platform_setup(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
+#if RESET_TO_BL31
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+
+ bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ bl33_image_ep_info.args.arg0 =
+ FW_NS_HANDOFF_BASE + ARM_PRELOADED_DTB_OFFSET;
+ bl33_image_ep_info.args.arg1 =
+ TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
+ bl33_image_ep_info.args.arg3 = FW_NS_HANDOFF_BASE;
+#else
struct transfer_list_entry *te = NULL;
struct entry_point_info *ep;
@@ -160,6 +185,7 @@
}
}
}
+#endif /* RESET_TO_BL31 */
}
#else
void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config,
@@ -338,6 +364,28 @@
******************************************************************************/
void arm_bl31_platform_setup(void)
{
+ struct transfer_list_entry *te __unused;
+
+#if TRANSFER_LIST && !RESET_TO_BL31
+ /* Initialise the non-secure world tl, BL31 may modify the HW_CONFIG so defer
+ * copying it until later.
+ */
+ ns_tl = transfer_list_init((void *)FW_NS_HANDOFF_BASE,
+ PLAT_ARM_FW_HANDOFF_SIZE);
+
+ if (ns_tl == NULL) {
+ ERROR("Non-secure transfer list initialisation failed!");
+ panic();
+ }
+
+#if !RESET_TO_BL2
+ te = transfer_list_find(secure_tl, TL_TAG_FDT);
+ assert(te != NULL);
+
+ fconf_populate("HW_CONFIG", (uintptr_t)transfer_list_entry_data(te));
+#endif /* !(RESET_TO_BL2 && RESET_TO_BL31) */
+#endif /* TRANSFER_LIST */
+
/* Initialize the GIC driver, cpu and distributor interfaces */
plat_arm_gic_driver_init();
plat_arm_gic_init();
@@ -380,9 +428,26 @@
******************************************************************************/
void arm_bl31_plat_runtime_setup(void)
{
+ struct transfer_list_entry *te __unused;
/* Initialize the runtime console */
arm_console_runtime_init();
+#if TRANSFER_LIST && !RESET_TO_BL31
+ te = transfer_list_find(secure_tl, TL_TAG_FDT);
+ assert(te != NULL);
+
+ te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
+ transfer_list_entry_data(te));
+ assert(te != NULL);
+
+ /*
+ * We assume BL31 has added all TE's required by BL33 at this stage, ensure
+ * that data is visible to all observers by performing a flush operation, so
+ * they can access the updated data even if caching is not enabled.
+ */
+ flush_dcache_range((uintptr_t)ns_tl, ns_tl->size);
+#endif /* TRANSFER_LIST && !(RESET_TO_BL2 || RESET_TO_BL31) */
+
#if RECLAIM_INIT_CODE
arm_free_init_memory();
#endif
@@ -497,15 +562,5 @@
void __init bl31_plat_arch_setup(void)
{
- struct transfer_list_entry *te __unused;
-
arm_bl31_plat_arch_setup();
-
-#if TRANSFER_LIST && !RESET_TO_BL2
- te = transfer_list_find(secure_tl, TL_TAG_FDT);
- assert(te != NULL);
-
- /* Populate HW_CONFIG device tree with the mapped address */
- fconf_populate("HW_CONFIG", (uintptr_t)transfer_list_entry_data(te));
-#endif
}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index f5919ab..dff0135 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -377,30 +377,38 @@
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
else
- BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c
# Juno has its own TBBR CoT file for BL2
- ifneq (${PLAT},juno)
- BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_bl2.c
+ ifeq (${PLAT},juno)
+ BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c
endif
endif
else ifeq (${COT},dualroot)
- BL1_SOURCES += drivers/auth/dualroot/cot.c
+ BL1_SOURCES += drivers/auth/dualroot/bl1_cot.c
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
- else
- BL2_SOURCES += drivers/auth/dualroot/cot.c
endif
else ifeq (${COT},cca)
- BL1_SOURCES += drivers/auth/cca/cot.c
+ BL1_SOURCES += drivers/auth/cca/bl1_cot.c
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
- else
- BL2_SOURCES += drivers/auth/cca/cot.c
endif
else
$(error Unknown chain of trust ${COT})
endif
+ ifeq (${COT_DESC_IN_DTB},0)
+ ifeq (${COT},dualroot)
+ COTDTPATH := fdts/dualroot_cot_descriptors.dtsi
+ else ifeq (${COT},cca)
+ COTDTPATH := fdts/cca_cot_descriptors.dtsi
+ else ifeq (${COT},tbbr)
+ ifneq (${PLAT},juno)
+ COTDTPATH := fdts/tbbr_cot_descriptors.dtsi
+ endif
+ endif
+ bl2: cot-dt2c
+ endif
+
BL1_SOURCES += ${AUTH_SOURCES} \
bl1/tbbr/tbbr_img_desc.c \
plat/arm/common/arm_bl1_fwu.c \
@@ -458,3 +466,31 @@
$(error To reclaim init code xlat tables v2 must be used)
endif
endif
+
+TRANSFER_LIST_BIN := ${BUILD_PLAT}/tl.bin
+
+.PHONY: tl
+tl: ${HW_CONFIG}
+ @echo " TLC ${TRANSFER_LIST_BIN}"
+ $(Q)${PYTHON} -m tools.tlc.tlc create --fdt ${HW_CONFIG} -s ${FW_HANDOFF_SIZE} ${TRANSFER_LIST_BIN}
+ $(Q)$(eval ARM_PRELOADED_DTB_OFFSET := `tlc info --fdt-offset ${TRANSFER_LIST_BIN}`)
+
+ifeq (${TRANSFER_LIST}, 1)
+ ifeq (${RESET_TO_BL31}, 1)
+ bl31: tl
+ endif
+endif
+
+cot-dt2c:
+ifneq ($(COTDTPATH),)
+ $(info COT CONVERSION FOR ${COTDTPATH})
+ toolpath := $(shell which cot-dt2c)
+ ifeq (${toolpath},)
+ output := $(shell make -C ./${CERTCONVPATH} install)
+ $(info install output ${output})
+ toolpath := $(shell which cot-dt2c)
+ endif
+ output := $(shell ${toolpath} convert-to-c ${COTDTPATH} ${BUILD_PLAT}/bl2_cot.c)
+ $(info ${output})
+ BL2_SOURCES += ${BUILD_PLAT}/bl2_cot.c
+endif
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index 19ee1b0..5a3d27a 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -124,6 +124,7 @@
const struct plat_io_policy *policy;
policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
+ assert(policy->check != NULL);
result = policy->check(policy->image_spec);
if (result == 0) {
*image_spec = policy->image_spec;
diff --git a/plat/arm/common/arm_ni.c b/plat/arm/common/arm_ni.c
new file mode 100644
index 0000000..b3ad8b3
--- /dev/null
+++ b/plat/arm/common/arm_ni.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+#define NI_CHILD_NODE_COUNT 4
+#define NI_CHILD_POINTERS_START 8
+
+#define NI_PMU_SECURE_CTRL 0x100
+#define NI_PMU_SECURE_EVENT_OBSERVATION 0x108
+#define NI_PMU_DEBUG_ENABLE 0x110
+#define NI_COMP_NUM_SUBFEATURES 0x100
+#define NI_COMP_SUBFEATURE_TYPE_START 0x108
+#define NI_COMP_SUBFEATURE_SECURE_CTRL_START 0x308
+
+#define SECURE_OVERRIDE_DEFAULT BIT(0)
+#define SECURE_EVENT_ENABLE BIT(2)
+#define NA_EVENT_ENABLE BIT(3)
+#define PMU_ENABLE BIT(0)
+
+#define NI_NODE_MASK 0x0000ffff
+#define NI_NODE_TYPE(node_info) (node_info & NI_NODE_MASK)
+#define NI_CHILD_POINTER(i) (NI_CHILD_POINTERS_START + (i * 4))
+#define NI_COMP_SUBFEATURE_TYPE(i) (NI_COMP_SUBFEATURE_TYPE_START + (i * 8))
+#define NI_COMP_SUBFEATURE_SECURE_CTRL(i) (NI_COMP_SUBFEATURE_SECURE_CTRL_START + (i * 8))
+
+#define NI_PERIPHERAL_ID0 0xfe0
+#define NI_PIDR0_PART_MASK 0xff
+#define NI_PERIPHERAL_ID1 0xfe4
+#define NI_PIDR1_PART_MASK 0xf
+#define NI_PIDR1_PART_SHIFT 8
+
+enum ni_part {
+ NI_700 = 0x43b,
+ NI_710AE = 0x43d,
+ NI_TOWER = 0x43f,
+};
+
+enum ni_node_type {
+ NI_INVALID_NODE = 0,
+ NI_VOLTAGE_DOMAIN = 1,
+ NI_POWER_DOMAIN = 2,
+ NI_CLOCK_DOMAIN = 3,
+ NI_ASNI = 4,
+ NI_AMNI = 5,
+ NI_PMU = 6,
+ NI_HSNI = 7,
+ NI_HMNI = 8,
+ NI_PMNI = 9,
+ NI_CMNI = 14,
+ NI_CFGNI = 15
+};
+
+enum ni_subfeature_type {
+ NI_SUBFEATURE_APU = 0,
+ NI_SUBFEATURE_ADDR_MAP = 1,
+ NI_SUBFEATURE_FCU = 2,
+ NI_SUBFEATURE_IDM = 3
+};
+
+static void ni_enable_pmu(uintptr_t pmu_addr)
+{
+ mmio_setbits_32(pmu_addr + NI_PMU_DEBUG_ENABLE, PMU_ENABLE);
+}
+
+static void ni_enable_fcu_ns_access(uintptr_t comp_addr)
+{
+ uint32_t subfeature_type;
+ uint32_t subfeature_count;
+ uint32_t subfeature_secure_ctrl;
+
+ subfeature_count = mmio_read_32(comp_addr + NI_COMP_NUM_SUBFEATURES);
+ for (uint32_t i = 0U; i < subfeature_count; i++) {
+ subfeature_type =
+ NI_NODE_TYPE(mmio_read_32(comp_addr + NI_COMP_SUBFEATURE_TYPE(i)));
+ if (subfeature_type == NI_SUBFEATURE_FCU) {
+ subfeature_secure_ctrl = comp_addr + NI_COMP_SUBFEATURE_SECURE_CTRL(i);
+ mmio_setbits_32(subfeature_secure_ctrl, SECURE_OVERRIDE_DEFAULT);
+ }
+ }
+}
+
+static void ni_enable_pmu_ns_access(uintptr_t comp_addr)
+{
+ mmio_setbits_32(comp_addr + NI_PMU_SECURE_CTRL, SECURE_OVERRIDE_DEFAULT);
+ mmio_setbits_32(comp_addr + NI_PMU_SECURE_EVENT_OBSERVATION,
+ SECURE_EVENT_ENABLE | NA_EVENT_ENABLE);
+}
+
+static void ni_setup_component(uintptr_t comp_addr)
+{
+ uint32_t node_info;
+
+ node_info = mmio_read_32(comp_addr);
+
+ switch (NI_NODE_TYPE(node_info)) {
+ case NI_ASNI:
+ case NI_AMNI:
+ case NI_HSNI:
+ case NI_HMNI:
+ case NI_PMNI:
+ ni_enable_fcu_ns_access(comp_addr);
+ break;
+ case NI_PMU:
+ ni_enable_pmu_ns_access(comp_addr);
+ ni_enable_pmu(comp_addr);
+ break;
+ default:
+ return;
+ }
+}
+
+int plat_arm_ni_setup(uintptr_t global_cfg)
+{
+ uintptr_t vd_addr;
+ uintptr_t pd_addr;
+ uintptr_t cd_addr;
+ uintptr_t comp_addr;
+ uint32_t vd_count;
+ uint32_t pd_count;
+ uint32_t cd_count;
+ uint32_t comp_count;
+ uint32_t part;
+ uint32_t reg;
+
+ reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID0);
+ part = reg & NI_PIDR0_PART_MASK;
+ reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID1);
+ part |= ((reg & NI_PIDR1_PART_MASK) << NI_PIDR1_PART_SHIFT);
+
+ if (part != NI_TOWER) {
+ ERROR("0x%x is not supported\n", part);
+ return -EINVAL;
+ }
+
+ vd_count = mmio_read_32(global_cfg + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t i = 0U; i < vd_count; i++) {
+ vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i));
+ pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t j = 0U; j < pd_count; j++) {
+ pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j));
+ cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t k = 0U; k < cd_count; k++) {
+ cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k));
+ comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t l = 0U; l < comp_count; l++) {
+ comp_addr = global_cfg +
+ mmio_read_32(cd_addr + NI_CHILD_POINTER(l));
+ ni_setup_component(comp_addr);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/arm/common/arm_transfer_list.c b/plat/arm/common/arm_transfer_list.c
index d144bbb..59fb039 100644
--- a/plat/arm/common/arm_transfer_list.c
+++ b/plat/arm/common/arm_transfer_list.c
@@ -30,8 +30,7 @@
}
void arm_transfer_list_populate_ep_info(bl_mem_params_node_t *next_param_node,
- struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl)
+ struct transfer_list_header *secure_tl)
{
uint32_t next_exe_img_id;
entry_point_info_t *ep;
@@ -53,10 +52,7 @@
ep = transfer_list_entry_data(te);
- if (next_exe_img_id == BL33_IMAGE_ID) {
- ep = transfer_list_set_handoff_args(ns_tl, ep);
- assert(ep != NULL);
- } else if ((next_exe_img_id == BL32_IMAGE_ID) && SPMC_AT_EL3) {
+ if ((next_exe_img_id == BL32_IMAGE_ID) && SPMC_AT_EL3) {
/*
* Populate the BL32 image base, size and max limit in
* the entry point information, since there is no
@@ -78,19 +74,3 @@
flush_dcache_range((uintptr_t)secure_tl, secure_tl->size);
}
-
-void arm_transfer_list_copy_hw_config(struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl)
-{
- struct transfer_list_entry *te =
- transfer_list_find(secure_tl, TL_TAG_FDT);
- assert(te != NULL);
-
- /* Refresh the now stale checksum following loading of HW_CONFIG into the TL. */
- transfer_list_update_checksum(secure_tl);
-
- /* Copy the hardware configuration to the non-secure TL. */
- te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
- transfer_list_entry_data(te));
- assert(te != NULL);
-}
diff --git a/plat/aspeed/ast2700/plat_bl31_setup.c b/plat/aspeed/ast2700/plat_bl31_setup.c
index 9fec3e8..087b479 100644
--- a/plat/aspeed/ast2700/plat_bl31_setup.c
+++ b/plat/aspeed/ast2700/plat_bl31_setup.c
@@ -174,7 +174,7 @@
break;
}
} else {
- if (pll_reg.b.bypass != 0U) {
+ if (pll_reg.b.bypass == 0U) {
if (pll_idx == PLAT_CLK_MPLL) {
/* F = 25Mhz * [M / (n + 1)] / (p + 1) */
mul = (pll_reg.b.m) / ((pll_reg.b.n + 1));
diff --git a/plat/imx/imx7/common/imx7.mk b/plat/imx/imx7/common/imx7.mk
index 950d8fd..2bda3a5 100644
--- a/plat/imx/imx7/common/imx7.mk
+++ b/plat/imx/imx7/common/imx7.mk
@@ -71,7 +71,6 @@
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
-$(eval $(call MAKE_LIB_DIRS))
$(BUILD_PLAT)/bl2/imx7_rotpk.o: $(ROTPK_HASH)
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index 40554c3..f0cdb3e 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -127,7 +127,6 @@
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
-$(eval $(call MAKE_LIB_DIRS))
$(BUILD_PLAT)/bl2/imx8mm_rotpk.o: $(ROTPK_HASH)
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index 5f4ddee..5df598c 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -124,7 +124,6 @@
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
-$(eval $(call MAKE_LIB_DIRS))
$(BUILD_PLAT)/bl2/imx8mp_rotpk.o: $(ROTPK_HASH)
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 18f5430..e8f892d 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -167,10 +167,9 @@
$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
$(q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
-$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL)
+$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) | $(BUILD_PLAT)/$(BUILD_UART)/ $$(@D)/
$(s)echo
$(s)echo "Building uart images"
- $(q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART)
$(q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin
$(q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE)
$(q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS)
diff --git a/plat/mediatek/build_helpers/mtk_build_helpers.mk b/plat/mediatek/build_helpers/mtk_build_helpers.mk
index a497049..0cb2014 100644
--- a/plat/mediatek/build_helpers/mtk_build_helpers.mk
+++ b/plat/mediatek/build_helpers/mtk_build_helpers.mk
@@ -71,15 +71,6 @@
$(eval SOURCES := $(2))
$(eval OBJS_TEMP := $(addprefix $(BUILD_DIR)/$(MODULE)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
$(eval MODULE_OBJS += $(OBJS_TEMP))
- # We use sort only to get a list of unique object directory names.
- # ordering is not relevant but sort removes duplicates.
- $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS_TEMP} ${LINKERFILE})))
- # The $(dir ) function leaves a trailing / on the directory names
- # Rip off the / to match directory names with make rule targets.
- $(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS)))
-
-$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-${3}_dirs: | ${OBJ_DIRS}
$(eval $(call MAKE_OBJS,$(BUILD_DIR)/$(MODULE),$(SOURCES),${3}))
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index 5309d98..4ff9888 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -142,7 +142,7 @@
val = read_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_SP_EL0));
write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X2), (val));
- val = read_ctx_reg((el1state_ctx), (uint32_t)(CTX_SP_EL1));
+ val = read_el1_ctx_common(el1state_ctx, sp_el1);
write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X3), (val));
return 0;
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index 83d815a..8232883 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -356,10 +356,10 @@
* will re-init this info from non-secure software when the
* core come online.
*/
- actlr_elx = read_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1));
+ actlr_elx = read_el1_ctx_common((get_el1_sysregs_ctx(ctx)), actlr_el1);
actlr_elx &= ~DENVER_CPU_PMSTATE_MASK;
actlr_elx |= DENVER_CPU_PMSTATE_C1;
- write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+ write_el1_ctx_common((get_el1_sysregs_ctx(ctx)), actlr_el1, actlr_elx);
/*
* Check if we are exiting from deep sleep and restore SE
diff --git a/plat/nxp/soc-lx2160a/ddr_fip.mk b/plat/nxp/soc-lx2160a/ddr_fip.mk
index e717cbc..c303ced 100644
--- a/plat/nxp/soc-lx2160a/ddr_fip.mk
+++ b/plat/nxp/soc-lx2160a/ddr_fip.mk
@@ -38,8 +38,6 @@
DDR_DMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_dmem.bin
endif
-$(shell mkdir -p '${BUILD_PLAT}')
-
ifeq (${DDR_FIP_NAME},)
ifeq (${TRUSTED_BOARD_BOOT},1)
DDR_FIP_NAME := ddr_fip_sec.bin
diff --git a/plat/nxp/soc-lx2160a/ddr_tbbr.mk b/plat/nxp/soc-lx2160a/ddr_tbbr.mk
index deb475b..836a431 100644
--- a/plat/nxp/soc-lx2160a/ddr_tbbr.mk
+++ b/plat/nxp/soc-lx2160a/ddr_tbbr.mk
@@ -39,8 +39,6 @@
# Pass the non-volatile counters to the cert_create tool
$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr,DDR_))
-$(shell mkdir -p '${BUILD_PLAT}')
-
ifeq (${DDR_KEY},)
DDR_KEY=${BUILD_PLAT}/ddr.pem
endif
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index d752b6c..c96e4b9 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -357,12 +357,20 @@
case BL31_IMAGE_ID:
/*
* arg0 is a bl_params_t reserved for bl31_early_platform_setup2
- * we just need arg1 and arg3 for BL31 to update th TL from S
+ * we just need arg1 and arg3 for BL31 to update the TL from S
* to NS memory before it exits
*/
- bl_mem_params->ep_info.args.arg1 =
- TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
+#ifdef __aarch64__
+ if (GET_RW(bl_mem_params->ep_info.spsr) == MODE_RW_64) {
+ bl_mem_params->ep_info.args.arg1 =
+ TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
+ } else
+#endif
+ {
+ bl_mem_params->ep_info.args.arg1 =
+ TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+ }
+
bl_mem_params->ep_info.args.arg3 = (uintptr_t)bl2_tl;
break;
#endif
diff --git a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
index c4cd259..804ad42 100644
--- a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
+++ b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
@@ -142,10 +142,10 @@
qti_ns_ctx->elr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_ELR_EL3);
qti_ns_ctx->spsr_el1 =
- read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SPSR_EL1);
+ read_el1_ctx_common(get_el1_sysregs_ctx(ctx), spsr_el1);
qti_ns_ctx->elr_el1 =
- read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_ELR_EL1);
- qti_ns_ctx->sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SP_EL1);
+ read_el1_ctx_common(get_el1_sysregs_ctx(ctx), elr_el1);
+ qti_ns_ctx->sp_el1 = read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sp_el1);
qti_ns_ctx->x0 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0);
qti_ns_ctx->x1 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1);
diff --git a/plat/renesas/common/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h
index f1c2553..8676444 100644
--- a/plat/renesas/common/include/rcar_def.h
+++ b/plat/renesas/common/include/rcar_def.h
@@ -310,4 +310,31 @@
#define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV
#define LOSSY_ENA_DIS2 LOSSY_DISABLE
+#define RCAR_CC63_BASE 0xE6600000U
+#define CC63_TRNG_ISR_REG_ADDR 0x104U
+#define CC63_TRNG_ISR_REG_EHR_VALID BIT_32(0)
+#define CC63_TRNG_ISR_REG_AUTOCORR_ERR BIT_32(1)
+#define CC63_TRNG_ICR_REG_ADDR 0x108U
+#define CC63_TRNG_CONFIG_REG_ADDR 0x10CU
+#define CC63_TRNG_CONFIG_REG_ROSC_MAX_LENGTH 3
+#define CC63_TRNG_VALID_REG_ADDR 0x110U
+#define CC63_TRNG_VALID_REG_EHR_NOT_READY 0x0
+#define CC63_TRNG_EHR_DATA_ADDR_0_REG_ADDR 0x114U
+#define CC63_TRNG_SOURCE_ENABLE_REG_ADDR 0x12CU
+#define CC63_TRNG_SOURCE_ENABLE_REG_SET 0x1
+#define CC63_TRNG_SOURCE_ENABLE_REG_CLR 0x0
+#define CC63_TRNG_SAMPLE_CNT1_REG_ADDR 0x130U
+#define CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT 100
+#define CC63_TRNG_DEBUG_CONTROL_REG_ADDR 0x138U
+#define CC63_TRNG_DEBUG_CONTROL_REG_VNC_BYPASS BIT_32(1)
+#define CC63_TRNG_DEBUG_CONTROL_REG_AUTOCORR_BYPASS BIT_32(3)
+#define CC63_TRNG_DEBUG_CONTROL_REG_80090B \
+ (CC63_TRNG_DEBUG_CONTROL_REG_VNC_BYPASS | \
+ CC63_TRNG_DEBUG_CONTROL_REG_AUTOCORR_BYPASS)
+#define CC63_TRNG_SW_RESET_REG_ADDR 0x140U
+#define CC63_TRNG_SW_RESET_REG_SET 0x1
+#define CC63_TRNG_VERSION_REG_ADDR 0x1C0U
+#define CC63_TRNG_CLK_ENABLE_REG_ADDR 0x1C4U
+#define CC63_TRNG_CLK_ENABLE_REG_SET 0x1
+
#endif /* RCAR_DEF_H */
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index 41031d6..c548240 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -756,6 +756,69 @@
#endif
}
+static void bl2_add_kaslr_seed(void)
+{
+ uint32_t cnt, isr, prr;
+ uint64_t seed;
+ int ret, node;
+
+ /* SCEG is only available on H3/M3-W/M3-N */
+ prr = mmio_read_32(RCAR_PRR);
+ switch (prr & PRR_PRODUCT_MASK) {
+ case PRR_PRODUCT_H3:
+ case PRR_PRODUCT_M3:
+ case PRR_PRODUCT_M3N:
+ break;
+ default:
+ return;
+ }
+
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SW_RESET_REG_ADDR,
+ CC63_TRNG_SW_RESET_REG_SET);
+
+ do {
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_CLK_ENABLE_REG_ADDR,
+ CC63_TRNG_CLK_ENABLE_REG_SET);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SAMPLE_CNT1_REG_ADDR,
+ CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT);
+ cnt = mmio_read_32(RCAR_CC63_BASE + CC63_TRNG_SAMPLE_CNT1_REG_ADDR);
+ } while (cnt != CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT);
+
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_CONFIG_REG_ADDR,
+ CC63_TRNG_CONFIG_REG_ROSC_MAX_LENGTH);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_DEBUG_CONTROL_REG_ADDR,
+ CC63_TRNG_DEBUG_CONTROL_REG_80090B);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SOURCE_ENABLE_REG_ADDR,
+ CC63_TRNG_SOURCE_ENABLE_REG_SET);
+
+ do {
+ isr = mmio_read_32(RCAR_CC63_BASE + CC63_TRNG_ISR_REG_ADDR);
+ if ((isr & CC63_TRNG_ISR_REG_AUTOCORR_ERR) != 0U) {
+ panic();
+ }
+ } while ((isr & CC63_TRNG_ISR_REG_EHR_VALID) == 0U);
+
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_ICR_REG_ADDR, UINT32_MAX);
+ seed = mmio_read_64(RCAR_CC63_BASE + CC63_TRNG_EHR_DATA_ADDR_0_REG_ADDR);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SOURCE_ENABLE_REG_ADDR,
+ CC63_TRNG_SOURCE_ENABLE_REG_CLR);
+
+ node = ret = fdt_add_subnode(fdt, 0, "chosen");
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = fdt_setprop_u64(fdt, node, "kaslr-seed", seed);
+ if (ret < 0) {
+ goto err;
+ }
+
+ return;
+err:
+ NOTICE("BL2: Cannot add KASLR seed to FDT (ret=%i)\n", ret);
+ panic();
+}
+
static void bl2_add_dram_entry(uint64_t start, uint64_t size)
{
char nodename[32] = { 0 };
@@ -1215,6 +1278,9 @@
/* Print DRAM layout */
bl2_advertise_dram_size(product);
+ /* Add KASLR seed */
+ bl2_add_kaslr_seed();
+
if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
if (rcar_emmc_init() != EMMC_SUCCESS) {
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 2394dce..9d0e215 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -104,9 +104,8 @@
${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW)
${RK_PLAT_SOC}/drivers/pmu/pmu_fw.S: $(RK3399M0FW)
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},${BUILD_PLAT}))
.PHONY: $(RK3399M0FW)
-$(RK3399M0FW): | ${BUILD_M0}
+$(RK3399M0FW): | $$(@D)/
$(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0)
# Do not enable SVE
diff --git a/plat/st/common/common_rules.mk b/plat/st/common/common_rules.mk
index 8b81c7f..fba7783 100644
--- a/plat/st/common/common_rules.mk
+++ b/plat/st/common/common_rules.mk
@@ -41,7 +41,7 @@
fi
# Create DTB file for BL2
-${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | $$(@D)/
$(q)echo '#include "$(patsubst fdts/%,%,$<)"' > $@
$(q)echo '#include "${BL2_DTSI}"' >> $@
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index a1f44e8..138f16c 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -255,11 +255,11 @@
ifeq ($(AARCH32_SP),sp_min)
# Create DTB file for BL32
-${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | $$(@D)/
$(q)echo '#include "$(patsubst fdts/%,%,$<)"' > $@
$(q)echo '#include "${BL32_DTSI}"' >> $@
-${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts | $$(@D)/
endif
include plat/st/common/common_rules.mk
diff --git a/plat/xilinx/common/include/pm_api_sys.h b/plat/xilinx/common/include/pm_api_sys.h
index ffee805..029bb43 100644
--- a/plat/xilinx/common/include/pm_api_sys.h
+++ b/plat/xilinx/common/include/pm_api_sys.h
@@ -64,6 +64,7 @@
uint32_t wake, uint32_t enable,
uint32_t flag);
enum pm_ret_status pm_get_chipid(uint32_t *value);
+enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload);
/*
* Assigning of argument values into array elements.
@@ -97,4 +98,9 @@
PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4)); \
}
+#define PM_PACK_PAYLOAD7(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { \
+ pl[6] = (uint32_t)(arg6); \
+ PM_PACK_PAYLOAD6(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4), (arg5)); \
+}
+
#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/common/include/pm_common.h b/plat/xilinx/common/include/pm_common.h
index c0308ab..c38cdef 100644
--- a/plat/xilinx/common/include/pm_common.h
+++ b/plat/xilinx/common/include/pm_common.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,13 +18,15 @@
#if IPI_CRC_CHECK
#define PAYLOAD_ARG_CNT 8U
+#define RET_PAYLOAD_ARG_CNT 7U
#define IPI_W0_TO_W6_SIZE 28U
#define PAYLOAD_CRC_POS 7U
#define CRC_INIT_VALUE 0x4F4EU
#define CRC_ORDER 16U
#define CRC_POLYNOM 0x8005U
#else
-#define PAYLOAD_ARG_CNT 6U
+#define PAYLOAD_ARG_CNT 7U
+#define RET_PAYLOAD_ARG_CNT 6U
#endif
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
diff --git a/plat/xilinx/common/include/pm_defs.h b/plat/xilinx/common/include/pm_defs.h
index 055fa3d..9920611 100644
--- a/plat/xilinx/common/include/pm_defs.h
+++ b/plat/xilinx/common/include/pm_defs.h
@@ -35,6 +35,7 @@
(uint32_t)XPM_NODESUBCL_DEV_PERIPH, \
(uint32_t)XPM_NODETYPE_DEV_PERIPH, (IDX))
+#define TF_A_FEATURE_CHECK 0xa00U
#define PM_GET_CALLBACK_DATA 0xa01U
#define PM_GET_TRUSTZONE_VERSION 0xa03U
#define TF_A_PM_REGISTER_SGI 0xa04U
@@ -95,6 +96,8 @@
IOCTL_GET_LAST_RESET_REASON = 23,
/* AI engine NPI ISR clear */
IOCTL_AIE_ISR_CLEAR = 24,
+ IOCTL_UFS_TXRX_CFGRDY_GET = 40,
+ IOCTL_UFS_SRAM_CSR_SEL = 41,
};
/**
diff --git a/plat/xilinx/common/include/pm_svc_main.h b/plat/xilinx/common/include/pm_svc_main.h
index 67fbeae..000f198 100644
--- a/plat/xilinx/common/include/pm_svc_main.h
+++ b/plat/xilinx/common/include/pm_svc_main.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,8 @@
extern bool pwrdwn_req_received;
+#define PASS_THROUGH_FW_CMD_ID U(0xfff)
+
/******************************************************************************/
/**
* SECURE_REDUNDANT_CALL() - Adds redundancy to the function call. This is to
diff --git a/plat/xilinx/common/pm_service/pm_api_sys.c b/plat/xilinx/common/pm_service/pm_api_sys.c
index 0a6e810..e9c5f13 100644
--- a/plat/xilinx/common/pm_service/pm_api_sys.c
+++ b/plat/xilinx/common/pm_service/pm_api_sys.c
@@ -122,7 +122,7 @@
}
PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
- return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
+ return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, RET_PAYLOAD_ARG_CNT);
}
/**
@@ -364,6 +364,37 @@
}
/**
+ * eemi_feature_check() - Returns the supported API version if supported.
+ * @api_id: API ID to check.
+ * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of
+ * words Returned supported API version
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload)
+{
+ enum pm_ret_status ret;
+
+ /* Return version of API which are implemented in TF-A only */
+ switch (api_id) {
+ case PM_GET_CALLBACK_DATA:
+ case PM_GET_TRUSTZONE_VERSION:
+ ret_payload[0] = PM_API_VERSION_2;
+ ret = PM_RET_SUCCESS;
+ break;
+ case TF_A_PM_REGISTER_SGI:
+ case TF_A_FEATURE_CHECK:
+ ret_payload[0] = PM_API_BASE_VERSION;
+ ret = PM_RET_SUCCESS;
+ break;
+ default:
+ ret = PM_RET_ERROR_NO_FEATURE;
+ }
+
+ return ret;
+}
+
+/**
* pm_feature_check() - Returns the supported API version if supported.
* @api_id: API ID to check.
* @flag: 0 - Call from secure source.
@@ -406,7 +437,7 @@
PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
PM_FEATURE_CHECK, api_id);
- return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
+ return pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT);
}
/**
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 56567dd..205877c 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -164,15 +164,10 @@
*
*/
static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
- uint32_t *value, size_t count)
+ uint32_t value[PAYLOAD_ARG_CNT])
{
size_t i;
enum pm_ret_status ret;
-#if IPI_CRC_CHECK
- uint32_t *payload_ptr = value;
- size_t j;
- uint32_t response_payload[PAYLOAD_ARG_CNT];
-#endif
uintptr_t buffer_base = proc->ipi->buffer_base +
IPI_BUFFER_TARGET_REMOTE_OFFSET +
IPI_BUFFER_RESP_OFFSET;
@@ -184,27 +179,21 @@
* buf-2: unused
* buf-3: unused
*/
- for (i = 1; i <= count; i++) {
- *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
- value++;
+ for (i = 0; i < PAYLOAD_ARG_CNT; i++) {
+ value[i] = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
}
- ret = mmio_read_32(buffer_base);
+ ret = value[0];
#if IPI_CRC_CHECK
- for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
- response_payload[j] = mmio_read_32(buffer_base +
- (j * PAYLOAD_ARG_SIZE));
- }
-
- if (response_payload[PAYLOAD_CRC_POS] !=
- calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
+ if (value[PAYLOAD_CRC_POS] !=
+ calculate_crc(value, IPI_W0_TO_W6_SIZE)) {
NOTICE("ERROR in CRC response payload value:0x%x\n",
- response_payload[PAYLOAD_CRC_POS]);
+ value[PAYLOAD_CRC_POS]);
ret = PM_RET_ERROR_INVALID_CRC;
/* Payload data is invalid as CRC validation failed
* Clear the payload to avoid leakage of data to upper layers
*/
- memset(payload_ptr, 0, count);
+ memset(value, 0, PAYLOAD_ARG_CNT);
}
#endif
@@ -240,7 +229,7 @@
count = IPI_BUFFER_MAX_WORDS;
}
- for (i = 0; i <= count; i++) {
+ for (i = 0; i < count; i++) {
*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
value++;
}
@@ -282,6 +271,7 @@
uint32_t *value, size_t count)
{
enum pm_ret_status ret;
+ uint32_t i, ret_payload[PAYLOAD_ARG_CNT] = {0U};
pm_ipi_lock_get();
@@ -290,7 +280,12 @@
goto unlock;
}
+ ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, ret_payload));
+
- ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
+ for (i = 1U; i <= count; i++) {
+ *value = ret_payload[i];
+ value++;
+ }
unlock:
pm_ipi_lock_release();
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index 7ac0ac1..b431a6c 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -36,6 +36,32 @@
#define EVENT_CPU_PWRDWN (4U)
#define MBOX_SGI_SHARED_IPI (7U)
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ */
+#define upper_32_bits(n) ((uint32_t)((n) >> 32U))
+
+/**
+ * lower_32_bits - return bits 0-31 of a number
+ * @n: the number we're accessing
+ */
+#define lower_32_bits(n) ((uint32_t)((n) & 0xffffffffU))
+
+/**
+ * EXTRACT_SMC_ARGS - extracts 32-bit payloads from 64-bit SMC arguments
+ * @pm_arg: array of 32-bit payloads
+ * @x: array of 64-bit SMC arguments
+ */
+#define EXTRACT_ARGS(pm_arg, x) \
+ for (uint32_t i = 0U; i < (PAYLOAD_ARG_CNT - 1U); i++) { \
+ if ((i % 2U) != 0U) { \
+ pm_arg[i] = lower_32_bits(x[(i / 2U) + 1U]); \
+ } else { \
+ pm_arg[i] = upper_32_bits(x[i / 2U]); \
+ } \
+ }
+
/* 1 sec of wait timeout for secondary core down */
#define PWRDWN_WAIT_TIMEOUT (1000U)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
@@ -278,7 +304,7 @@
case (uint32_t)PM_FEATURE_CHECK:
{
- uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t result[RET_PAYLOAD_ARG_CNT] = {0U};
ret = pm_feature_check(pm_arg[0], result, security_flag);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
@@ -367,6 +393,15 @@
{
switch (api_id) {
+ case TF_A_FEATURE_CHECK:
+ {
+ enum pm_ret_status ret;
+ uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+
+ ret = eemi_feature_check(pm_arg[0], result);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U));
+ }
+
case TF_A_PM_REGISTER_SGI:
{
int32_t ret;
@@ -424,7 +459,7 @@
void *handle, uint32_t security_flag)
{
enum pm_ret_status ret;
- uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+ uint32_t buf[RET_PAYLOAD_ARG_CNT] = {0};
ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4],
@@ -449,6 +484,45 @@
}
/**
+ * eemi_api_handler() - Prepare EEMI payload and perform IPI transaction.
+ * @api_id: identifier for the API being called.
+ * @pm_arg: pointer to the argument data for the API call.
+ * @handle: Pointer to caller's context structure.
+ * @security_flag: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * EEMI - Embedded Energy Management Interface is AMD-Xilinx proprietary
+ * protocol to allow communication between power management controller and
+ * different processing clusters.
+ *
+ * This handler prepares EEMI protocol payload received from kernel and performs
+ * IPI transaction.
+ *
+ * Return: If EEMI API found then, uintptr_t type address, else 0
+ */
+static uintptr_t eemi_api_handler(uint32_t api_id, const uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+ uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+ uint32_t payload[PAYLOAD_ARG_CNT] = {0};
+ uint32_t module_id;
+
+ module_id = (api_id & MODULE_ID_MASK) >> 8U;
+
+ PM_PACK_PAYLOAD7(payload, module_id, security_flag, api_id,
+ pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
+ pm_arg[4], pm_arg[5]);
+
+ ret = pm_ipi_send_sync(primary_proc, payload, (uint32_t *)buf,
+ PAYLOAD_ARG_CNT);
+
+ SMC_RET4(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
+ (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U),
+ (uint64_t)buf[3] | ((uint64_t)buf[4] << 32U),
+ (uint64_t)buf[5]);
+}
+
+/**
* pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
* @smc_fid: Function Identifier.
* @x1: SMC64 Arguments from kernel.
@@ -477,6 +551,7 @@
uint32_t security_flag = NON_SECURE_FLAG;
uint32_t api_id;
bool status = false, status_tmp = false;
+ uint64_t x[4] = {x1, x2, x3, x4};
/* Handle case where PM wasn't initialized properly */
if (pm_up == false) {
@@ -494,6 +569,14 @@
security_flag = SECURE_FLAG;
}
+ if ((smc_fid & FUNCID_NUM_MASK) == PASS_THROUGH_FW_CMD_ID) {
+ api_id = lower_32_bits(x[0]);
+
+ EXTRACT_ARGS(pm_arg, x);
+
+ return eemi_api_handler(api_id, pm_arg, handle, security_flag);
+ }
+
pm_arg[0] = (uint32_t)x1;
pm_arg[1] = (uint32_t)(x1 >> 32U);
pm_arg[2] = (uint32_t)x2;
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
index 772477f..9e8134a 100644
--- a/plat/xilinx/versal/aarch64/versal_common.c
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -1,12 +1,11 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
-#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -18,7 +17,7 @@
#include <versal_def.h>
uint32_t platform_id, platform_version;
-uint32_t cpu_clock = VERSAL_CPU_CLOCK;
+uint32_t cpu_clock;
/*
* Table of regions to map using the MMU.
@@ -39,19 +38,10 @@
return plat_versal_mmap;
}
-static void versal_print_platform_name(void)
-{
- NOTICE("TF-A running on %s\n", PLATFORM_NAME);
-}
-
void versal_config_setup(void)
{
/* Configure IPI data for versal */
versal_ipi_config_table_init();
-
- versal_print_platform_name();
-
- generic_delay_timer_init();
}
void board_detection(void)
@@ -70,7 +60,50 @@
platform_version = FIELD_GET(PLATFORM_VERSION_MASK, plat_info[1]);
}
+const char *board_name_decode(void)
+{
+ const char *platform;
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ platform = "IPP";
+ break;
+ case VERSAL_EMU:
+ platform = "EMU";
+ break;
+ case VERSAL_QEMU:
+ platform = "QEMU";
+ break;
+ case VERSAL_SILICON:
+ platform = "SILICON";
+ break;
+ default:
+ platform = "unknown";
+ }
+
+ return platform;
+}
+
uint32_t get_uart_clk(void)
{
- return UART_CLOCK;
+ uint32_t uart_clock;
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ uart_clock = 25000000;
+ break;
+ case VERSAL_EMU:
+ uart_clock = 212000;
+ break;
+ case VERSAL_QEMU:
+ uart_clock = 25000000;
+ break;
+ case VERSAL_SILICON:
+ uart_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+
+ return uart_clock;
}
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 594784f..0e4ec1c 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <bl31/bl31.h>
#include <common/bl_common.h>
#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -73,22 +74,41 @@
enum pm_ret_status ret_status;
uint64_t addr[HANDOFF_PARAMS_MAX_SIZE];
- set_cnt_freq();
-
- setup_console();
-
- /* Initialize the platform config for future decision making */
- versal_config_setup();
-
- /* Get platform related information */
- board_detection();
-
/*
* Do initial security configuration to allow DRAM/device access. On
* Base VERSAL only DRAM security is programmable (via TrustZone), but
* other platforms might have more programmable security devices
* present.
*/
+ versal_config_setup();
+
+ /* Initialize the platform config for future decision making */
+ board_detection();
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ cpu_clock = 2720000;
+ break;
+ case VERSAL_EMU:
+ cpu_clock = 212000;
+ break;
+ case VERSAL_QEMU:
+ /* Random values now */
+ cpu_clock = 2720000;
+ break;
+ case VERSAL_SILICON:
+ cpu_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+ set_cnt_freq();
+
+ generic_delay_timer_init();
+
+ setup_console();
+
+ NOTICE("TF-A running on %s %d\n", board_name_decode(), platform_version);
/* Populate common information for BL32 and BL33 */
SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h
index 932c6de..4b2b6cf 100644
--- a/plat/xilinx/versal/include/plat_private.h
+++ b/plat/xilinx/versal/include/plat_private.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,8 @@
extern uint32_t cpu_clock, platform_id, platform_version;
void board_detection(void);
+const char *board_name_decode(void);
+
void plat_versal_gic_driver_init(void);
void plat_versal_gic_init(void);
void plat_versal_gic_cpuif_enable(void);
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index f21d409..b7691ad 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,13 +25,11 @@
#define CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE)
-/* List all supported platforms */
-#define VERSAL_PLATFORM_ID_versal_virt 1
-#define VERSAL_PLATFORM_ID_spp_itr6 2
-#define VERSAL_PLATFORM_ID_emu_itr6 3
-#define VERSAL_PLATFORM_ID_silicon 4
-
-#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM)
+/* List of platforms */
+#define VERSAL_SILICON U(0)
+#define VERSAL_SPP U(1)
+#define VERSAL_EMU U(2)
+#define VERSAL_QEMU U(3)
/* Firmware Image Package */
#define VERSAL_PRIMARY_CPU 0
@@ -75,27 +73,7 @@
/*******************************************************************************
* Platform related constants
******************************************************************************/
-#if VERSAL_PLATFORM_IS(versal_virt)
-# define PLATFORM_NAME "Versal Virt"
-# define UART_CLOCK 25000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 2720000
-#elif VERSAL_PLATFORM_IS(silicon)
-# define PLATFORM_NAME "Versal Silicon"
-# define UART_CLOCK 100000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 100000000
-#elif VERSAL_PLATFORM_IS(spp_itr6)
-# define PLATFORM_NAME "SPP ITR6"
-# define UART_CLOCK 25000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 2720000
-#elif VERSAL_PLATFORM_IS(emu_itr6)
-# define PLATFORM_NAME "EMU ITR6"
-# define UART_CLOCK 212000
-# define UART_BAUDRATE 9600
-# define VERSAL_CPU_CLOCK 212000
-#endif
+#define UART_BAUDRATE 115200
/* Access control register defines */
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 4cf1ed1..74c5bf3 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -197,7 +197,7 @@
*/
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index 2f07996..6cc28e1 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -1,5 +1,5 @@
# Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
-# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -44,8 +44,9 @@
$(eval $(call add_define,IPI_CRC_CHECK))
endif
-VERSAL_PLATFORM ?= silicon
-$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM}))
+ifdef VERSAL_PLATFORM
+ $(warning "VERSAL_PLATFORM has been deprecated")
+endif
ifdef XILINX_OF_BOARD_DTB_ADDR
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
index 4441d3e..3c0bd63 100644
--- a/plat/xilinx/versal/sip_svc_setup.c
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,7 +22,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR U(0)
-#define SIP_SVC_VERSION_MINOR U(1)
+#define SIP_SVC_VERSION_MINOR U(2)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index e5a5235..fb2005d 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -59,7 +59,7 @@
*/
static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
diff --git a/plat/xilinx/versal_net/sip_svc_setup.c b/plat/xilinx/versal_net/sip_svc_setup.c
index 80d5a53..c974810 100644
--- a/plat/xilinx/versal_net/sip_svc_setup.c
+++ b/plat/xilinx/versal_net/sip_svc_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,7 +25,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR (0U)
-#define SIP_SVC_VERSION_MINOR (1U)
+#define SIP_SVC_VERSION_MINOR (2U)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
index 3d546b3..66f011a 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
@@ -919,7 +919,7 @@
enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
uint32_t *bit_mask, uint8_t len)
{
- uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret_payload[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t status;
/* Get API version implemented in TF-A */
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
index 5a6a9f8..bf17ea4 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
@@ -285,7 +285,7 @@
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t pm_arg[5];
- uint32_t result[PAYLOAD_ARG_CNT] = {0};
+ uint32_t result[RET_PAYLOAD_ARG_CNT] = {0};
uint32_t api_id;
/* Handle case where PM wasn't initialized properly */
@@ -566,7 +566,7 @@
PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4]);
ret = pm_ipi_send_sync(primary_proc, payload, result,
- PAYLOAD_ARG_CNT);
+ RET_PAYLOAD_ARG_CNT);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
(uint64_t)result[1] | ((uint64_t)result[2] << 32U));
}
diff --git a/poetry.lock b/poetry.lock
index 5119003..b465f48 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "alabaster"
@@ -13,57 +13,58 @@
[[package]]
name = "anytree"
-version = "2.8.0"
-description = "Powerful and Lightweight Python Tree Data Structure.."
+version = "2.12.1"
+description = "Powerful and Lightweight Python Tree Data Structure with various plugins"
optional = false
-python-versions = "*"
+python-versions = ">=3.7.2,<4"
files = [
- {file = "anytree-2.8.0-py2.py3-none-any.whl", hash = "sha256:14c55ac77492b11532395049a03b773d14c7e30b22aa012e337b1e983de31521"},
- {file = "anytree-2.8.0.tar.gz", hash = "sha256:3f0f93f355a91bc3e6245319bf4c1d50e3416cc7a35cc1133c1ff38306bbccab"},
+ {file = "anytree-2.12.1-py3-none-any.whl", hash = "sha256:5ea9e61caf96db1e5b3d0a914378d2cd83c269dfce1fb8242ce96589fa3382f0"},
+ {file = "anytree-2.12.1.tar.gz", hash = "sha256:244def434ccf31b668ed282954e5d315b4e066c4940b94aff4a7962d85947830"},
]
[package.dependencies]
-six = ">=1.9.0"
-
-[package.extras]
-dev = ["check-manifest"]
-test = ["coverage"]
+six = "*"
[[package]]
name = "babel"
-version = "2.12.1"
+version = "2.15.0"
description = "Internationalization utilities"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
- {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
+ {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"},
+ {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"},
]
[package.dependencies]
pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
+
[[package]]
name = "build"
-version = "0.10.0"
+version = "1.2.1"
description = "A simple, correct Python build frontend"
optional = false
-python-versions = ">= 3.7"
+python-versions = ">=3.8"
files = [
- {file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"},
- {file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"},
+ {file = "build-1.2.1-py3-none-any.whl", hash = "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"},
+ {file = "build-1.2.1.tar.gz", hash = "sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d"},
]
[package.dependencies]
colorama = {version = "*", markers = "os_name == \"nt\""}
-packaging = ">=19.0"
+importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""}
+packaging = ">=19.1"
pyproject_hooks = "*"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[package.extras]
-docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"]
-test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"]
-typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"]
+docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
+test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
+typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
+uv = ["uv (>=0.1.18)"]
virtualenv = ["virtualenv (>=20.0.35)"]
[[package]]
@@ -79,97 +80,112 @@
[[package]]
name = "charset-normalizer"
-version = "3.1.0"
+version = "3.3.2"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
- {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
+ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.7"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
files = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
[package.dependencies]
@@ -187,6 +203,20 @@
]
[[package]]
+name = "commonmark"
+version = "0.9.1"
+description = "Python parser for the CommonMark Markdown spec"
+optional = false
+python-versions = "*"
+files = [
+ {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
+ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
+]
+
+[package.extras]
+test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
+
+[[package]]
name = "docutils"
version = "0.18.1"
description = "Docutils -- Python Documentation Utilities"
@@ -221,22 +251,22 @@
[[package]]
name = "importlib-metadata"
-version = "6.6.0"
+version = "8.2.0"
description = "Read metadata from Python packages"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
- {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
+ {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"},
+ {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"},
]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
-testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
[[package]]
name = "jinja2"
@@ -281,61 +311,71 @@
[[package]]
name = "markupsafe"
-version = "2.1.2"
+version = "2.1.5"
description = "Safely add untrusted strings to HTML/XML markup."
optional = false
python-versions = ">=3.7"
files = [
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
- {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
+ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
]
[[package]]
@@ -396,35 +436,35 @@
[[package]]
name = "packaging"
-version = "23.1"
+version = "24.1"
description = "Core utilities for Python packages"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
- {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
+ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
]
[[package]]
name = "pip"
-version = "23.3"
+version = "24.2"
description = "The PyPA recommended tool for installing Python packages."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pip-23.3-py3-none-any.whl", hash = "sha256:bc38bb52bc286514f8f7cb3a1ba5ed100b76aaef29b521d48574329331c5ae7b"},
- {file = "pip-23.3.tar.gz", hash = "sha256:bb7d4f69f488432e4e96394612f43ab43dd478d073ef7422604a570f7157561e"},
+ {file = "pip-24.2-py3-none-any.whl", hash = "sha256:2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2"},
+ {file = "pip-24.2.tar.gz", hash = "sha256:5b5e490b5e9cb275c879595064adce9ebd31b854e3e803740b72f9ccf34a45b8"},
]
[[package]]
name = "pip-tools"
-version = "6.13.0"
+version = "6.14.0"
description = "pip-tools keeps your pinned dependencies fresh."
optional = false
python-versions = ">=3.7"
files = [
- {file = "pip-tools-6.13.0.tar.gz", hash = "sha256:61d46bd2eb8016ed4a924e196e6e5b0a268cd3babd79e593048720db23522bb1"},
- {file = "pip_tools-6.13.0-py3-none-any.whl", hash = "sha256:50943f151d87e752abddec8158622c34ad7f292e193836e90e30d87da60b19d9"},
+ {file = "pip-tools-6.14.0.tar.gz", hash = "sha256:06366be0e08d86b416407333e998b4d305d5bd925151b08942ed149380ba3e47"},
+ {file = "pip_tools-6.14.0-py3-none-any.whl", hash = "sha256:c5ad042cd27c0b343b10db1db7f77a7d087beafbec59ae6df1bba4d3368dfe8c"},
]
[package.dependencies]
@@ -432,28 +472,29 @@
click = ">=8"
pip = ">=22.2"
setuptools = "*"
+tomli = {version = "*", markers = "python_version < \"3.11\""}
wheel = "*"
[package.extras]
-coverage = ["pytest-cov"]
-testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist"]
+coverage = ["covdefaults", "pytest-cov"]
+testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist", "tomli-w"]
[[package]]
name = "prettytable"
-version = "3.7.0"
+version = "3.10.2"
description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "prettytable-3.7.0-py3-none-any.whl", hash = "sha256:f4aaf2ed6e6062a82fd2e6e5289bbbe705ec2788fe401a3a1f62a1cea55526d2"},
- {file = "prettytable-3.7.0.tar.gz", hash = "sha256:ef8334ee40b7ec721651fc4d37ecc7bb2ef55fde5098d994438f0dfdaa385c0c"},
+ {file = "prettytable-3.10.2-py3-none-any.whl", hash = "sha256:1cbfdeb4bcc73976a778a0fb33cb6d752e75396f16574dcb3e2d6332fd93c76a"},
+ {file = "prettytable-3.10.2.tar.gz", hash = "sha256:29ec6c34260191d42cd4928c28d56adec360ac2b1208a26c7e4f14b90cc8bc84"},
]
[package.dependencies]
wcwidth = "*"
[package.extras]
-tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
+tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"]
[[package]]
name = "pyelftools"
@@ -468,101 +509,109 @@
[[package]]
name = "pygments"
-version = "2.15.1"
+version = "2.18.0"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
- {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[package.extras]
-plugins = ["importlib-metadata"]
+windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyproject-hooks"
-version = "1.0.0"
+version = "1.1.0"
description = "Wrappers to call pyproject.toml-based build backend hooks."
optional = false
python-versions = ">=3.7"
files = [
- {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"},
- {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"},
+ {file = "pyproject_hooks-1.1.0-py3-none-any.whl", hash = "sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2"},
+ {file = "pyproject_hooks-1.1.0.tar.gz", hash = "sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965"},
]
-[package.dependencies]
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-
[[package]]
name = "pytz"
-version = "2023.3"
+version = "2024.1"
description = "World timezone definitions, modern and historical"
optional = false
python-versions = "*"
files = [
- {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
- {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
+ {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
+ {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
]
[[package]]
name = "pyyaml"
-version = "6.0"
+version = "6.0.1"
description = "YAML parser and emitter for Python"
optional = false
python-versions = ">=3.6"
files = [
- {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
- {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
- {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
- {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
- {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
- {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
- {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
- {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
- {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
- {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
- {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
- {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
- {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
- {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
- {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
- {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
- {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
- {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
- {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
- {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
- {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
- {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
+ {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
+ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
[[package]]
name = "requests"
-version = "2.32.2"
+version = "2.32.3"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.8"
files = [
- {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"},
- {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"},
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
@@ -576,20 +625,50 @@
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
+name = "rich"
+version = "10.16.2"
+description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
+optional = false
+python-versions = ">=3.6.2,<4.0.0"
+files = [
+ {file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"},
+ {file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.0,<0.5.0"
+commonmark = ">=0.9.0,<0.10.0"
+pygments = ">=2.6.0,<3.0.0"
+
+[package.extras]
+jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
+
+[[package]]
name = "setuptools"
-version = "67.7.2"
+version = "72.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
- {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
+ {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
+ {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
-testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+description = "Tool to Detect Surrounding Shell"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
+ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
+]
[[package]]
name = "six"
@@ -650,19 +729,19 @@
[[package]]
name = "sphinx-rtd-theme"
-version = "1.2.0"
+version = "1.3.0"
description = "Read the Docs theme for Sphinx"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
- {file = "sphinx_rtd_theme-1.2.0-py2.py3-none-any.whl", hash = "sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2"},
- {file = "sphinx_rtd_theme-1.2.0.tar.gz", hash = "sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8"},
+ {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"},
+ {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"},
]
[package.dependencies]
docutils = "<0.19"
-sphinx = ">=1.6,<7"
-sphinxcontrib-jquery = {version = ">=2.0.0,<3.0.0 || >3.0.0", markers = "python_version > \"3\""}
+sphinx = ">=1.6,<8"
+sphinxcontrib-jquery = ">=4,<5"
[package.extras]
dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
@@ -804,6 +883,25 @@
cairosvg = ["cairosvg (>=1.0)"]
[[package]]
+name = "tlc"
+version = "0.9.0"
+description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
+optional = false
+python-versions = "^3.8"
+files = []
+develop = false
+
+[package.dependencies]
+click = "^8.1.7"
+pyyaml = "^6.0.1"
+rich = "^10.14.0"
+typer = {version = "^0.4.0", extras = ["all"]}
+
+[package.source]
+type = "directory"
+url = "tools/tlc"
+
+[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
@@ -815,14 +913,36 @@
]
[[package]]
+name = "typer"
+version = "0.4.2"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.4.2-py3-none-any.whl", hash = "sha256:023bae00d1baf358a6cc7cea45851639360bb716de687b42b0a4641cd99173f1"},
+ {file = "typer-0.4.2.tar.gz", hash = "sha256:b8261c6c0152dd73478b5ba96ba677e5d6948c715c310f7c91079f311f62ec03"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
+shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
+[[package]]
name = "typing-extensions"
-version = "4.5.0"
-description = "Backported and Experimental Type Hints for Python 3.7+"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
- {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
@@ -844,45 +964,45 @@
[[package]]
name = "wcwidth"
-version = "0.2.6"
+version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
python-versions = "*"
files = [
- {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
- {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
]
[[package]]
name = "wheel"
-version = "0.40.0"
+version = "0.43.0"
description = "A built-package format for Python"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"},
- {file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"},
+ {file = "wheel-0.43.0-py3-none-any.whl", hash = "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"},
+ {file = "wheel-0.43.0.tar.gz", hash = "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85"},
]
[package.extras]
-test = ["pytest (>=6.0.0)"]
+test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
[[package]]
name = "zipp"
-version = "3.15.0"
+version = "3.19.2"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
- {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+ {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"},
+ {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "62d9ce9ca1c9f4669c7b40724acfc93968cde31c0460d1d7515d289739dc9464"
+content-hash = "8798a2d1efd456c3b68ae464a216f015afaa1bbb653a905148bef17ab8ce278e"
diff --git a/pyproject.toml b/pyproject.toml
index 7814497..03d898e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,8 +14,12 @@
[tool.poetry.dependencies]
python = "^3.8"
+tlc = {path = "tools/tlc"}
+
+[tool.poetry.group.docs]
+optional = true
-[tool.poetry.group.doc.dependencies]
+[tool.poetry.group.docs.dependencies]
sphinx = "^5.3.0"
myst-parser = "^0.18.1"
sphinxcontrib-plantuml = "^0.24.1"
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index d6c0040..9e83848 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -552,13 +552,14 @@
if (opteed_rw == OPTEE_AARCH64) {
arg0 = (uint64_t)dt;
+ arg1 = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
arg2 = 0;
} else {
- arg2 = (uint64_t)dt;
arg0 = 0;
+ arg1 = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+ arg2 = (uint64_t)dt;
}
- arg1 = TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
+
arg3 = (uint64_t)bl31_tl;
} else {
/* Default handoff arguments */
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index 7daebcd..f2048a3 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -160,9 +160,9 @@
(void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs));
ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3);
ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3);
- ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1);
+ ctx->fiq_sp_el1 = read_el1_ctx_common(get_el1_sysregs_ctx(handle), sp_el1);
- write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp);
+ write_el1_ctx_common(get_el1_sysregs_ctx(handle), sp_el1, ctx->fiq_handler_sp);
cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr);
SMC_RET0(handle);
@@ -221,7 +221,7 @@
*/
(void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs));
ctx->fiq_handler_active = 0;
- write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1);
+ write_el1_ctx_common(get_el1_sysregs_ctx(handle), sp_el1, ctx->fiq_sp_el1);
cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr);
SMC_RET0(handle);
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 6ccb003..15b3724 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -202,19 +202,23 @@
int rc;
/* Make sure RME is supported. */
- assert(is_feat_rme_present());
+ if (is_feat_rme_present() == 0U) {
+ /* Mark the RMM boot as failed for all the CPUs */
+ rmm_boot_failed = true;
+ return -ENOTSUP;
+ }
rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM);
- if (rmm_ep_info == NULL) {
+ if ((rmm_ep_info == NULL) || (rmm_ep_info->pc == 0)) {
WARN("No RMM image provided by BL2 boot loader, Booting "
"device without RMM initialization. SMCs destined for "
"RMM will return SMC_UNK\n");
+
+ /* Mark the boot as failed for all the CPUs */
+ rmm_boot_failed = true;
return -ENOENT;
}
- /* Under no circumstances will this parameter be 0 */
- assert(rmm_ep_info->pc == RMM_BASE);
-
/* Initialise an entrypoint to set up the CPU context */
ep_attr = EP_REALM;
if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) {
@@ -239,6 +243,8 @@
rc = plat_rmmd_load_manifest(manifest);
if (rc != 0) {
ERROR("Error loading RMM Boot Manifest (%i)\n", rc);
+ /* Mark the boot as failed for all the CPUs */
+ rmm_boot_failed = true;
return rc;
}
flush_dcache_range((uintptr_t)shared_buf_base, shared_buf_size);
diff --git a/services/std_svc/spm/el3_spmc/spmc_setup.c b/services/std_svc/spm/el3_spmc/spmc_setup.c
index 609d968..e8beae1 100644
--- a/services/std_svc/spm/el3_spmc/spmc_setup.c
+++ b/services/std_svc/spm/el3_spmc/spmc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -319,24 +319,35 @@
xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
EL1_EL0_REGIME);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
mmu_cfg_params[MMU_CFG_MAIR]);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1, mmu_cfg_params[MMU_CFG_TCR]);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), tcr_el1,
mmu_cfg_params[MMU_CFG_TCR]);
+#endif /* ERRATA_SPECULATIVE_AT */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
mmu_cfg_params[MMU_CFG_TTBR0]);
}
static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
{
- u_register_t sctlr_el1;
+ u_register_t sctlr_el1_val;
/* Setup SCTLR_EL1 */
- sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+#if (ERRATA_SPECULATIVE_AT)
+ sctlr_el1_val = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
+ sctlr_el1_val = read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
- sctlr_el1 |=
+ sctlr_el1_val |=
/*SCTLR_EL1_RES1 |*/
/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
SCTLR_UCI_BIT |
@@ -357,7 +368,7 @@
/* Enable MMU. */
SCTLR_M_BIT;
- sctlr_el1 &= ~(
+ sctlr_el1_val &= ~(
/* Explicit data accesses at EL0 are little-endian. */
SCTLR_E0E_BIT |
/*
@@ -369,7 +380,13 @@
SCTLR_UMA_BIT
);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_el1_val);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, sctlr_el1_val);
+#endif /* ERRATA_SPECULATIVE_AT */
}
static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
@@ -383,10 +400,10 @@
/* Setup other system registers. */
/* Shim Exception Vector Base Address */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
SPM_SHIM_EXCEPTIONS_PTR);
#if NS_TIMER_SWITCH
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cntkctl_el1,
EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
#endif
@@ -397,7 +414,7 @@
* TTA: Enable access to trace registers.
* ZEN (v8.2): Trap SVE instructions and access to SVE registers.
*/
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
}
diff --git a/services/std_svc/spm/spm_mm/spm_mm_setup.c b/services/std_svc/spm/spm_mm/spm_mm_setup.c
index 4e65c9c..bb9c7a9 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -27,7 +27,7 @@
void spm_sp_setup(sp_context_t *sp_ctx)
{
cpu_context_t *ctx = &(sp_ctx->cpu_ctx);
-
+ u_register_t sctlr_el1_val;
/* Pointer to the MP information from the platform port. */
const spm_mm_boot_info_t *sp_boot_info =
plat_get_secure_partition_boot_info(NULL);
@@ -122,19 +122,30 @@
xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
EL1_EL0_REGIME);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
mmu_cfg_params[MMU_CFG_MAIR]);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1, mmu_cfg_params[MMU_CFG_TCR]);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), tcr_el1,
mmu_cfg_params[MMU_CFG_TCR]);
+#endif /* ERRATA_SPECULATIVE_AT */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
mmu_cfg_params[MMU_CFG_TTBR0]);
/* Setup SCTLR_EL1 */
- u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+#if (ERRATA_SPECULATIVE_AT)
+ sctlr_el1_val = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
+ sctlr_el1_val = read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
- sctlr_el1 |=
+ sctlr_el1_val |=
/*SCTLR_EL1_RES1 |*/
/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
SCTLR_UCI_BIT |
@@ -156,7 +167,7 @@
SCTLR_M_BIT
;
- sctlr_el1 &= ~(
+ sctlr_el1_val &= ~(
/* Explicit data accesses at EL0 are little-endian. */
SCTLR_E0E_BIT |
/*
@@ -168,7 +179,13 @@
SCTLR_UMA_BIT
);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_el1_val);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, sctlr_el1_val);
+#endif /* ERRATA_SPECULATIVE_AT */
/*
* Setup other system registers
@@ -176,10 +193,10 @@
*/
/* Shim Exception Vector Base Address */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
SPM_SHIM_EXCEPTIONS_PTR);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
+ write_el1_ctx_arch_timer(get_el1_sysregs_ctx(ctx), cntkctl_el1,
EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
/*
@@ -189,7 +206,7 @@
* TTA: Enable access to trace registers.
* ZEN (v8.2): Trap SVE instructions and access to SVE registers.
*/
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
/*
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index e782d09..5cfe5f9 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -66,7 +66,7 @@
#if ENABLE_RME
if (rmmd_setup() != 0) {
- ret = 1;
+ WARN("RMMD setup failed. Continuing boot.\n");
}
#endif
diff --git a/tools/cot_dt2c/Makefile b/tools/cot_dt2c/Makefile
new file mode 100644
index 0000000..ad8d9f5
--- /dev/null
+++ b/tools/cot_dt2c/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+##* Variables
+SHELL := /usr/bin/env bash
+PYTHON := python
+PYTHONPATH := `pwd`
+
+.PHONY: dist
+dist: clean
+ poetry build
+
+#* Installation
+.PHONY: dev-install
+dev-install:
+ pip3 install mypy
+ pip3 install pytest
+ pip install -r requirements.txt
+ poetry lock -n && poetry export --without-hashes > requirements.txt
+ poetry install -n
+ -poetry run mypy --install-types --non-interactive ./
+
+.PHONY: install
+install: dist
+ pip install mypy
+ pip install pytest
+ pip install -r requirements.txt
+ pip install dist/*.whl
+
+clean-test: ## remove test and coverage artifacts
+ rm -fr .tox/
+ rm -f .coverage
+ rm -fr htmlcov/
+
+clean-pyc: ## remove Python file artifacts
+ find . -name '*.pyc' -exec rm -f {} +
+ find . -name '*.pyo' -exec rm -f {} +
+ find . -name '*~' -exec rm -f {} +
+ find . -name '__pycache__' -exec rm -fr {} +
+ find . | grep -E ".pytest_cache" | xargs rm -rf
+ find . | grep -E ".mypy_cache" | xargs rm -rf
+
+
+clean-build: ## remove build artifacts
+ rm -fr build/
+ rm -fr dist/
+ rm -fr .eggs/
+ find . -name '*.egg-info' -exec rm -fr {} +
+ find . -name '*.egg' -exec rm -f {} +
+
+clean-tmp:
+ rm -rf ./tmp
+
+#* Cleaning
+.PHONY: clean clean-build clean-pyc clean-test
+clean: uninstall clean-build clean-pyc clean-test clean-tmp ## remove all build, test, coverage and Python artifacts
+
+uninstall:
+ pip uninstall -y cot-dt2c
+
+.PHONY: reinstall
+reinstall: clean install
+
+.PHONY: test
+test:
+ PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml tests/
diff --git a/tools/cot_dt2c/cot_dt2c/LICENSE b/tools/cot_dt2c/cot_dt2c/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/tools/cot_dt2c/cot_dt2c/__init__.py b/tools/cot_dt2c/cot_dt2c/__init__.py
new file mode 100644
index 0000000..621c55a
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/__init__.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+
+if sys.version_info >= (3, 8):
+ from importlib import metadata as importlib_metadata
+else:
+ import importlib_metadata
+
+
+def get_version() -> str:
+ try:
+ return importlib_metadata.version(__name__)
+ except importlib_metadata.PackageNotFoundError: # pragma: no cover
+ return "unknown"
+
+
+version: str = get_version()
diff --git a/tools/cot_dt2c/cot_dt2c/__main__.py b/tools/cot_dt2c/cot_dt2c/__main__.py
new file mode 100644
index 0000000..5aa4a92
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/__main__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+from cot_dt2c.cli import cli
+if __name__ == "__main__":
+ cli()
diff --git a/tools/cot_dt2c/cot_dt2c/cli.py b/tools/cot_dt2c/cot_dt2c/cli.py
new file mode 100644
index 0000000..d338430
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cli.py
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+from pathlib import Path
+from cot_dt2c.cot_dt2c import generateMain
+from cot_dt2c.cot_dt2c import validateMain
+from cot_dt2c.cot_dt2c import visualizeMain
+from cot_dt2c.dt_validator import dtValidatorMain
+
+import click
+
+@click.group()
+@click.version_option()
+def cli():
+ pass
+
+@cli.command()
+@click.argument("inputfile", type=click.Path(dir_okay=True))
+@click.argument("outputfile", type=click.Path(dir_okay=True))
+def convert_to_c(inputfile, outputfile):
+ generateMain(inputfile, outputfile)
+
+@cli.command()
+@click.argument("inputfile", type=click.Path(dir_okay=True))
+def validate_cot(inputfile):
+ validateMain(inputfile)
+
+@cli.command()
+@click.argument("inputfile", type=click.Path(dir_okay=True))
+def visualize_cot(inputfile):
+ visualizeMain(inputfile)
+
+@cli.command()
+@click.argument("inputfiledir", type=click.Path(dir_okay=True))
+def validate_dt(inputfiledir):
+ dtValidatorMain(inputfiledir)
diff --git a/tools/cot_dt2c/cot_dt2c/cot_dt2c.py b/tools/cot_dt2c/cot_dt2c/cot_dt2c.py
new file mode 100644
index 0000000..4056aac
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cot_dt2c.py
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+from cot_dt2c.cot_parser import COT
+
+def generateMain(input, output=None):
+ cot = COT(input, output)
+ cot.generate_c_file()
+
+def validateMain(input):
+ cot = COT(input)
+ if not cot.validate_nodes():
+ print("not a valid CoT DT file")
+
+def visualizeMain(input):
+ cot = COT(input)
+ cot.tree_visualization()
+
+if __name__=="__main__":
+ if (len(sys.argv) < 2):
+ print("usage: python3 " + sys.argv[0] + " [dtsi file path] [optional output c file path]")
+ exit()
+ if len(sys.argv) == 3:
+ generateMain(sys.argv[1], sys.argv[2])
+ if len(sys.argv) == 2:
+ validateMain(sys.argv[1])
diff --git a/tools/cot_dt2c/cot_dt2c/cot_parser.py b/tools/cot_dt2c/cot_dt2c/cot_parser.py
new file mode 100644
index 0000000..c1d53e2
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cot_parser.py
@@ -0,0 +1,804 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+import re
+from cot_dt2c.pydevicetree.source.parser import ifdef_stack
+from cot_dt2c.pydevicetree.ast import CellArray, LabelReference
+from cot_dt2c.pydevicetree import *
+from pathlib import Path
+
+def extractNumber(s):
+ for i in s:
+ if i.isdigit():
+ return (int)(i)
+
+ return -1
+
+def removeNumber(s):
+ result = ''.join([i for i in s if not i.isdigit()])
+ return result
+
+class COT:
+ def __init__(self, inputfile: str, outputfile=None):
+ with open(inputfile, 'r') as f:
+ contents = f.read()
+ pos = contents.find("cot")
+ if pos == -1:
+ print("not a valid CoT DT file")
+ exit(1)
+
+ contents = contents[pos:]
+
+ try:
+ self.tree = Devicetree.parseStr(contents)
+ except:
+ print("not a valid CoT DT file")
+ exit(1)
+
+ self.output = outputfile
+ self.input = inputfile
+ self.has_root = False
+
+ # edge cases
+ certs = self.get_all_certificates()
+ for c in certs:
+ if self.if_root(c):
+ if not c.get_fields("signing-key"):
+ c.properties.append(Property("signing-key", CellArray([LabelReference("subject_pk")])))
+
+ def print_cert_info(self, node:Node):
+ img_id = node.get_field("image-id").values[0].replace('"', "")
+ sign_key = self.get_sign_key(node)
+ nv = self.get_nv_ctr(node)
+
+ info = "<b>name:</b> {}<br><b>image-id:</b> {}<br>{}{}{}"\
+ .format(node.name, img_id, "<b>root-certificate</b><br>" if self.if_root(node) else "", \
+ "<b>signing-key:</b> " + self.extract_label(sign_key) + "<br>" if sign_key else "", \
+ "<b>nv counter:</b> " + self.extract_label(nv) + "<br>" if nv else "")
+ return info
+
+ def print_data_info(self, node:Node):
+ oid = node.get_field("oid")
+ info = "<b>name:</b> {}<br><b>oid:</b> {}<br>" \
+ .format(node.name, oid)
+
+ return info
+
+ def print_img_info(self, node:Node):
+ hash = self.extract_label(node.get_fields("hash"))
+ img_id = node.get_field("image-id").values[0].replace('"', "")
+ info = "<b>name:</b> {}<br><b>image-id:</b> {}<br><b>hash:</b> {}"\
+ .format(node.name, img_id, hash)
+
+ return info
+
+ def tree_width(self, parent_set, root):
+ ans = 1
+ stack = [root]
+
+ while stack:
+ tmp_stack = []
+ while stack:
+ cur_node = stack.pop()
+ child = parent_set[cur_node]
+ for c in child:
+ tmp_stack.append(c)
+
+ stack = tmp_stack.copy()
+ ans = max(ans, len(tmp_stack))
+
+ return ans
+
+ def resolve_lay(self, parent_set, lay, name_idx, root, bounds, break_name):
+ child = parent_set[root]
+
+ if len(child) == 0:
+ return
+
+ width = []
+ total_width = 0
+ for c in child:
+ w = self.tree_width(parent_set, c)
+ width.append(w)
+ total_width += w
+
+ allow_width = bounds[1] - bounds[0]
+ interval = allow_width / total_width
+ start = bounds[0]
+ for i, c in enumerate(child):
+ end = start + interval * width[i]
+ new_bounds = [start, end]
+ lay[name_idx[c]][0] = start + (end - start) / 2
+ if end - start < 0.28:
+ break_name.add(c)
+ start = end
+ self.resolve_lay(parent_set, lay, name_idx, c, new_bounds, break_name)
+
+ def tree_visualization(self):
+ import igraph
+ from igraph import Graph, EdgeSeq
+ import collections
+
+ cert = self.get_certificates()
+ pk = self.get_rot_keys()
+ nv = self.get_nv_counters()
+ image = self.get_images()
+
+ certs = cert.children
+ if pk:
+ pks = pk.children
+ else:
+ pks = []
+ nvs = nv.children
+ images = image.children
+
+ root_name = "CoT"
+
+ G = Graph()
+ detail = []
+ lay = []
+ name_idx = {}
+ parent_set = collections.defaultdict(list)
+
+ G.add_vertex(root_name)
+ detail.append("CoT Root")
+ name_idx[root_name] = len(lay)
+ lay.append([0,0])
+
+ G.add_vertex(cert.name)
+ G.add_edge(root_name, cert.name)
+ detail.append("All Certificates")
+ name_idx[cert.name] = len(lay)
+ lay.append([0, 1])
+ parent_set[root_name].append(cert.name)
+
+ if pk:
+ G.add_vertex(pk.name)
+ detail.append("All Public Trusted Key")
+ G.add_edge(root_name, pk.name)
+ name_idx[pk.name] = len(lay)
+ lay.append([-2.0, 1])
+ parent_set[root_name].append(pk.name)
+
+ G.add_vertex(nv.name)
+ detail.append("All NV Counters")
+ G.add_edge(root_name, nv.name)
+ name_idx[nv.name] = len(lay)
+ lay.append([2.0, 1])
+ parent_set[root_name].append(nv.name)
+
+ if pks:
+ for i, p in enumerate(pks):
+ G.add_vertex(p.name)
+ detail.append(self.print_data_info(p))
+ G.add_edge(pk.name, p.name)
+ name_idx[p.name] = len(lay)
+ parent_set[pk.name].append(p.name)
+ lay.append([0, lay[name_idx[pk.name]][1] + 1])
+
+ for c in certs:
+ G.add_vertex(c.name)
+ detail.append(self.print_cert_info(c))
+ name_idx[c.name] = len(lay)
+ if self.if_root(c):
+ G.add_edge(cert.name, c.name)
+ parent_set[cert.name].append(c.name)
+ lay.append([0, 2])
+ else:
+ parent = self.extract_label(c.get_fields("parent"))
+ G.add_edge(parent, c.name)
+ parent_set[parent].append(c.name)
+ lay.append([0, lay[name_idx[parent]][1] + 1])
+
+ for idx, i in enumerate(images):
+ G.add_vertex(i.name)
+ detail.append(self.print_img_info(i))
+ parent = self.extract_label(i.get_fields("parent"))
+ G.add_edge(parent, i.name)
+ parent_set[parent].append(i.name)
+ name_idx[i.name] = len(lay)
+ lay.append([0, lay[name_idx[parent]][1] + 1])
+
+ for i, n in enumerate(nvs):
+ G.add_vertex(n.name)
+ detail.append(self.print_data_info(n))
+ G.add_edge(nv.name, n.name)
+ name_idx[n.name] = len(lay)
+ parent_set[nv.name].append(n.name)
+ lay.append([0, lay[name_idx[nv.name]][1] + 1])
+
+ break_name = set()
+ self.resolve_lay(parent_set, lay, name_idx, root_name, [-3, 3], break_name)
+ #lay = G.layout('rt')
+
+ numVertex = len(G.get_vertex_dataframe())
+ vertices = G.get_vertex_dataframe()
+ v_label = []
+
+ for i in vertices['name']:
+ if i in break_name and len(i) > 10:
+ middle = len(i) // 2
+ v_label.append(i[:middle] + "<br>" + i[middle:])
+ else:
+ v_label.append(i)
+
+ position = {k: lay[k] for k in range(numVertex)}
+ Y = [lay[k][1] for k in range(numVertex)]
+ M = max(Y)
+
+ es = EdgeSeq(G) # sequence of edges
+ E = [e.tuple for e in G.es] # list of edges
+
+ L = len(position)
+ Xn = [position[k][0] for k in range(L)]
+ Yn = [2*M-position[k][1] for k in range(L)]
+ Xe = []
+ Ye = []
+ for edge in E:
+ Xe += [position[edge[0]][0], position[edge[1]][0], None]
+ Ye += [2*M-position[edge[0]][1], 2*M-position[edge[1]][1], None]
+
+ labels = v_label
+
+ import plotly.graph_objects as go
+ fig = go.Figure()
+ fig.add_trace(go.Scatter(x = Xe,
+ y = Ye,
+ mode = 'lines',
+ line = dict(color='rgb(210,210,210)', width=2),
+ hoverinfo = 'none'
+ ))
+ fig.add_trace(go.Scatter(x = Xn,
+ y = Yn,
+ mode = 'markers',
+ name = 'detail',
+ marker = dict(symbol = 'circle-dot',
+ size = 50,
+ color = 'rgba(135, 206, 250, 0.8)', #'#DB4551',
+ line = dict(color='MediumPurple', width=3)
+ ),
+ text=detail,
+ hoverinfo='text',
+ hovertemplate =
+ '<b>Detail</b><br>'
+ '%{text}',
+ opacity=0.8
+ ))
+
+ def make_annotations(pos, text, font_size=10, font_color='rgb(0,0,0)'):
+ L = len(pos)
+ if len(text) != L:
+ raise ValueError('The lists pos and text must have the same len')
+ annotations = []
+ for k in range(L):
+ annotations.append(
+ dict(
+ text = labels[k],
+ x = pos[k][0], y = 2*M-position[k][1],
+ xref = 'x1', yref = 'y1',
+ font = dict(color = font_color, size = font_size),
+ showarrow = False)
+ )
+ return annotations
+
+ axis = dict(showline=False, # hide axis line, grid, ticklabels and title
+ zeroline=False,
+ showgrid=False,
+ showticklabels=False,
+ )
+
+ fig.update_layout(title= 'CoT Device Tree',
+ annotations=make_annotations(position, v_label),
+ font_size=12,
+ showlegend=False,
+ xaxis=axis,
+ yaxis=axis,
+ margin=dict(l=40, r=40, b=85, t=100),
+ hovermode='closest',
+ plot_bgcolor='rgb(248,248,248)'
+ )
+
+ fig.show()
+
+ return
+
+ def if_root(self, node:Node) -> bool:
+ for p in node.properties:
+ if p.name == "root-certificate":
+ return True
+ return False
+
+ def get_sign_key(self, node:Node):
+ for p in node.properties:
+ if p.name == "signing-key":
+ return p.values
+
+ return None
+
+ def get_nv_ctr(self, node:Node):
+ for nv in node.properties:
+ if nv.name == "antirollback-counter":
+ return nv.values
+
+ return None
+
+ def extract_label(self, label) -> str:
+ if not label:
+ return label
+ return label[0].label.name
+
+ def get_auth_data(self, node:Node):
+ return node.children
+
+ def format_auth_data_val(self, node:Node, cert:Node):
+ type_desc = node.name
+ if "sp_pkg" in type_desc:
+ ptr = removeNumber(type_desc) + "_buf"
+ else:
+ ptr = type_desc + "_buf"
+ len = "(unsigned int)HASH_DER_LEN"
+ if "pk" in type_desc:
+ len = "(unsigned int)PK_DER_LEN"
+
+ # edge case
+ if not self.if_root(cert) and "key_cert" in cert.name:
+ if "content_pk" in ptr:
+ ptr = "content_pk_buf"
+
+ return type_desc, ptr, len
+
+ def get_node(self, nodes: list[Node], name: str) -> Node:
+ for i in nodes:
+ if i.name == name:
+ return i
+
+ def get_certificates(self) -> Node:
+ children = self.tree.children
+ for i in children:
+ if i.name == "cot":
+ return self.get_node(i.children, "manifests")
+
+ def get_images(self)-> Node:
+ children = self.tree.children
+ for i in children:
+ if i.name == "cot":
+ return self.get_node(i.children, "images")
+
+ def get_nv_counters(self) -> Node:
+ children = self.tree.children
+ return self.get_node(children, "non_volatile_counters")
+
+ def get_rot_keys(self) -> Node:
+ children = self.tree.children
+ return self.get_node(children, "rot_keys")
+
+ def get_all_certificates(self) -> Node:
+ cert = self.get_certificates()
+ return cert.children
+
+ def get_all_images(self) -> Node:
+ image = self.get_images()
+ return image.children
+
+ def get_all_nv_counters(self) -> Node:
+ nv = self.get_nv_counters()
+ return nv.children
+
+ def get_all_pks(self) -> Node:
+ pk = self.get_rot_keys()
+ if not pk:
+ return []
+ return pk.children
+
+ def validate_cert(self, node:Node) -> bool:
+ valid = True
+ if not node.has_field("image-id"):
+ print("{} missing mandatory attribute image-id".format(node.name))
+ valid = False
+
+ if not node.has_field("root-certificate"):
+ if not node.has_field("parent"):
+ print("{} missing mandatory attribute parent".format(node.name))
+ valid = False
+ else:
+ # check if refer to non existing parent
+ certs = self.get_all_certificates()
+ found = False
+ for c in certs:
+ if c.name == self.extract_label(node.get_fields("parent")):
+ found = True
+
+ if not found:
+ print("{} refer to non existing parent".format(node.name))
+ valid = False
+
+ else:
+ self.has_root = True
+
+ child = node.children
+ if child:
+ for c in child:
+ if not c.has_field("oid"):
+ print("{} missing mandatory attribute oid".format(c.name))
+ valid = False
+
+ return valid
+
+ def validate_img(self, node:Node) -> bool:
+ valid = True
+ if not node.has_field("image-id"):
+ print("{} missing mandatory attribute image-id".format(node.name))
+ valid = False
+
+ if not node.has_field("parent"):
+ print("{} missing mandatory attribute parent".format(node.name))
+ valid = False
+
+ if not node.has_field("hash"):
+ print("{} missing mandatory attribute hash".format(node.name))
+ valid = False
+
+ # check if refer to non existing parent
+ certs = self.get_all_certificates()
+ found = False
+ for c in certs:
+ if c.name == self.extract_label(node.get_fields("parent")):
+ found = True
+
+ if not found:
+ print("{} refer to non existing parent".format(node.name))
+ valid = False
+
+ return valid
+
+ def validate_nodes(self) -> bool:
+ valid = True
+
+ if ifdef_stack:
+ print("invalid ifdef macro")
+ valid = False
+
+ certs = self.get_all_certificates()
+ images = self.get_all_images()
+
+ for n in certs:
+ node_valid = self.validate_cert(n)
+ valid = valid and node_valid
+
+ for i in images:
+ node_valid = self.validate_img(i)
+ valid = valid and node_valid
+
+ if not self.has_root:
+ print("missing root certificate")
+
+ return valid
+
+ def extract_licence(self, f):
+ licence = []
+
+ licencereg = re.compile(r'/\*')
+ licenceendReg = re.compile(r'\*/')
+
+ licencePre = False
+
+ for line in f:
+ match = licencereg.search(line)
+ if match != None:
+ licence.append(line)
+ licencePre = True
+ continue
+
+ match = licenceendReg.search(line)
+ if match != None:
+ licence.append(line)
+ licencePre = False
+ return licence
+
+ if licencePre:
+ licence.append(line)
+ else:
+ return licence
+
+ return licence
+
+ def licence_to_c(self, licence, f):
+ if len(licence) != 0:
+ for i in licence:
+ f.write(i)
+
+ f.write("\n")
+ return
+
+ def extract_include(self, f):
+ include = []
+
+ for line in f:
+ if "cot" in line:
+ return include
+
+ if line != "" and "common" not in line and line != "\n":
+ include.append(line)
+
+ return include
+
+ def include_to_c(self, include, f):
+ f.write("#include <stddef.h>\n")
+ f.write("#include <mbedtls/version.h>\n")
+ f.write("#include <common/tbbr/cot_def.h>\n")
+ f.write("#include <drivers/auth/auth_mod.h>\n")
+ f.write("\n")
+ for i in include:
+ f.write(i)
+ f.write("\n")
+ f.write("#include <platform_def.h>\n\n")
+ return
+
+ def generate_header(self, input, output):
+ licence = self.extract_licence(input)
+ include = self.extract_include(input)
+ self.licence_to_c(licence, output)
+ self.include_to_c(include, output)
+
+ def all_cert_to_c(self, f):
+ certs = self.get_all_certificates()
+ for c in certs:
+ self.cert_to_c(c, f)
+
+ f.write("\n")
+
+ def cert_to_c(self, node: Node, f):
+ ifdef = node.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("static const auth_img_desc_t {} = {{\n".format(node.name))
+ f.write("\t.img_id = {},\n".format(node.get_field("image-id").values[0].replace('"', "")))
+ f.write("\t.img_type = IMG_CERT,\n")
+
+ if not self.if_root(node):
+ f.write("\t.parent = &{},\n".format(node.get_field("parent").label.name))
+ else:
+ f.write("\t.parent = NULL,\n")
+
+ sign = self.get_sign_key(node)
+ nv_ctr = self.get_nv_ctr(node)
+
+ if sign or nv_ctr:
+ f.write("\t.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {\n")
+
+ if sign:
+ f.write("\t\t[0] = {\n")
+ f.write("\t\t\t.type = AUTH_METHOD_SIG,\n")
+ f.write("\t\t\t.param.sig = {\n")
+
+ f.write("\t\t\t\t.pk = &{},\n".format(self.extract_label(sign)))
+ f.write("\t\t\t\t.sig = &sig,\n")
+ f.write("\t\t\t\t.alg = &sig_alg,\n")
+ f.write("\t\t\t\t.data = &raw_data\n")
+ f.write("\t\t\t}\n")
+ f.write("\t\t}}{}\n".format("," if nv_ctr else ""))
+
+ if nv_ctr:
+ f.write("\t\t[1] = {\n")
+ f.write("\t\t\t.type = AUTH_METHOD_NV_CTR,\n")
+ f.write("\t\t\t.param.nv_ctr = {\n")
+
+ f.write("\t\t\t\t.cert_nv_ctr = &{},\n".format(self.extract_label(nv_ctr)))
+ f.write("\t\t\t\t.plat_nv_ctr = &{}\n".format(self.extract_label(nv_ctr)))
+
+ f.write("\t\t\t}\n")
+ f.write("\t\t}\n")
+
+ f.write("\t},\n")
+
+ auth_data = self.get_auth_data(node)
+ if auth_data:
+ f.write("\t.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {\n")
+
+ for i, d in enumerate(auth_data):
+ type_desc, ptr, data_len = self.format_auth_data_val(d, node)
+
+ f.write("\t\t[{}] = {{\n".format(i))
+ f.write("\t\t\t.type_desc = &{},\n".format(type_desc))
+ f.write("\t\t\t.data = {\n")
+
+ n = extractNumber(type_desc)
+ if "pkg" not in type_desc or n == -1:
+ f.write("\t\t\t\t.ptr = (void *){},\n".format(ptr))
+ else:
+ f.write("\t\t\t\t.ptr = (void *){}[{}],\n".format(ptr, n-1))
+
+ f.write("\t\t\t\t.len = {}\n".format(data_len))
+ f.write("\t\t\t}\n")
+
+ f.write("\t\t}}{}\n".format("," if i != len(auth_data) - 1 else ""))
+
+ f.write("\t}\n")
+
+ f.write("};\n\n")
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+ f.write("\n")
+
+ return
+
+
+ def img_to_c(self, node:Node, f):
+ ifdef = node.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("static const auth_img_desc_t {} = {{\n".format(node.name))
+ f.write("\t.img_id = {},\n".format(node.get_field("image-id").values[0].replace('"', "")))
+ f.write("\t.img_type = IMG_RAW,\n")
+ f.write("\t.parent = &{},\n".format(node.get_field("parent").label.name))
+ f.write("\t.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {\n")
+
+ f.write("\t\t[0] = {\n")
+ f.write("\t\t\t.type = AUTH_METHOD_HASH,\n")
+ f.write("\t\t\t.param.hash = {\n")
+ f.write("\t\t\t\t.data = &raw_data,\n")
+ f.write("\t\t\t\t.hash = &{}\n".format(node.get_field("hash").label.name))
+ f.write("\t\t\t}\n")
+
+ f.write("\t\t}\n")
+ f.write("\t}\n")
+ f.write("};\n\n")
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+ f.write("\n")
+
+ return
+
+ def all_img_to_c(self, f):
+ images = self.get_all_images()
+ for i in images:
+ self.img_to_c(i, f)
+
+ f.write("\n")
+
+ def nv_to_c(self, f):
+ nv_ctr = self.get_all_nv_counters()
+
+ for nv in nv_ctr:
+ f.write("static auth_param_type_desc_t {} = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_NV_CTR, {});\n".format(nv.name, nv.get_field("oid")))
+
+ f.write("\n")
+
+ return
+
+ def pk_to_c(self, f):
+ pks = self.get_all_pks()
+
+ for p in pks:
+ f.write("static auth_param_type_desc_t {} = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, {});\n".format(p.name, p.get_field("oid")))
+
+ f.write("\n")
+ return
+
+ def buf_to_c(self, f):
+ certs = self.get_all_certificates()
+
+ buffers = {}
+
+ for c in certs:
+ auth_data = self.get_auth_data(c)
+ for a in auth_data:
+ type_desc, ptr, data_len = self.format_auth_data_val(a, c)
+ if ptr not in buffers:
+ buffers[ptr] = c.get_fields("ifdef")
+
+ for key, values in buffers.items():
+ if values:
+ for i in values:
+ f.write("{}\n".format(i))
+
+ if "sp_pkg_hash_buf" in key:
+ f.write("static unsigned char {}[MAX_SP_IDS][HASH_DER_LEN];\n".format(key))
+ elif "pk" in key:
+ f.write("static unsigned char {}[PK_DER_LEN];\n".format(key))
+ else:
+ f.write("static unsigned char {}[HASH_DER_LEN];\n".format(key))
+
+ if values:
+ for i in values:
+ f.write("#endif\n")
+
+ f.write("\n")
+
+ def param_to_c(self, f):
+ f.write("static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, 0);\n")
+ f.write("static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_SIG, 0);\n")
+ f.write("static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_SIG_ALG, 0);\n")
+ f.write("static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_RAW_DATA, 0);\n")
+ f.write("\n")
+
+ certs = self.get_all_certificates()
+ for c in certs:
+ ifdef = c.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ hash = c.children
+ for h in hash:
+ name = h.name
+ oid = h.get_field("oid")
+
+ if "pk" in name and "pkg" not in name:
+ f.write("static auth_param_type_desc_t {} = "\
+ "AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, {});\n".format(name, oid))
+ elif "hash" in name:
+ f.write("static auth_param_type_desc_t {} = "\
+ "AUTH_PARAM_TYPE_DESC(AUTH_PARAM_HASH, {});\n".format(name, oid))
+ elif "ctr" in name:
+ f.write("static auth_param_type_desc_t {} = "\
+ "AUTH_PARAM_TYPE_DESC(AUTH_PARAM_NV_CTR, {});\n".format(name, oid))
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+
+ f.write("\n")
+
+ def cot_to_c(self, f):
+ certs = self.get_all_certificates()
+ images = self.get_all_images()
+
+ f.write("static const auth_img_desc_t * const cot_desc[] = {\n")
+
+ for i, c in enumerate(certs):
+ ifdef = c.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("\t[{}] = &{}{}\n".format(c.get_field("image-id").values[0], c.name, ","))
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+
+ for i, c in enumerate(images):
+ ifdef = c.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("\t[{}] = &{}{}\n".format(c.get_field("image-id").values[0], c.name, "," if i != len(images) - 1 else ""))
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+
+ f.write("};\n\n")
+ f.write("REGISTER_COT(cot_desc);\n")
+ return
+
+ def generate_c_file(self):
+ filename = Path(self.output)
+ filename.parent.mkdir(exist_ok=True, parents=True)
+ output = open(self.output, 'w+')
+ input = open(self.input, "r")
+
+ self.generate_header(input, output)
+ self.buf_to_c(output)
+ self.param_to_c(output)
+ self.nv_to_c(output)
+ self.pk_to_c(output)
+ self.all_cert_to_c(output)
+ self.all_img_to_c(output)
+ self.cot_to_c(output)
+
+ return
diff --git a/tools/cot_dt2c/cot_dt2c/dt_validator.py b/tools/cot_dt2c/cot_dt2c/dt_validator.py
new file mode 100644
index 0000000..65e8ca2
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/dt_validator.py
@@ -0,0 +1,130 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+from os import path, walk, mkdir
+import subprocess
+from cot_dt2c.pydevicetree import *
+
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKCYAN = '\033[96m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
+class DTTree:
+ def __init__(self, input):
+ self.input = input
+ self.test_dir = "./tmp"
+ self.logging_file = self.test_dir + "/result.log"
+
+ def dtValidate(self):
+ subprocess.run(["rm", "-rf", self.test_dir])
+
+ if not path.exists(self.test_dir):
+ mkdir(self.test_dir)
+
+ if path.isfile(self.input):
+ self.dtValidateFile(self.input, printInfo=True)
+ return
+
+ if path.isdir(self.input):
+ self.dtValidateFiles()
+ return
+
+ def dtValidateFile(self, input, printInfo=False):
+ valid, tree = self.dtParseFile(input, printInfo)
+
+ if not valid:
+ return False
+
+ if input.rfind("/") != -1:
+ filename = self.test_dir + input[input.rfind("/"):]
+ else:
+ filename = self.test_dir + "/" + input
+
+ f = open(filename, "w+")
+ if "/dts-v1/;" not in str(tree):
+ f.write("/dts-v1/;\n\n")
+ f.write(str(tree))
+ f.close()
+
+ if str(tree) == "":
+ return valid
+
+ return valid
+
+ def dtParseFile(self, input, printInfo=False):
+ with open(input, 'r') as f:
+ contents = f.read()
+
+ pos = contents.find("/ {")
+ if pos != -1:
+ contents = contents[pos:]
+
+ try:
+ tree = Devicetree.parseStr(contents)
+ if printInfo:
+ print(bcolors.OKGREEN + "{} parse tree successfully".format(input) + bcolors.ENDC)
+ except Exception as e:
+ if printInfo:
+ print(bcolors.FAIL + "{} parse tree failed:\t{}".format(input, str(e)) + bcolors.ENDC)
+ else:
+ f = open(self.logging_file, "a")
+ f.write("=====================================================================================\n")
+ f.write("{} result:\n".format(input))
+ f.write("{} INVALID:\t{}\n".format(input, str(e)))
+ f.close()
+ return False, None
+
+ return True, tree
+
+ def dtValidateFiles(self):
+ f = []
+ for (dirpath, dirnames, filenames) in walk(self.input):
+ f.extend(filenames)
+
+ allFile = len(f)
+ dtsiFile = 0
+ validFile = 0
+ invalidFile = 0
+
+ for i in f:
+ if (".dtsi" in i or ".dts" in i) and "cot" not in i and "fw-config" not in i:
+ dtsiFile += 1
+ valid = True
+
+ if self.input[-1] == "/":
+ valid = self.dtValidateFile(self.input + i)
+ else:
+ valid = self.dtValidateFile(self.input + "/" + i)
+
+ if valid:
+ validFile += 1
+ else:
+ invalidFile += 1
+
+ print("=====================================================")
+ print("Total File: " + str(allFile))
+ print("Total DT File: " + str(dtsiFile))
+ print("Total Valid File: " + str(validFile))
+ print("Total Invalid File: " + str(invalidFile))
+
+def dtValidatorMain(input):
+ dt = DTTree(input)
+ dt.dtValidate()
+
+if __name__=="__main__":
+ if (len(sys.argv) < 2):
+ print("usage: python3 " + sys.argv[0] + " [dtsi file path] or [dtsi folder path]")
+ exit()
+ if len(sys.argv) == 2:
+ dtValidatorMain(sys.argv[1])
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py
new file mode 100644
index 0000000..49595a7
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from cot_dt2c.pydevicetree.ast import Devicetree, Node, Property, Directive, CellArray, LabelReference
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py
new file mode 100644
index 0000000..f30d897
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from cot_dt2c.pydevicetree.ast.directive import Directive
+from cot_dt2c.pydevicetree.ast.node import Node, NodeReference, Devicetree
+from cot_dt2c.pydevicetree.ast.property import PropertyValues, Bytestring, CellArray, StringList, Property, \
+ RegArray, OneString
+from cot_dt2c.pydevicetree.ast.reference import Label, Path, Reference, LabelReference, PathReference
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py
new file mode 100644
index 0000000..fdd6f0e
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import Any
+
+from cot_dt2c.pydevicetree.ast.helpers import formatLevel, wrapStrings
+
+class Directive:
+ """Represents a Devicetree directive
+
+ Directives in Devicetree source are statements of the form
+
+ /directive-name/ [option1 [option2 [...]]];
+
+ Common directive examples include:
+
+ /dts-v1/;
+ /include/ "overlay.dtsi";
+ /delete-node/ &uart0;
+ /delete-property/ status;
+
+ Their semantic meaning depends on the directive name, their location in the Devicetree,
+ and their options.
+ """
+ def __init__(self, directive: str, option: Any = None):
+ """Create a directive object"""
+ self.directive = directive
+ self.option = option
+
+ def __repr__(self) -> str:
+ return "<Directive %s>" % self.directive
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ def to_dts(self, level: int = 0) -> str:
+ """Format the Directive in Devicetree Source format"""
+ if isinstance(self.option, list):
+ return formatLevel(level, "%s %s;\n" % (self.directive,
+ wrapStrings(self.option)))
+ if isinstance(self.option, str):
+ if self.directive == "/include/":
+ return formatLevel(level, "%s \"%s\"\n" % (self.directive, self.option))
+ return formatLevel(level, "%s \"%s\";\n" % (self.directive, self.option))
+ return formatLevel(level, "%s;\n" % self.directive)
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py
new file mode 100644
index 0000000..30c54dc
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import List, Any
+
+from cot_dt2c.pydevicetree.ast.reference import Reference
+
+def formatLevel(level: int, s: str) -> str:
+ """Helper to indent a string with a number of tabs"""
+ return "\t" * level + s
+
+def wrapStrings(values: List[Any], formatHex: bool = False) -> List[Any]:
+ """Helper to wrap strings in quotes where appropriate"""
+ wrapped = []
+ for v in values:
+ if isinstance(v, Reference):
+ wrapped.append(v.to_dts())
+ elif isinstance(v, str):
+ wrapped.append("\"%s\"" % v)
+ elif isinstance(v, int):
+ if formatHex:
+ wrapped.append("0x%x" % v)
+ else:
+ wrapped.append(str(v))
+ else:
+ wrapped.append(str(v))
+ return wrapped
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py
new file mode 100644
index 0000000..d203af8
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py
@@ -0,0 +1,514 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+import re
+import os
+from typing import List, Union, Optional, Iterable, Callable, Any, cast, Pattern
+
+from cot_dt2c.pydevicetree.ast.helpers import formatLevel
+from cot_dt2c.pydevicetree.ast.property import Property, PropertyValues, RegArray, RangeArray
+from cot_dt2c.pydevicetree.ast.directive import Directive
+from cot_dt2c.pydevicetree.ast.reference import Label, Path, Reference, LabelReference, PathReference
+
+# Type signature for elements passed to Devicetree constructor
+ElementList = Iterable[Union['Node', Property, Directive]]
+
+# Callback type signatures for Devicetree.match() and Devicetree.chosen()
+MatchFunc = Callable[['Node'], bool]
+MatchCallback = Optional[Callable[['Node'], None]]
+ChosenCallback = Optional[Callable[[PropertyValues], None]]
+
+class Node:
+ """Represents a Devicetree Node
+
+ A Devicetree Node generally takes the form
+
+ [label:] node-name@unit-address {
+ [directives]
+ [properties]
+ [child nodes]
+ };
+
+ The structure formed by creating trees of Nodes is the bulk of any Devicetree. As the naming
+ system implies, then, each node roughly corresponds to some conceptual device, subsystem of
+ devices, bus, etc.
+
+ Devices can be referenced by label or by path, and are generally uniquely identified by a
+ collection of string identifiers assigned to the "compatible" property.
+
+ For instance, a UART device might look like
+
+ uart0: uart@10013000 {
+ compatible = "sifive,uart0";
+ reg = <0x10013000 0x1000>;
+ reg-names = "control";
+ interrupt-parent = <&plic>;
+ interrupts = <3>;
+ clocks = <&busclk>;
+ status = "okay";
+ };
+
+ This node can be identified in the following ways:
+
+ - By label: uart0
+ - By path: /path/to/uart@10013000
+ - By name: uart@10013000 (for example when referenced in a /delete-node/ directive)
+ """
+ # pylint: disable=too-many-arguments
+ def __init__(self, name: str, label: Optional[str], address: Optional[int],
+ properties: List[Property], directives: List[Directive],
+ children: List['Node']):
+ """Initializes a Devicetree Node
+
+ Also evaluates the /delete-node/ and /delete-property/ directives found in the node
+ and deletes the respective nodes and properties.
+ """
+ self.name = name
+ self.parent = None # type: Optional['Node']
+
+ self.label = label
+ self.address = address
+ self.properties = properties
+ self.directives = directives
+ self.children = children
+ self.ifdef = []
+
+ for d in self.directives:
+ if d.directive == "/delete-node/":
+ if isinstance(d.option, LabelReference):
+ node = self.get_by_reference(d.option)
+ elif isinstance(d.option, str):
+ node = self.__get_child_by_handle(d.option)
+ if node:
+ self.remove_child(node)
+ elif d.directive == "/delete-property/":
+ # pylint: disable=cell-var-from-loop
+ properties = list(filter(lambda p: p.name == d.option, self.properties))
+ if properties:
+ del self.properties[self.properties.index(properties[0])]
+
+ def __repr__(self) -> str:
+ if self.address:
+ return "<Node %s@%x>" % (self.name, self.address)
+ return "<Node %s>" % self.name
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ def __eq__(self, other) -> bool:
+ return self.name == other.name and self.address == other.address
+
+ def __hash__(self):
+ return hash((self.name, self.address))
+
+ @staticmethod
+ def from_dts(source: str) -> 'Node':
+ """Create a node from Devicetree Source"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from pydevicetree.source import parseNode
+ return parseNode(source)
+
+ def add_child(self, node: 'Node', merge: bool = True):
+ """Add a child node and merge it into the tree"""
+ node.parent = self
+ self.children.append(node)
+ if merge:
+ self.merge_tree()
+
+ def to_dts(self, level: int = 0) -> str:
+ """Format the subtree starting at the node as Devicetree Source"""
+ out = ""
+ if isinstance(self.address, int) and self.label:
+ out += formatLevel(level,
+ "%s: %s@%x {\n" % (self.label, self.name, self.address))
+ elif isinstance(self.address, int):
+ out += formatLevel(level, "%s@%x {\n" % (self.name, self.address))
+ elif self.label:
+ out += formatLevel(level, "%s: %s {\n" % (self.label, self.name))
+ elif self.name != "":
+ out += formatLevel(level, "%s {\n" % self.name)
+
+ for d in self.directives:
+ out += d.to_dts(level + 1)
+ for p in self.properties:
+ out += p.to_dts(level + 1)
+ for c in self.children:
+ out += c.to_dts(level + 1)
+
+ if self.name != "":
+ out += formatLevel(level, "};\n")
+
+ return out
+
+ def merge_tree(self):
+ """Recursively merge child nodes into a single tree
+
+ Parsed Devicetrees can describe the same tree multiple times, adding nodes and properties
+ each time. After parsing, this method is called to recursively merge the tree.
+ """
+ partitioned_children = []
+ for n in self.children:
+ partitioned_children.append([e for e in self.children if e == n])
+
+ new_children = []
+ for part in partitioned_children:
+ first = part[0]
+ rest = part[1:]
+ if first not in new_children:
+ for n in rest:
+ first.merge(n)
+ new_children.append(first)
+
+ self.children = new_children
+
+ for n in self.children:
+ n.parent = self
+ n.merge_tree()
+
+ def merge(self, other: 'Node'):
+ """Merge the contents of a node into this node.
+
+ Used by Node.merge_trees()
+ """
+ if not self.label and other.label:
+ self.label = other.label
+ self.properties += other.properties
+ self.directives += other.directives
+ self.children += other.children
+ self.ifdef += other.ifdef
+
+ def get_path(self, includeAddress: bool = True) -> str:
+ """Get the path of a node (ex. /cpus/cpu@0)"""
+ if self.name == "/":
+ return ""
+ if self.parent is None:
+ return "/" + self.name
+ if isinstance(self.address, int) and includeAddress:
+ return self.parent.get_path() + "/" + self.name + "@" + ("%x" % self.address)
+ return self.parent.get_path() + "/" + self.name
+
+ def get_by_reference(self, reference: Reference) -> Optional['Node']:
+ """Get a node from the subtree by reference (ex. &label, &{/path/to/node})"""
+ if isinstance(reference, LabelReference):
+ return self.get_by_label(reference.label)
+ if isinstance(reference, PathReference):
+ return self.get_by_path(reference.path)
+
+ return None
+
+ def get_by_label(self, label: Union[Label, str]) -> Optional['Node']:
+ """Get a node from the subtree by label"""
+ matching_nodes = list(filter(lambda n: n.label == label, self.child_nodes()))
+ if len(matching_nodes) != 0:
+ return matching_nodes[0]
+ return None
+
+ def __get_child_by_handle(self, handle: str) -> Optional['Node']:
+ """Get a child node by name or name and unit address"""
+ if '@' in handle:
+ name, addr_s = handle.split('@')
+ address = int(addr_s, base=16)
+ nodes = list(filter(lambda n: n.name == name and n.address == address, self.children))
+ else:
+ name = handle
+ nodes = list(filter(lambda n: n.name == name, self.children))
+
+ if not nodes:
+ return None
+ if len(nodes) > 1:
+ raise Exception("Handle %s is ambiguous!" % handle)
+ return nodes[0]
+
+ def get_by_path(self, path: Union[Path, str]) -> Optional['Node']:
+ """Get a node in the subtree by path"""
+ matching_nodes = list(filter(lambda n: path == n.get_path(includeAddress=True), \
+ self.child_nodes()))
+ if len(matching_nodes) != 0:
+ return matching_nodes[0]
+
+ matching_nodes = list(filter(lambda n: path == n.get_path(includeAddress=False), \
+ self.child_nodes()))
+ if len(matching_nodes) != 0:
+ return matching_nodes[0]
+ return None
+
+ def filter(self, matchFunc: MatchFunc, cbFunc: MatchCallback = None) -> List['Node']:
+ """Filter all child nodes by matchFunc
+
+ If cbFunc is provided, this method will iterate over the Nodes selected by matchFunc
+ and call cbFunc on each Node
+
+ Returns a list of all matching Nodes
+ """
+ nodes = list(filter(matchFunc, self.child_nodes()))
+
+ if cbFunc is not None:
+ for n in nodes:
+ cbFunc(n)
+
+ return nodes
+
+ def match(self, compatible: Pattern, func: MatchCallback = None) -> List['Node']:
+ """Get a node from the subtree by compatible string
+
+ Accepts a regular expression to match one of the strings in the compatible property.
+ """
+ regex = re.compile(compatible)
+
+ def match_compat(node: Node) -> bool:
+ compatibles = node.get_fields("compatible")
+ if compatibles is not None:
+ return any(regex.match(c) for c in compatibles)
+ return False
+
+ return self.filter(match_compat, func)
+
+ def child_nodes(self) -> Iterable['Node']:
+ """Get an iterable over all the nodes in the subtree"""
+ for n in self.children:
+ yield n
+ for m in n.child_nodes():
+ yield m
+
+ def remove_child(self, node):
+ """Remove a child node"""
+ del self.children[self.children.index(node)]
+
+ def get_fields(self, field_name: str) -> Optional[PropertyValues]:
+ """Get all the values of a property"""
+ for p in self.properties:
+ if p.name == field_name:
+ return p.values
+ return None
+
+ def has_field(self, field_name: str) -> bool:
+ for p in self.properties:
+ if p.name == field_name:
+ return True
+ return False
+
+ def get_field(self, field_name: str) -> Any:
+ """Get the first value of a property"""
+ fields = self.get_fields(field_name)
+ if fields is not None:
+ if len(cast(PropertyValues, fields)) != 0:
+ return fields[0]
+ return None
+
+ def get_reg(self) -> Optional[RegArray]:
+ """If the node defines a `reg` property, return a RegArray for easier querying"""
+ reg = self.get_fields("reg")
+ reg_names = self.get_fields("reg-names")
+ if reg is not None:
+ if reg_names is not None:
+ return RegArray(reg.values, self.address_cells(), self.size_cells(),
+ reg_names.values)
+ return RegArray(reg.values, self.address_cells(), self.size_cells())
+ return None
+
+ def get_ranges(self) -> Optional[RangeArray]:
+ """If the node defines a `ranges` property, return a RangeArray for easier querying"""
+ ranges = self.get_fields("ranges")
+ child_address_cells = self.get_field("#address-cells")
+ parent_address_cells = self.address_cells()
+ size_cells = self.get_field("#size-cells")
+ if ranges is not None:
+ return RangeArray(ranges.values, child_address_cells, parent_address_cells, size_cells)
+ return None
+
+ def address_cells(self):
+ """Get the number of address cells
+
+ The #address-cells property is defined by the parent of a node and describes how addresses
+ are encoded in cell arrays. If no property is defined, the default value is 2.
+ """
+ if self.parent is not None:
+ cells = self.parent.get_field("#address-cells")
+ if cells is not None:
+ return cells
+ return 2
+ return 2
+
+ def size_cells(self):
+ """Get the number of size cells
+
+ The #size-cells property is defined by the parent of a node and describes how addresses
+ are encoded in cell arrays. If no property is defined, the default value is 1.
+ """
+ if self.parent is not None:
+ cells = self.parent.get_field("#size-cells")
+ if cells is not None:
+ return cells
+ return 1
+ return 1
+
+class NodeReference(Node):
+ """A NodeReference is used to extend the definition of a previously-defined Node
+
+ NodeReferences are commonly used by Devicetree "overlays" to extend the properties of a node
+ or add child devices, such as to a bus like I2C.
+ """
+ def __init__(self, reference: Reference, properties: List[Property],
+ directives: List[Directive], children: List[Node]):
+ """Instantiate a Node identified by reference to another node"""
+ self.reference = reference
+ Node.__init__(self, label=None, name="", address=None, properties=properties,
+ directives=directives, children=children)
+
+ def __repr__(self) -> str:
+ return "<NodeReference %s>" % self.reference.to_dts()
+
+ def resolve_reference(self, tree: 'Devicetree') -> Node:
+ """Given the full tree, get the node being referenced"""
+ node = tree.get_by_reference(self.reference)
+ if node is None:
+ raise Exception("Node reference %s cannot be resolved" % self.reference.to_dts())
+ return cast(Node, node)
+
+ def to_dts(self, level: int = 0) -> str:
+ out = formatLevel(level, self.reference.to_dts() + " {\n")
+
+ for d in self.directives:
+ out += d.to_dts(level + 1)
+ for p in self.properties:
+ out += p.to_dts(level + 1)
+ for c in self.children:
+ out += c.to_dts(level + 1)
+
+ out += formatLevel(level, "};\n")
+
+ return out
+
+
+class Devicetree(Node):
+ """A Devicetree object describes the full Devicetree tree
+
+ This class encapsulates both the tree itself (starting at the root node /) and any Directives
+ or nodes which exist at the top level of the Devicetree Source files.
+
+ Devicetree Source files can be parsed by calling Devicetree.parseFile().
+ """
+ def __init__(self, elements: ElementList):
+ """Instantiate a Devicetree with the list of parsed elements
+
+ Resolves all reference nodes and merges the tree to combine all identical nodes.
+ """
+ properties = [] # type: List[Property]
+ directives = [] # type: List[Directive]
+ children = [] # type: List[Node]
+
+ for e in elements:
+ if isinstance(e, Node):
+ children.append(cast(Node, e))
+ elif isinstance(e, Property):
+ properties.append(cast(Property, e))
+ elif isinstance(e, Directive):
+ directives.append(cast(Directive, e))
+
+ Node.__init__(self, label=None, name="", address=None,
+ properties=properties, directives=directives, children=children)
+
+ for node in self.children:
+ node.parent = self
+
+ reference_nodes = self.filter(lambda n: isinstance(n, NodeReference))
+ for refnode in reference_nodes:
+ refnode = cast(NodeReference, refnode)
+
+ node = refnode.resolve_reference(self)
+
+ if refnode.parent:
+ cast(Node, refnode.parent).remove_child(refnode)
+
+ node.properties += refnode.properties
+ node.directives += refnode.directives
+ node.children += refnode.children
+
+ self.merge_tree()
+
+ def __repr__(self) -> str:
+ name = self.root().get_field("compatible")
+ return "<Devicetree %s>" % name
+
+ def to_dts(self, level: int = 0) -> str:
+ """Convert the tree back to Devicetree Source"""
+ out = ""
+
+ for d in self.directives:
+ out += d.to_dts()
+ for p in self.properties:
+ out += p.to_dts()
+ for c in self.children:
+ out += c.to_dts()
+
+ return out
+
+ def get_by_path(self, path: Union[Path, str]) -> Optional[Node]:
+ """Get a node in the tree by path (ex. /cpus/cpu@0)"""
+
+ # Find and replace all aliases in the path
+ aliases = self.aliases()
+ if aliases:
+ for prop in aliases.properties:
+ if prop.name in path and len(prop.values) > 0:
+ path = path.replace(prop.name, prop.values[0])
+
+ return self.root().get_by_path(path)
+
+ @staticmethod
+ # pylint: disable=arguments-differ
+ def from_dts(dts: str) -> 'Devicetree':
+ """Parse a string and return a Devicetree object"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from pydevicetree.source import parseTree
+ return parseTree(dts)
+
+ @staticmethod
+ def parseFile(filename: str, followIncludes: bool = False) -> 'Devicetree':
+ """Parse a file and return a Devicetree object"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from cot_dt2c.pydevicetree.source.parser import parseTree
+ with open(filename, 'r') as f:
+ contents = f.read()
+ dirname = os.path.dirname(filename)
+ if dirname != "":
+ dirname += "/"
+ return parseTree(contents, dirname, followIncludes)
+
+ @staticmethod
+ def parseStr(input: str, followIncludes: bool = False) -> 'Devicetree':
+ from cot_dt2c.pydevicetree.source.parser import parseTree
+ return parseTree(input, "", followIncludes)
+
+ def all_nodes(self) -> Iterable[Node]:
+ """Get an iterable over all nodes in the tree"""
+ return self.child_nodes()
+
+ def root(self) -> Node:
+ """Get the root node of the tree"""
+ for n in self.all_nodes():
+ if n.name == "/":
+ return n
+ raise Exception("Devicetree has no root node!")
+
+ def aliases(self) -> Optional[Node]:
+ """Get the aliases node of the tree if it exists"""
+ for n in self.all_nodes():
+ if n.name == "aliases":
+ return n
+ return None
+
+ def chosen(self, property_name: str, func: ChosenCallback = None) -> Optional[PropertyValues]:
+ """Get the values associated with one of the properties in the chosen node"""
+ def match_chosen(node: Node) -> bool:
+ return node.name == "chosen"
+
+ for n in filter(match_chosen, self.all_nodes()):
+ for p in n.properties:
+ if p.name == property_name:
+ if func is not None:
+ func(p.values)
+ return p.values
+
+ return None
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py
new file mode 100644
index 0000000..d5fb687
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py
@@ -0,0 +1,278 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import List, Any, cast, Tuple, Optional, Iterable
+from itertools import zip_longest
+
+from cot_dt2c.pydevicetree.ast.helpers import wrapStrings, formatLevel
+
+class PropertyValues:
+ """PropertyValues is the parent class of all values which can be assigned to a Property
+
+ Child classes include
+
+ Bytestring
+ CellArray
+ StringList
+ """
+ def __init__(self, values: List[Any]):
+ """Create a PropertyValue"""
+ self.values = values
+
+ def __repr__(self) -> str:
+ return "<PropertyValues " + self.values.__repr__() + ">"
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ def __iter__(self):
+ return iter(self.values)
+
+ def __len__(self) -> int:
+ return len(self.values)
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the values in Devicetree Source format"""
+ return ", ".join(wrapStrings(self.values, formatHex))
+
+ def __getitem__(self, key) -> Any:
+ return self.values[key]
+
+ def __eq__(self, other) -> bool:
+ if isinstance(other, PropertyValues):
+ return self.values == other.values
+ return self.values == other
+
+class Bytestring(PropertyValues):
+ """A Bytestring is a sequence of bytes
+
+ In Devicetree, Bytestrings are represented as a sequence of two-digit hexadecimal integers,
+ optionally space-separated, enclosed by square brackets:
+
+ [de ad be eef]
+ """
+ def __init__(self, bytelist: List[int]):
+ """Create a Bytestring object"""
+ PropertyValues.__init__(self, cast(List[Any], bytearray(bytelist)))
+
+ def __repr__(self) -> str:
+ return "<Bytestring " + str(self.values) + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the bytestring in Devicetree Source format"""
+ return "[" + " ".join("%02x" % v for v in self.values) + "]"
+
+class CellArray(PropertyValues):
+ """A CellArray is an array of integer values
+
+ CellArrays are commonly used as the value of Devicetree properties like `reg` and `interrupts`.
+ The interpretation of each element of a CellArray is device-dependent. For example, the `reg`
+ property encodes a CellArray as a list of tuples (base address, size), while the `interrupts`
+ property encodes a CellArray as simply a list of interrupt line numbers.
+ """
+ def __init__(self, cells: List[Any]):
+ """Create a CellArray object"""
+ PropertyValues.__init__(self, cells)
+
+ def __repr__(self) -> str:
+ return "<CellArray " + self.values.__repr__() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the cell array in Devicetree Source format"""
+ dtsValues = []
+ for i in self.values:
+ if not isinstance(i, OneString) and not isinstance(i, str):
+ dtsValues.append(i)
+ return "<" + " ".join(wrapStrings(dtsValues, formatHex)) + ">"
+
+class RegArray(CellArray):
+ """A RegArray is the CellArray assigned to the reg property"""
+ def __init__(self, cells: List[int],
+ address_cells: int, size_cells: int,
+ names: Optional[List[str]] = None):
+ """Create a RegArray from a list of ints"""
+ # pylint: disable=too-many-locals
+ CellArray.__init__(self, cells)
+ self.address_cells = address_cells
+ self.size_cells = size_cells
+
+ self.tuples = [] # type: List[Tuple[int, int, Optional[str]]]
+
+ group_size = self.address_cells + self.size_cells
+
+ if len(cells) % group_size != 0:
+ raise Exception("CellArray does not contain enough cells")
+
+ grouped_cells = [cells[i:i+group_size] for i in range(0, len(cells), group_size)]
+
+ if not names:
+ names = []
+
+ for group, name in zip_longest(grouped_cells, cast(Iterable[Any], names)):
+ address = 0
+ a_cells = list(reversed(group[:self.address_cells]))
+ for a, i in zip(a_cells, range(len(a_cells))):
+ address += (1 << (32 * i)) * a
+
+ size = 0
+ s_cells = list(reversed(group[self.address_cells:]))
+ for s, i in zip(s_cells, range(len(s_cells))):
+ size += (1 << (32 * i)) * s
+
+ self.tuples.append(cast(Tuple[int, int, Optional[str]], tuple([address, size, name])))
+
+ def get_by_name(self, name: str) -> Optional[Tuple[int, int]]:
+ """Returns the (address, size) tuple with a given name"""
+ for t in self.tuples:
+ if t[2] == name:
+ return cast(Tuple[int, int], tuple(t[:2]))
+ return None
+
+ def __repr__(self) -> str:
+ return "<RegArray " + self.values.__repr__() + ">"
+
+ def __iter__(self) -> Iterable[Tuple[int, int]]:
+ return cast(Iterable[Tuple[int, int]], map(lambda t: tuple(t[:2]), self.tuples))
+
+ def __len__(self) -> int:
+ return len(self.tuples)
+
+ def __getitem__(self, key) -> Optional[Tuple[int, int]]:
+ return list(self.__iter__())[key]
+
+class RangeArray(CellArray):
+ """A RangeArray is the CellArray assigned to the range property"""
+ def __init__(self, cells: List[int], child_address_cells: int,
+ parent_address_cells: int, size_cells: int):
+ """Create a RangeArray from a list of ints"""
+ # pylint: disable=too-many-locals
+ CellArray.__init__(self, cells)
+ self.child_address_cells = child_address_cells
+ self.parent_address_cells = parent_address_cells
+ self.size_cells = size_cells
+
+ self.tuples = [] # type: List[Tuple[int, int, int]]
+
+ group_size = self.child_address_cells + self.parent_address_cells + self.size_cells
+
+ if len(cells) % group_size != 0:
+ raise Exception("CellArray does not contain enough cells")
+
+ grouped_cells = [cells[i:i+group_size] for i in range(0, len(cells), group_size)]
+
+ def sum_cells(cells: List[int]):
+ value = 0
+ for cell, index in zip(list(reversed(cells)), range(len(cells))):
+ value += (1 << (32 * index)) * cell
+ return value
+
+ for group in grouped_cells:
+ child_address = sum_cells(group[:self.child_address_cells])
+ parent_address = sum_cells(group[self.child_address_cells: \
+ self.child_address_cells + self.parent_address_cells])
+ size = sum_cells(group[self.child_address_cells + self.parent_address_cells:])
+
+ self.tuples.append(cast(Tuple[int, int, int],
+ tuple([child_address, parent_address, size])))
+
+ def __repr__(self) -> str:
+ return "<RangeArray " + self.values.__repr__() + ">"
+
+ def __iter__(self):
+ return iter(self.tuples)
+
+ def __len__(self) -> int:
+ return len(self.tuples)
+
+ def __getitem__(self, key) -> Any:
+ return self.tuples[key]
+
+class StringList(PropertyValues):
+ """A StringList is a list of null-terminated strings
+
+ The most common use of a StringList in Devicetree is to describe the `compatible` property.
+ """
+ def __init__(self, strings: List[str]):
+ """Create a StringList object"""
+ PropertyValues.__init__(self, strings)
+
+ def __repr__(self) -> str:
+ return "<StringList " + self.values.__repr__() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the list of strings in Devicetree Source format"""
+ return ", ".join(wrapStrings(self.values))
+
+class OneString(PropertyValues):
+ def __init__(self, string: str):
+ PropertyValues.__init__(self, string)
+
+ def __repr__(self) -> str:
+ return self.values.__repr__()
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ return super().to_dts(formatHex)
+
+class Property:
+ """A Property is a key-value pair for a Devicetree Node
+
+ Properties are used to describe Nodes in the tree. There are many common properties, like
+
+ - compatible
+ - reg
+ - reg-names
+ - ranges
+ - interrupt-controller
+ - interrupts
+ - interrupt-parent
+ - clocks
+ - status
+
+ Which might commonly describe many or all nodes in a tree, and there are device, vendor,
+ operating system, runtime-specific properties.
+
+ Properties can possess no value, conveing meaning solely by their presence:
+
+ interrupt-controller;
+
+ Properties can also possess values such as an array of cells, a list of strings, etc.
+
+ reg = <0x10013000 0x1000>;
+ compatible = "sifive,rocket0", "riscv";
+
+ And properties can posses arbitrarily complex values, such as the following from the
+ Devicetree specification:
+
+ example = <0xf00f0000 19>, "a strange property format";
+ """
+ def __init__(self, name: str, values: PropertyValues):
+ """Create a Property object"""
+ self.name = name
+ self.values = values
+
+ def __repr__(self) -> str:
+ return "<Property %s>" % self.name
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ @staticmethod
+ def from_dts(dts: str) -> 'Property':
+ """Parse a file and return a Devicetree object"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from pydevicetree.source import parseProperty
+ return parseProperty(dts)
+
+ def to_dts(self, level: int = 0) -> str:
+ """Format the Property assignment in Devicetree Source format"""
+ if self.name in ["reg", "ranges"]:
+ value = self.values.to_dts(formatHex=True)
+ else:
+ value = self.values.to_dts(formatHex=False)
+
+ if value != "":
+ return formatLevel(level, "%s = %s;\n" % (self.name, value))
+ if self.name == "ifdef":
+ return ""
+ return formatLevel(level, "%s;\n" % self.name)
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py
new file mode 100644
index 0000000..54b2d28
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import Union, Iterator
+
+class Label:
+ """A Label is a unique identifier for a Node
+
+ For example, the following node has the label "uart0":
+
+ uart0: uart@10013000 {
+ ...
+ };
+ """
+ def __init__(self, name: str):
+ """Create a Label"""
+ self.name = name
+
+ def __repr__(self) -> str:
+ return "<Label " + self.name + ">"
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Label):
+ return self.name == other.name
+ if isinstance(other, str):
+ return self.name == other
+ return False
+
+ def to_dts(self) -> str:
+ """Format the label in Devicetree Source format"""
+ return self.name + ":"
+
+class Path:
+ """A Path uniquely identifies a Node by its parents and (optionally) unit address"""
+ def __init__(self, path: str):
+ """Create a path out of a string"""
+ self.path = path
+
+ def to_dts(self) -> str:
+ """Format the Path in Devicetree Source format"""
+ return self.path
+
+ def __repr__(self) -> str:
+ return "<Path " + self.to_dts() + ">"
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Path):
+ return self.to_dts() == other.to_dts()
+ if isinstance(other, str):
+ return self.to_dts() == other
+ return False
+
+ def __iter__(self) -> Iterator[str]:
+ return iter(self.path.split("/"))
+
+ def replace(self, old: str, new: str) -> 'Path':
+ """Replace any elements of the path which match 'old' with a new element 'new'"""
+ return Path(self.path.replace(old, new))
+
+class Reference:
+ """A Reference is a Devicetree construct which points to a Node in the tree
+
+ The following are types of references:
+
+ - A reference to a label:
+
+ &my-label;
+
+ - A reference to a node by path:
+
+ &{/path/to/node@deadbeef}
+
+ This is the parent class for both types of references, LabelReference and PathReference
+ """
+ # pylint: disable=no-self-use
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the Reference in Devicetree Source format"""
+ return ""
+
+class LabelReference(Reference):
+ """A LabelReference is a reference to a Node by label"""
+ def __init__(self, label: Union[Label, str]):
+ """Create a LabelReference from a Label or string"""
+ if isinstance(label, Label):
+ self.label = label
+ elif isinstance(label, str):
+ self.label = Label(label)
+
+ def __repr__(self) -> str:
+ return "<LabelReference " + self.to_dts() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the LabelReference in Devicetree Source format"""
+ return "&" + self.label.name
+
+class PathReference(Reference):
+ """A PathReference is a reference to a Node by path"""
+ def __init__(self, path: Union[Path, str]):
+ """Create a PathReference from a Path or string"""
+ if isinstance(path, Path):
+ self.path = path
+ elif isinstance(path, str):
+ self.path = Path(path)
+
+ def __repr__(self) -> str:
+ return "<PathReference " + self.to_dts() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the PathReference in Devicetree Source format"""
+ return "&{" + self.path.to_dts() + "}"
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py
new file mode 100644
index 0000000..96768b3
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from cot_dt2c.pydevicetree.source.parser import parseTree, parseNode, parseProperty
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py
new file mode 100644
index 0000000..fb165e1
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+import os
+import sys
+
+import pyparsing as p # type: ignore
+
+ENV_CACHE_OPTION = "PYDEVICETREE_CACHE_SIZE_BOUND"
+
+cache_bound = None
+if ENV_CACHE_OPTION in os.environ:
+ option = os.environ[ENV_CACHE_OPTION]
+ if option != "None":
+ try:
+ cache_bound = int(option)
+ except ValueError:
+ print("%s requires a valid integer" % ENV_CACHE_OPTION, file=sys.stderr)
+p.ParserElement.enablePackrat(cache_bound)
+
+node_name = p.Word(p.alphanums + ",.-+_") ^ p.Literal("/")
+integer = p.pyparsing_common.integer ^ (p.Literal("0x").suppress() + p.pyparsing_common.hex_integer)
+unit_address = p.pyparsing_common.hex_integer
+unit_addresses = p.delimitedList(unit_address("address"), delim=",")
+node_handle = node_name("node_name") + p.Optional(p.Literal("@") + unit_addresses)
+property_name = p.Word(p.alphanums + ",.-_+?#")
+label = p.Word(p.alphanums + "_").setResultsName("label")
+label_creation = p.Combine(label + p.Literal(":"))
+string = p.QuotedString(quoteChar='"')
+stringlist = p.delimitedList(string)
+node_path = p.Combine(p.Literal("/") + \
+ p.delimitedList(node_handle, delim="/", combine=True)).setResultsName("path")
+path_reference = p.Literal("&{").suppress() + node_path + p.Literal("}").suppress()
+label_reference = p.Literal("&").suppress() + label
+label_raw = p.Word(p.alphanums + "_")
+reference = path_reference ^ label_reference ^ label_raw
+include_directive = p.Literal("/include/") + p.QuotedString(quoteChar='"')
+generic_directive = p.QuotedString(quoteChar="/", unquoteResults=False) + \
+ p.Optional(string ^ property_name ^ node_name ^ reference ^ (integer * 2)) + \
+ p.Literal(";").suppress()
+directive = include_directive ^ generic_directive
+
+operator = p.oneOf("~ ! * / + - << >> < <= > >= == != & ^ | && ||")
+arith_expr = p.Forward()
+ternary_element = arith_expr ^ integer
+ternary_expr = ternary_element + p.Literal("?") + ternary_element + p.Literal(":") + ternary_element
+arith_expr = p.nestedExpr(content=(p.OneOrMore(operator ^ integer) ^ ternary_expr))
+arth_str = p.Forward()
+arith_str_expr = p.nestedExpr(content=(p.OneOrMore(operator ^ integer ^ label_raw ^ p.Literal(",")) ^ ternary_expr))
+
+label_list = p.OneOrMore(p.Combine(label + p.Literal("\n")))
+
+cell_array = p.Literal("<").suppress() + \
+ p.ZeroOrMore(integer ^ arith_expr ^ arith_str_expr ^ label_list ^ string ^ reference ^ label_creation.suppress()) + \
+ p.Literal(">").suppress()
+bytestring = p.Literal("[").suppress() + \
+ (p.OneOrMore(p.Word(p.hexnums, exact=2) ^ label_creation.suppress())) + \
+ p.Literal("]").suppress()
+property_values = p.Forward()
+property_values = p.delimitedList(property_values ^ cell_array ^ bytestring ^ stringlist ^ \
+ reference ^ label_raw)
+property_assignment = property_name("property_name") + p.Optional(p.Literal("=").suppress() + \
+ (property_values)).setResultsName("value") + p.Optional(p.Literal(";").suppress())
+
+ifdef_label = p.ZeroOrMore(p.Word(p.alphanums + " _|//*=/(/)"))
+ifdef_define = p.Combine(p.Keyword("#if") + ifdef_label)
+ifdef_end = p.Combine(p.Keyword("#endif") + ifdef_label)
+ifdef_define_values = p.Forward()
+ifdef_define_values = p.ZeroOrMore(ifdef_define)
+ifdef_end_values = p.Forward()
+ifdef_end_values = p.ZeroOrMore(ifdef_end)
+
+node_opener = ifdef_define_values + p.Optional(label_creation) + node_handle + p.Literal("{").suppress()
+node_reference_opener = reference + p.Literal("{").suppress()
+node_closer = p.Literal("}").suppress() + p.Literal(";").suppress() + ifdef_end_values
+node_definition = p.Forward()
+# pylint: disable=expression-not-assigned
+node_definition << (node_opener ^ node_reference_opener) + \
+ p.ZeroOrMore(property_assignment ^ directive ^ node_definition ^ ifdef_define ^ ifdef_end) + \
+ node_closer
+
+devicetree = p.ZeroOrMore(directive ^ node_definition)
+
+devicetree.ignore(p.cStyleComment)
+devicetree.ignore("//" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#include" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#define" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#else" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#error" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#ifndef" + p.SkipTo(p.lineEnd))
+
+if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ devicetree.parseFile(sys.argv[1]).pprint()
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py
new file mode 100644
index 0000000..0692482
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from itertools import chain
+
+from cot_dt2c.pydevicetree.source import grammar
+from cot_dt2c.pydevicetree.ast import *
+
+ifdef_stack = []
+
+def transformNode(string, location, tokens):
+ """Transforms a ParseResult into a Node"""
+ properties = [e for e in tokens.asList() if isinstance(e, Property)]
+ directives = [e for e in tokens.asList() if isinstance(e, Directive)]
+ children = [e for e in tokens.asList() if isinstance(e, Node)]
+
+ if isinstance(tokens[0], Reference):
+ return NodeReference(tokens[0], properties=properties,
+ directives=directives, children=children)
+ return Node(tokens.node_name, tokens.label, tokens.address, properties=properties,
+ directives=directives, children=children)
+
+def transformPropertyAssignment(string, location, tokens):
+ """Transforms a ParseResult into a Property"""
+ for v in tokens.value:
+ if isinstance(v, PropertyValues):
+ return Property(tokens.property_name, v)
+ if isinstance(v, CellArray):
+ return Property(tokens.property_name, v)
+ if isinstance(v, StringList):
+ return Property(tokens.property_name, v)
+ if isinstance(v, Reference):
+ return Property(tokens.property_name, v)
+
+ return Property(tokens.property_name, PropertyValues([]))
+
+def transformDirective(string, location, tokens):
+ """Transforms a ParseResult into a Directive"""
+ if len(tokens.asList()) > 1:
+ return Directive(tokens[0], tokens[1])
+ return Directive(tokens[0])
+
+def evaluateArithExpr(string, location, tokens):
+ """Evaluates a ParseResult as a python expression"""
+ flat_tokens = list(chain.from_iterable(tokens.asList()))
+ expr = " ".join(str(t) for t in flat_tokens)
+ # pylint: disable=eval-used
+ return eval(expr)
+
+def transformTernary(string, location, tokens):
+ """Evaluates a ParseResult as a ternary expression"""
+ # pylint: disable=eval-used
+ return eval(str(tokens[2]) +" if " + str(tokens[0]) + " else " + str(tokens[4]))
+
+def transformPropertyValues(string, location, tokens):
+ """Transforms a ParseResult into a PropertyValues"""
+ if len(tokens.asList()) == 1:
+ return tokens.asList()[0]
+ return PropertyValues(tokens.asList())
+
+def transformStringList(string, location, tokens):
+ """Transforms a ParseResult into a StringList"""
+ return StringList(tokens.asList())
+
+def transformString(string, location, token):
+ return OneString(token)
+
+def transformIfdefMacro(string, location, tokens):
+ tokenlist = tokens.asList()
+ for t in tokenlist:
+ ifdef_stack.append(t)
+ return Property("ifdef", PropertyValues(ifdef_stack.copy()))
+
+def transformIfdefEnd(string, location, tokens):
+ tokenlist = tokens.asList()
+ for t in tokenlist:
+ ifdef_stack.pop()
+
+def transformIfdef(string, location, tokens):
+ return Property("ifdef", PropertyValues(tokens))
+
+def evaluateStrArithExpr(string, location, tokens):
+ """Evaluates a ParseResult as a python expression"""
+ flat_tokens = list(chain.from_iterable(tokens.asList()))
+ for i, t in enumerate(flat_tokens):
+ if isinstance(t, int):
+ flat_tokens[i] = "(" + str(t) + ")"
+ expr = " ".join(str(t) for t in flat_tokens)
+ # pylint: disable=eval-used
+ return expr
+
+def transformBytestring(string, location, tokens):
+ """Transforms a ParseResult into a Bytestring"""
+ inttokens = []
+ for t in tokens.asList():
+ if all(c in "0123456789abcdefABCDEF" for c in t):
+ inttokens.append(int(t, base=16))
+ return Bytestring(inttokens)
+
+def transformCellArray(string, location, tokens):
+ """Transforms a ParseResult into a CellArray"""
+ return CellArray(tokens.asList())
+
+def transformLabel(string, location, tokens):
+ """Transforms a ParseResult into a Label"""
+ return Label(tokens.label)
+
+def transformPath(string, location, tokens):
+ """Transforms a ParseResult into a Path"""
+ path = ""
+ for handle in tokens.path[0].split("/"):
+ if "@" in handle:
+ node, address = handle.split("@")
+ path += "/%s@%x" % (node, int(address))
+ elif handle != "":
+ path += "/" + handle
+ return Path(path)
+
+def transformPathReference(string, location, tokens):
+ """Transforms a ParseResult into a PathReference"""
+ return PathReference(tokens[0])
+
+def transformLabelReference(string, location, tokens):
+ """Transforms a ParseResult into a LabelReference"""
+ return LabelReference(tokens[0])
+
+def transformReference(string, location, tokens):
+ """Transforms a ParseResult into a Reference"""
+ if isinstance(tokens[0], Reference):
+ return tokens[0]
+ return None
+
+grammar.label.setParseAction(transformLabel)
+grammar.node_path.setParseAction(transformPath)
+grammar.path_reference.setParseAction(transformPathReference)
+grammar.label_reference.setParseAction(transformLabelReference)
+grammar.reference.setParseAction(transformReference)
+grammar.node_definition.setParseAction(transformNode)
+grammar.property_assignment.setParseAction(transformPropertyAssignment)
+grammar.directive.setParseAction(transformDirective)
+grammar.arith_expr.setParseAction(evaluateArithExpr)
+grammar.ternary_expr.setParseAction(transformTernary)
+grammar.stringlist.setParseAction(transformStringList)
+grammar.bytestring.setParseAction(transformBytestring)
+grammar.cell_array.setParseAction(transformCellArray)
+grammar.property_values.setParseAction(transformPropertyValues)
+grammar.label_raw.setParseAction(transformString)
+grammar.ifdef_define_values.setParseAction(transformIfdefMacro)
+grammar.ifdef_end_values.setParseAction(transformIfdefEnd)
+grammar.arith_str_expr.setParseAction(transformPropertyValues)
+
+def printTree(tree, level=0):
+ """Helper function to print a bunch of elements as a tree"""
+ def printlevel(level, s):
+ print(" " * level + s)
+
+ for item in tree:
+ if isinstance(item, Node):
+ if item.address:
+ printlevel(level, "Node %s@%x" % (item.name, item.address))
+ else:
+ printlevel(level, "Node %s" % item.name)
+
+ if item.label:
+ printlevel(level, " Label: %s" % item.label)
+
+ if item.parent:
+ printlevel(level, " Parent: %s" % item.parent)
+
+ printTree(item.properties, level=(level + 1))
+
+ printTree(item.children, level=(level + 1))
+ elif isinstance(item, Property):
+ if item.values:
+ printlevel(level, "Property %s: %s" % (item.name, item.values))
+ else:
+ printlevel(level, "Property %s" % item.name)
+ elif isinstance(item, Directive):
+ if item.options:
+ printlevel(level, "Directive %s: %s" % (item.directive, item.options))
+ else:
+ printlevel(level, "Directive %s" % item.directive)
+
+def parentNodes(tree, parent=None):
+ """Walks a tree and sets Nodes' parent field to point at their parent"""
+ for item in tree:
+ if isinstance(item, Node):
+ item.parent = parent
+ parentNodes(item.children, item)
+
+def recurseIncludeFiles(elements, pwd):
+ """Recursively follows and parses /include/ directives an a tree"""
+ for e in elements:
+ if isinstance(e, Directive):
+ if e.directive == "/include/":
+ # Prefix with current directory if path is not absolute
+ if e.option[0] != '/':
+ e.option = pwd + e.option
+
+ with open(e.option, 'r') as f:
+ contents = f.read()
+
+ elements += parseElements(contents)
+
+ del elements[elements.asList().index(e)]
+
+def parseElements(dts, pwd="", followIncludes=False):
+ """Parses a string into a list of elements"""
+ elements = grammar.devicetree.parseString(dts, parseAll=True)
+ parentNodes(elements)
+ if followIncludes:
+ recurseIncludeFiles(elements, pwd)
+ return elements
+
+def parseTree(dts, pwd="", followIncludes=False):
+ """Parses a string into a full Devicetree"""
+ return Devicetree(parseElements(dts, pwd, followIncludes))
+
+def parseNode(dts):
+ """Parses a string into a Devictreee Node"""
+ return grammar.node_definition.parseString(dts, parseAll=True)[0]
+
+def parseProperty(dts):
+ """Parses a string into a Devicetree Property"""
+ return grammar.property_assignment.parseString(dts, parseAll=True)[0]
+
+if __name__ == "__main__":
+ import sys
+ if len(sys.argv) > 1:
+ with open(sys.argv[1], 'r') as f:
+ dts = f.read()
+ tree = parseTree(dts)
+ printTree(tree)
+ print(tree)
+ else:
+ print("Please pass the devicetree source file as an argument")
+ sys.exit(1)
diff --git a/tools/cot_dt2c/pyproject.toml b/tools/cot_dt2c/pyproject.toml
new file mode 100644
index 0000000..d383924
--- /dev/null
+++ b/tools/cot_dt2c/pyproject.toml
@@ -0,0 +1,60 @@
+# Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/
+[build-system]
+requires = ["poetry_core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry]
+name = "cot_dt2c"
+version = "0.1.0"
+description = "CoT-dt2c Tool is a python script to convert CoT DT file into corresponding C file"
+authors = ["Arm Ltd <tf-a@lists.trustedfirmware.org>"]
+license = "BSD-3"
+repository = "https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/"
+homepage = "https://trustedfirmware-a.readthedocs.io/en/latest/index.html"
+
+# Pypi classifiers: https://pypi.org/classifiers/
+classifiers = [
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Operating System :: OS Independent",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "License :: OSI Approved :: BSD License",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+]
+
+
+[tool.poetry.dependencies]
+python = "^3.8"
+click = "^8.1.7"
+pyparsing = "^2.4.7"
+plotly = "^5.23.0"
+pandas = "^2.2.2"
+igraph = "^0.11.6"
+
+[tool.poetry.dev-dependencies]
+mypy = "^0.910"
+pytest = "^6.2.5"
+pyparsing = "^2.4.7"
+plotly = "^5.23.0"
+pandas = "^2.2.2"
+igraph = "^0.11.6"
+
+[tool.mypy]
+# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
+python_version = 3.8
+pretty = true
+show_traceback = true
+color_output = true
+
+[tool.coverage.run]
+source = ["tests"]
+
+[coverage.paths]
+source = "cot_dt2c"
+
+[tool.poetry.scripts]
+# Entry points for the package https://python-poetry.org/docs/pyproject/#scripts
+# "cot-dt2c" = "cot_dt2c.__main__:cli"
+"cot-dt2c" = "cot_dt2c.__main__:cli"
diff --git a/tools/cot_dt2c/requirements.txt b/tools/cot_dt2c/requirements.txt
new file mode 100644
index 0000000..246b81d
--- /dev/null
+++ b/tools/cot_dt2c/requirements.txt
@@ -0,0 +1,6 @@
+mypy
+pylint
+pyparsing
+igraph
+pandas
+plotly
diff --git a/tools/cot_dt2c/tests/test.dtsi b/tools/cot_dt2c/tests/test.dtsi
new file mode 100644
index 0000000..ee744e6
--- /dev/null
+++ b/tools/cot_dt2c/tests/test.dtsi
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a valid CoT DT file
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+#if defined(test)
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+ };
+#endif
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test2.dtsi b/tools/cot_dt2c/tests/test2.dtsi
new file mode 100644
index 0000000..c4dbf83
--- /dev/null
+++ b/tools/cot_dt2c/tests/test2.dtsi
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a valid CoT DT file
+ *
+ */
+
+#if test
+#include <example/example.h>
+#include <example/example/example.h>
+#endif
+
+cot
+{
+ manifests
+ {
+ compatible = "arm, cert-descs";
+#if defined (test)
+ example_cert: example_cert
+ {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+#endif
+ };
+
+ images
+ {
+ compatible = "arm, img-descs";
+
+ example
+ {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters
+{
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr
+ {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys
+{
+ example_pk: example_pk
+ {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_bracket.dtsi b/tools/cot_dt2c/tests/test_invalid_bracket.dtsi
new file mode 100644
index 0000000..ec5f9c7
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_bracket.dtsi
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there is
+ * unmatching bracket
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_ifdef.dtsi b/tools/cot_dt2c/tests/test_invalid_ifdef.dtsi
new file mode 100644
index 0000000..5bc6bb9
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_ifdef.dtsi
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there is
+ * unmatching ifdef macro
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+#if defined(test)
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_ifdef2.dtsi b/tools/cot_dt2c/tests/test_invalid_ifdef2.dtsi
new file mode 100644
index 0000000..c915168
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_ifdef2.dtsi
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there is
+ * unmatching ifdef macro
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+#if defined(test)
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+#endif
+#endif
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi
new file mode 100644
index 0000000..9c0a5f2
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that missing mandantory attributes
+ *
+ */
+
+#include <tools_share/cca_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <common/nv_cntr_ids.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ 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 {
+ };
+ fw_config_hash: fw_config_hash {
+ oid = FW_CONFIG_HASH_OID;
+ };
+ 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;
+ };
+ rmm_hash: rmm_hash {
+ oid = RMM_HASH_OID;
+ };
+ };
+
+ core_swd_key_cert: core_swd_key_cert {
+ root-certificate;
+ image-id = <CORE_SWD_KEY_CERT_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ core_swd_pk: core_swd_pk {
+ oid = CORE_SWD_PK_OID;
+ };
+ };
+
+ trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+ image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+ parent = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ tos_fw_hash: tos_fw_hash {
+ oid = TRUSTED_OS_FW_HASH_OID;
+ };
+ tos_fw_config_hash: tos_fw_config_hash {
+ oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ root-certificate;
+ image-id = <PLAT_KEY_CERT_ID>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = PLAT_PK_OID;
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&plat_key_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ 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;
+ };
+ };
+
+ plat_sp_content_cert: plat_sp_content_cert {
+ parent = <&plat_key_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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>;
+ hash = <&hw_config_hash>;
+ };
+
+ bl31_image {
+ image-id = <BL31_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <SOC_FW_CONFIG_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ rmm_image {
+ image-id = <RMM_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&rmm_hash>;
+ };
+
+ bl32_image {
+ image-id = <BL32_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_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 {
+ 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 = <&plat_sp_content_cert>;
+ hash = <&sp_pkg5_hash>;
+ };
+
+ sp_pkg6 {
+ image-id = <SP_PKG6_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg6_hash>;
+ };
+
+ sp_pkg7 {
+ image-id = <SP_PKG7_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg7_hash>;
+ };
+
+ sp_pkg8 {
+ image-id = <SP_PKG8_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg8_hash>;
+ };
+#endif
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <NON_TRUSTED_NV_CTR_ID>;
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = SWD_ROT_PK_OID;
+ };
+ prot_pk: prot_pk {
+ oid = PROT_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_attribute2.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_attribute2.dtsi
new file mode 100644
index 0000000..01b2597
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_attribute2.dtsi
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that points to invalid parent
+ *
+ */
+
+#include <tools_share/cca_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <common/nv_cntr_ids.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ image-id =<CCA_CONTENT_CERT_ID>;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ 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;
+ };
+ 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;
+ };
+ rmm_hash: rmm_hash {
+ oid = RMM_HASH_OID;
+ };
+ };
+
+ core_swd_key_cert: core_swd_key_cert {
+ root-certificate;
+ image-id = <CORE_SWD_KEY_CERT_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ core_swd_pk: core_swd_pk {
+ oid = CORE_SWD_PK_OID;
+ };
+ };
+
+ trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+ image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+ parent = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ tos_fw_hash: tos_fw_hash {
+ oid = TRUSTED_OS_FW_HASH_OID;
+ };
+ tos_fw_config_hash: tos_fw_config_hash {
+ oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ root-certificate;
+ image-id = <PLAT_KEY_CERT_ID>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = PLAT_PK_OID;
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&cca_content_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&cca_content_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ 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;
+ };
+ };
+
+ plat_sp_content_cert: plat_sp_content_cert {
+ image-id = <PLAT_SP_CONTENT_CERT_ID>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&cca_content_cert>;
+ hash = <&hw_config_hash>;
+ };
+
+ bl31_image {
+ image-id = <BL31_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <SOC_FW_CONFIG_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ rmm_image {
+ image-id = <RMM_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&rmm_hash>;
+ };
+
+ bl32_image {
+ image-id = <BL32_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_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>;
+ hash = <&nt_fw_config_hash>;
+ };
+
+#if defined(SPD_spmd)
+ sp_pkg1 {
+ image-id = <SP_PKG1_ID>;
+ 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 = <&plat_sp_content_cert>;
+ hash = <&sp_pkg5_hash>;
+ };
+
+ sp_pkg6 {
+ image-id = <SP_PKG6_ID>;
+ parent = <&wrong_parent>;
+ hash = <&sp_pkg6_hash>;
+ };
+
+ sp_pkg7 {
+ image-id = <SP_PKG7_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg7_hash>;
+ };
+
+ sp_pkg8 {
+ image-id = <SP_PKG8_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg8_hash>;
+ };
+#endif
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <NON_TRUSTED_NV_CTR_ID>;
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = SWD_ROT_PK_OID;
+ };
+ prot_pk: prot_pk {
+ oid = PROT_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi
new file mode 100644
index 0000000..5958f5d
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that missing definition of
+ * nv counters
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_root.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_root.dtsi
new file mode 100644
index 0000000..465a4c6
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_root.dtsi
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that missing root certificate
+ *
+ */
+
+#include <tools_share/cca_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <common/nv_cntr_ids.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ core_swd_key_cert: core_swd_key_cert {
+ image-id = <CORE_SWD_KEY_CERT_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ core_swd_pk: core_swd_pk {
+ oid = CORE_SWD_PK_OID;
+ };
+ };
+
+ trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+ image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+ parent = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ tos_fw_hash: tos_fw_hash {
+ oid = TRUSTED_OS_FW_HASH_OID;
+ };
+ tos_fw_config_hash: tos_fw_config_hash {
+ oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ image-id = <PLAT_KEY_CERT_ID>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = PLAT_PK_OID;
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&plat_key_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ 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;
+ };
+ };
+
+ plat_sp_content_cert: plat_sp_content_cert {
+ image-id = <PLAT_SP_CONTENT_CERT_ID>;
+ parent = <&plat_key_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&cca_content_cert>;
+ hash = <&hw_config_hash>;
+ };
+
+ bl31_image {
+ image-id = <BL31_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <SOC_FW_CONFIG_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ rmm_image {
+ image-id = <RMM_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&rmm_hash>;
+ };
+
+ bl32_image {
+ image-id = <BL32_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_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 = <&plat_sp_content_cert>;
+ hash = <&sp_pkg5_hash>;
+ };
+
+ sp_pkg6 {
+ image-id = <SP_PKG6_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg6_hash>;
+ };
+
+ sp_pkg7 {
+ image-id = <SP_PKG7_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg7_hash>;
+ };
+
+ sp_pkg8 {
+ image-id = <SP_PKG8_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg8_hash>;
+ };
+#endif
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <NON_TRUSTED_NV_CTR_ID>;
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = SWD_ROT_PK_OID;
+ };
+ prot_pk: prot_pk {
+ oid = PROT_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi b/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi
new file mode 100644
index 0000000..b761beb
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that points to invalid parent
+ *
+ */
+
+#include <tools_share/cca_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <common/nv_cntr_ids.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ image-id =<CCA_CONTENT_CERT_ID>;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ 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;
+ };
+ 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;
+ };
+ rmm_hash: rmm_hash {
+ oid = RMM_HASH_OID;
+ };
+ };
+
+ core_swd_key_cert: core_swd_key_cert {
+ root-certificate;
+ image-id = <CORE_SWD_KEY_CERT_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ core_swd_pk: core_swd_pk {
+ oid = CORE_SWD_PK_OID;
+ };
+ };
+
+ trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+ image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+ parent = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ tos_fw_hash: tos_fw_hash {
+ oid = TRUSTED_OS_FW_HASH_OID;
+ };
+ tos_fw_config_hash: tos_fw_config_hash {
+ oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ root-certificate;
+ image-id = <PLAT_KEY_CERT_ID>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = PLAT_PK_OID;
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&wrong_parent>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&wrong_parent>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ 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;
+ };
+ };
+
+ plat_sp_content_cert: plat_sp_content_cert {
+ image-id = <PLAT_SP_CONTENT_CERT_ID>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ 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 = <&cca_content_cert>;
+ hash = <&hw_config_hash>;
+ };
+
+ bl31_image {
+ image-id = <BL31_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <SOC_FW_CONFIG_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ rmm_image {
+ image-id = <RMM_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&rmm_hash>;
+ };
+
+ bl32_image {
+ image-id = <BL32_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_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>;
+ hash = <&nt_fw_config_hash>;
+ };
+
+#if defined(SPD_spmd)
+ sp_pkg1 {
+ image-id = <SP_PKG1_ID>;
+ 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 = <&plat_sp_content_cert>;
+ hash = <&sp_pkg5_hash>;
+ };
+
+ sp_pkg6 {
+ image-id = <SP_PKG6_ID>;
+ parent = <&wrong_parent>;
+ hash = <&sp_pkg6_hash>;
+ };
+
+ sp_pkg7 {
+ image-id = <SP_PKG7_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg7_hash>;
+ };
+
+ sp_pkg8 {
+ image-id = <SP_PKG8_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg8_hash>;
+ };
+#endif
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <NON_TRUSTED_NV_CTR_ID>;
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = SWD_ROT_PK_OID;
+ };
+ prot_pk: prot_pk {
+ oid = PROT_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_util.py b/tools/cot_dt2c/tests/test_util.py
new file mode 100644
index 0000000..b8e44d4
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_util.py
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import os
+import sys
+
+from cot_dt2c.cli import *
+from click.testing import CliRunner
+
+def get_script_path():
+ return os.path.dirname(os.path.realpath(sys.argv[0]))
+
+def test_convert():
+ runner = CliRunner()
+ test_file = get_script_path() + "/test.dtsi"
+ test_output = get_script_path() + "/test.c"
+
+ result = runner.invoke(convert_to_c, [test_file, test_output])
+ try:
+ assert result.output == ""
+ except:
+ print("test convert fail")
+
+ try:
+ os.remove(test_output)
+ except OSError:
+ pass
+
+if __name__=="__main__":
+ test_convert()
diff --git a/tools/renesas/rcar_layout_create/makefile b/tools/renesas/rcar_layout_create/makefile
index 115ca5c..7a64b19 100644
--- a/tools/renesas/rcar_layout_create/makefile
+++ b/tools/renesas/rcar_layout_create/makefile
@@ -7,6 +7,7 @@
toolchains := aarch64
+include ../../../make_helpers/build-rules.mk
include ../../../make_helpers/common.mk
include ../../../make_helpers/toolchain.mk
@@ -94,29 +95,29 @@
# Linker
###################################################
-$(FILE_NAME_SA0).srec: $(OUTPUT_FILE_SA0)
+$(FILE_NAME_SA0).srec: $(OUTPUT_FILE_SA0) | $$(@D)/
$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
-$(FILE_NAME_SA0).bin: $(OUTPUT_FILE_SA0)
+$(FILE_NAME_SA0).bin: $(OUTPUT_FILE_SA0) | $$(@D)/
$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
-$(OUTPUT_FILE_SA0): $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0)
+$(OUTPUT_FILE_SA0): $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) | $$(@D)/
$(aarch64-ld) $(OBJ_FILE_SA0) -nostdlib -T $(MEMORY_DEF_SA0) -o $(OUTPUT_FILE_SA0) -Wl,-Map $(FILE_NAME_SA0).map
-$(FILE_NAME_SA6).srec: $(OUTPUT_FILE_SA6)
+$(FILE_NAME_SA6).srec: $(OUTPUT_FILE_SA6) | $$(@D)/
$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
-$(FILE_NAME_SA6).bin: $(OUTPUT_FILE_SA6)
+$(FILE_NAME_SA6).bin: $(OUTPUT_FILE_SA6) | $$(@D)/
$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
-$(OUTPUT_FILE_SA6): $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6)
+$(OUTPUT_FILE_SA6): $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) | $$(@D)/
$(aarch64-ld) $(OBJ_FILE_SA6) -nostdlib -T $(MEMORY_DEF_SA6) -o $(OUTPUT_FILE_SA6) -Wl,-Map $(FILE_NAME_SA6).map
###################################################
# Compile
###################################################
-%.o: %.c
+%.o: %.c | $$(@D)/
$(aarch64-cc) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
.PHONY: clean
diff --git a/tools/renesas/rzg_layout_create/makefile b/tools/renesas/rzg_layout_create/makefile
index 1e8f7ff..936420d 100644
--- a/tools/renesas/rzg_layout_create/makefile
+++ b/tools/renesas/rzg_layout_create/makefile
@@ -7,6 +7,7 @@
toolchains := aarch64
+include ../../../make_helpers/build-rules.mk
include ../../../make_helpers/common.mk
include ../../../make_helpers/toolchain.mk
@@ -91,29 +92,29 @@
# Linker
###################################################
-$(FILE_NAME_SA0).srec: $(OUTPUT_FILE_SA0)
+$(FILE_NAME_SA0).srec: $(OUTPUT_FILE_SA0) | $$(@D)/
$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
-$(FILE_NAME_SA0).bin: $(OUTPUT_FILE_SA0)
+$(FILE_NAME_SA0).bin: $(OUTPUT_FILE_SA0) | $$(@D)/
$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
-$(OUTPUT_FILE_SA0): $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0)
+$(OUTPUT_FILE_SA0): $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) | $$(@D)/
$(aarch64-ld) $(OBJ_FILE_SA0) -nostdlib -T $(MEMORY_DEF_SA0) -o $(OUTPUT_FILE_SA0) -Wl,-Map $(FILE_NAME_SA0).map
-$(FILE_NAME_SA6).srec: $(OUTPUT_FILE_SA6)
+$(FILE_NAME_SA6).srec: $(OUTPUT_FILE_SA6) | $$(@D)/
$(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
-$(FILE_NAME_SA6).bin: $(OUTPUT_FILE_SA6)
+$(FILE_NAME_SA6).bin: $(OUTPUT_FILE_SA6) | $$(@D)/
$(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
-$(OUTPUT_FILE_SA6): $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6)
+$(OUTPUT_FILE_SA6): $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) | $$(@D)/
$(aarch64-ld) $(OBJ_FILE_SA6) -nostdlib -T $(MEMORY_DEF_SA6) -o $(OUTPUT_FILE_SA6) -Wl,-Map $(FILE_NAME_SA6).map
###################################################
# Compile
###################################################
-%.o: %.c
+%.o: %.c | $$(@D)/
$(aarch64-cc) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
.PHONY: clean
diff --git a/tools/tlc/Makefile b/tools/tlc/Makefile
new file mode 100644
index 0000000..e50b9dd
--- /dev/null
+++ b/tools/tlc/Makefile
@@ -0,0 +1,109 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+##* Variables
+SHELL := /usr/bin/env bash
+PYTHON := python
+PYTHONPATH := `pwd`
+
+#* Docker variables
+IMAGE := tlc
+VERSION := latest
+
+#* Installation
+.PHONY: dist
+dist: clean
+ poetry build
+
+.PHONY: dev-install
+dev-install:
+ poetry lock -n --no-update && poetry export --without-hashes > requirements.txt
+ poetry install -n
+ -poetry run mypy --install-types --non-interactive ./
+
+.PHONY: install
+install: dist
+ pip install dist/*.whl
+
+.PHONY: pre-commit-install
+pre-commit-install:
+ poetry run pre-commit install
+
+#* Formatters
+.PHONY: codestyle
+codestyle:
+ poetry run pyupgrade --exit-zero-even-if-changed --py38-plus **/*.py
+ poetry run isort --settings-path pyproject.toml ./
+ poetry run black --config pyproject.toml ./
+
+.PHONY: formatting
+formatting: codestyle
+
+#* Linting
+.PHONY: test
+test:
+ PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml --cov-report=html --cov=tlc tests/
+ poetry run coverage-badge -o assets/images/coverage.svg -f
+
+.PHONY: check-codestyle
+check-codestyle:
+ poetry run isort --diff --check-only --settings-path pyproject.toml ./
+ poetry run black --diff --check --config pyproject.toml ./
+ poetry run darglint --verbosity 2 tlc tests
+
+.PHONY: mypy
+mypy:
+ poetry run mypy --config-file pyproject.toml ./
+
+.PHONY: check-safety
+check-safety:
+ poetry check
+ poetry run safety check --full-report
+ poetry run bandit -ll --recursive tlc tests
+
+.PHONY: lint
+lint: test check-codestyle mypy check-safety
+
+.PHONY: update-dev-deps
+update-dev-deps:
+ poetry add -D bandit@latest darglint@latest "isort[colors]@latest" mypy@latest pre-commit@latest pydocstyle@latest pylint@latest pytest@latest pyupgrade@latest safety@latest coverage@latest coverage-badge@latest pytest-html@latest pytest-cov@latest
+ poetry add -D --allow-prereleases black@latest
+
+#* Docker
+.PHONY: docker-build docker-remove
+docker-build:
+ @echo Building docker $(IMAGE):$(VERSION) ...
+ docker build \
+ -t $(IMAGE):$(VERSION) . \
+ -f ./docker/Dockerfile --no-cache
+
+docker-remove:
+ @echo Removing docker $(IMAGE):$(VERSION) ...
+ docker rmi -f $(IMAGE):$(VERSION)
+
+
+#* Cleaning
+.PHONY: clean .clean-build clean-pyc clean-test
+clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
+
+clean-build: ## remove build artifacts
+ rm -fr build/
+ rm -fr dist/
+ rm -fr .eggs/
+ find . -name '*.egg-info' -exec rm -fr {} +
+ find . -name '*.egg' -exec rm -f {} +
+
+clean-pyc: ## remove Python file artifacts
+ find . -name '*.pyc' -exec rm -f {} +
+ find . -name '*.pyo' -exec rm -f {} +
+ find . -name '*~' -exec rm -f {} +
+ find . -name '__pycache__' -exec rm -fr {} +
+ find . | grep -E ".pytest_cache" | xargs rm -rf
+ find . | grep -E ".mypy_cache" | xargs rm -rf
+
+clean-test: ## remove test and coverage artifacts
+ rm -fr .tox/
+ rm -f .coverage
+ rm -fr htmlcov/
diff --git a/tools/tlc/assets/images/coverage.svg b/tools/tlc/assets/images/coverage.svg
new file mode 100644
index 0000000..b6c4e36
--- /dev/null
+++ b/tools/tlc/assets/images/coverage.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20">
+ <linearGradient id="b" x2="0" y2="100%">
+ <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
+ <stop offset="1" stop-opacity=".1"/>
+ </linearGradient>
+ <mask id="a">
+ <rect width="99" height="20" rx="3" fill="#fff"/>
+ </mask>
+ <g mask="url(#a)">
+ <path fill="#555" d="M0 0h63v20H0z"/>
+ <path fill="#4c1" d="M63 0h36v20H63z"/>
+ <path fill="url(#b)" d="M0 0h99v20H0z"/>
+ </g>
+ <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
+ <text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
+ <text x="31.5" y="14">coverage</text>
+ <text x="80" y="15" fill="#010101" fill-opacity=".3">95%</text>
+ <text x="80" y="14">95%</text>
+ </g>
+</svg>
diff --git a/tools/tlc/poetry.lock b/tools/tlc/poetry.lock
new file mode 100644
index 0000000..839f236
--- /dev/null
+++ b/tools/tlc/poetry.lock
@@ -0,0 +1,1356 @@
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+
+[[package]]
+name = "astroid"
+version = "2.15.8"
+description = "An abstract syntax tree for Python with inference support."
+optional = false
+python-versions = ">=3.7.2"
+files = [
+ {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"},
+ {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"},
+]
+
+[package.dependencies]
+lazy-object-proxy = ">=1.4.0"
+typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""}
+wrapt = [
+ {version = ">=1.11,<2", markers = "python_version < \"3.11\""},
+ {version = ">=1.14,<2", markers = "python_version >= \"3.11\""},
+]
+
+[[package]]
+name = "bandit"
+version = "1.7.9"
+description = "Security oriented static analyser for python code."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "bandit-1.7.9-py3-none-any.whl", hash = "sha256:52077cb339000f337fb25f7e045995c4ad01511e716e5daac37014b9752de8ec"},
+ {file = "bandit-1.7.9.tar.gz", hash = "sha256:7c395a436743018f7be0a4cbb0a4ea9b902b6d87264ddecf8cfdc73b4f78ff61"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
+PyYAML = ">=5.3.1"
+rich = "*"
+stevedore = ">=1.20.0"
+
+[package.extras]
+baseline = ["GitPython (>=3.1.30)"]
+sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"]
+test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"]
+toml = ["tomli (>=1.1.0)"]
+yaml = ["PyYAML"]
+
+[[package]]
+name = "black"
+version = "24.4.2"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"},
+ {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"},
+ {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"},
+ {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"},
+ {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"},
+ {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"},
+ {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"},
+ {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"},
+ {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"},
+ {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"},
+ {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"},
+ {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"},
+ {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"},
+ {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"},
+ {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"},
+ {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"},
+ {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"},
+ {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"},
+ {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"},
+ {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"},
+ {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"},
+ {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "certifi"
+version = "2024.7.4"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
+ {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
+]
+
+[[package]]
+name = "cfgv"
+version = "3.4.0"
+description = "Validate configuration and produce human readable error messages."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
+ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.3.2"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
+ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
+]
+
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "commonmark"
+version = "0.9.1"
+description = "Python parser for the CommonMark Markdown spec"
+optional = false
+python-versions = "*"
+files = [
+ {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
+ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
+]
+
+[package.extras]
+test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
+
+[[package]]
+name = "coverage"
+version = "6.5.0"
+description = "Code coverage measurement for Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"},
+ {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"},
+ {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"},
+ {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"},
+ {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"},
+ {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"},
+ {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"},
+ {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"},
+ {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"},
+ {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"},
+ {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"},
+ {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"},
+ {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"},
+ {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"},
+ {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"},
+ {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"},
+ {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"},
+ {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"},
+ {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"},
+ {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"},
+]
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "coverage-badge"
+version = "1.1.1"
+description = "Generate coverage badges for Coverage.py."
+optional = false
+python-versions = "*"
+files = [
+ {file = "coverage-badge-1.1.1.tar.gz", hash = "sha256:42252df917404af6147380861228a4ace3d9a29804df8fc2d34a22b2bc4f45b6"},
+ {file = "coverage_badge-1.1.1-py2.py3-none-any.whl", hash = "sha256:1d8e566ad47c37910fa2bbc74ea19972b171b5b4e40624b31b3e2f2d93680266"},
+]
+
+[package.dependencies]
+coverage = "*"
+
+[[package]]
+name = "darglint"
+version = "1.8.1"
+description = "A utility for ensuring Google-style docstrings stay up to date with the source code."
+optional = false
+python-versions = ">=3.6,<4.0"
+files = [
+ {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"},
+ {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
+]
+
+[[package]]
+name = "dill"
+version = "0.3.8"
+description = "serialize all of Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"},
+ {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"},
+]
+
+[package.extras]
+graph = ["objgraph (>=1.7.2)"]
+profile = ["gprof2dot (>=2022.7.29)"]
+
+[[package]]
+name = "distlib"
+version = "0.3.8"
+description = "Distribution utilities"
+optional = false
+python-versions = "*"
+files = [
+ {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
+ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
+]
+
+[[package]]
+name = "dparse"
+version = "0.6.3"
+description = "A parser for Python dependency files"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "dparse-0.6.3-py3-none-any.whl", hash = "sha256:0d8fe18714056ca632d98b24fbfc4e9791d4e47065285ab486182288813a5318"},
+ {file = "dparse-0.6.3.tar.gz", hash = "sha256:27bb8b4bcaefec3997697ba3f6e06b2447200ba273c0b085c3d012a04571b528"},
+]
+
+[package.dependencies]
+packaging = "*"
+tomli = {version = "*", markers = "python_version < \"3.11\""}
+
+[package.extras]
+conda = ["pyyaml"]
+pipenv = ["pipenv (<=2022.12.19)"]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.2.2"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
+ {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "filelock"
+version = "3.15.4"
+description = "A platform independent file lock."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"},
+ {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"]
+typing = ["typing-extensions (>=4.8)"]
+
+[[package]]
+name = "identify"
+version = "2.6.0"
+description = "File identification library for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"},
+ {file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"},
+]
+
+[package.extras]
+license = ["ukkonen"]
+
+[[package]]
+name = "idna"
+version = "3.7"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "isort"
+version = "5.13.2"
+description = "A Python utility / library to sort Python imports."
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
+ {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.4.6", optional = true, markers = "extra == \"colors\""}
+
+[package.extras]
+colors = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "jinja2"
+version = "3.1.4"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "lazy-object-proxy"
+version = "1.10.0"
+description = "A fast and thorough lazy object proxy."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-win32.whl", hash = "sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-win32.whl", hash = "sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-win32.whl", hash = "sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-win32.whl", hash = "sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd"},
+ {file = "lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d"},
+]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.5"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
+ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
+]
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
+]
+
+[[package]]
+name = "mypy"
+version = "0.910"
+description = "Optional static typing for Python"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"},
+ {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"},
+ {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"},
+ {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"},
+ {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"},
+ {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"},
+ {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"},
+ {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"},
+ {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"},
+ {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"},
+ {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"},
+ {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"},
+ {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"},
+ {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"},
+ {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"},
+ {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"},
+ {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"},
+ {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"},
+ {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"},
+ {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"},
+ {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"},
+ {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"},
+ {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=0.4.3,<0.5.0"
+toml = "*"
+typing-extensions = ">=3.7.4"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+python2 = ["typed-ast (>=1.4.0,<1.5.0)"]
+
+[[package]]
+name = "mypy-extensions"
+version = "0.4.4"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+optional = false
+python-versions = ">=2.7"
+files = [
+ {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"},
+]
+
+[[package]]
+name = "nodeenv"
+version = "1.9.1"
+description = "Node.js virtual environment builder"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
+ {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
+]
+
+[[package]]
+name = "packaging"
+version = "24.1"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
+ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
+]
+
+[[package]]
+name = "pathspec"
+version = "0.12.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+]
+
+[[package]]
+name = "pbr"
+version = "6.0.0"
+description = "Python Build Reasonableness"
+optional = false
+python-versions = ">=2.6"
+files = [
+ {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"},
+ {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"},
+]
+
+[[package]]
+name = "platformdirs"
+version = "4.2.2"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
+ {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
+type = ["mypy (>=1.8)"]
+
+[[package]]
+name = "pluggy"
+version = "1.5.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "pre-commit"
+version = "2.21.0"
+description = "A framework for managing and maintaining multi-language pre-commit hooks."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"},
+ {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"},
+]
+
+[package.dependencies]
+cfgv = ">=2.0.0"
+identify = ">=1.0.0"
+nodeenv = ">=0.11.1"
+pyyaml = ">=5.1"
+virtualenv = ">=20.10.0"
+
+[[package]]
+name = "pydocstyle"
+version = "6.3.0"
+description = "Python docstring style checker"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"},
+ {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"},
+]
+
+[package.dependencies]
+snowballstemmer = ">=2.2.0"
+
+[package.extras]
+toml = ["tomli (>=1.2.3)"]
+
+[[package]]
+name = "pygments"
+version = "2.18.0"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
+]
+
+[package.extras]
+windows-terminal = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "pylint"
+version = "2.17.7"
+description = "python code static checker"
+optional = false
+python-versions = ">=3.7.2"
+files = [
+ {file = "pylint-2.17.7-py3-none-any.whl", hash = "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87"},
+ {file = "pylint-2.17.7.tar.gz", hash = "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad"},
+]
+
+[package.dependencies]
+astroid = ">=2.15.8,<=2.17.0-dev0"
+colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
+dill = [
+ {version = ">=0.2", markers = "python_version < \"3.11\""},
+ {version = ">=0.3.6", markers = "python_version >= \"3.11\""},
+]
+isort = ">=4.2.5,<6"
+mccabe = ">=0.6,<0.8"
+platformdirs = ">=2.2.0"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+tomlkit = ">=0.10.1"
+typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+spelling = ["pyenchant (>=3.2,<4.0)"]
+testutils = ["gitpython (>3)"]
+
+[[package]]
+name = "pytest"
+version = "7.4.4"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "3.0.0"
+description = "Pytest plugin for measuring coverage."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
+ {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+
+[[package]]
+name = "pytest-html"
+version = "4.1.1"
+description = "pytest plugin for generating HTML reports"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest_html-4.1.1-py3-none-any.whl", hash = "sha256:c8152cea03bd4e9bee6d525573b67bbc6622967b72b9628dda0ea3e2a0b5dd71"},
+ {file = "pytest_html-4.1.1.tar.gz", hash = "sha256:70a01e8ae5800f4a074b56a4cb1025c8f4f9b038bba5fe31e3c98eb996686f07"},
+]
+
+[package.dependencies]
+jinja2 = ">=3.0.0"
+pytest = ">=7.0.0"
+pytest-metadata = ">=2.0.0"
+
+[package.extras]
+docs = ["pip-tools (>=6.13.0)"]
+test = ["assertpy (>=1.1)", "beautifulsoup4 (>=4.11.1)", "black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "pytest-mock (>=3.7.0)", "pytest-rerunfailures (>=11.1.2)", "pytest-xdist (>=2.4.0)", "selenium (>=4.3.0)", "tox (>=3.24.5)"]
+
+[[package]]
+name = "pytest-metadata"
+version = "3.1.1"
+description = "pytest plugin for test session metadata"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest_metadata-3.1.1-py3-none-any.whl", hash = "sha256:c8e0844db684ee1c798cfa38908d20d67d0463ecb6137c72e91f418558dd5f4b"},
+ {file = "pytest_metadata-3.1.1.tar.gz", hash = "sha256:d2a29b0355fbc03f168aa96d41ff88b1a3b44a3b02acbe491801c98a048017c8"},
+]
+
+[package.dependencies]
+pytest = ">=7.0.0"
+
+[package.extras]
+test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "tox (>=3.24.5)"]
+
+[[package]]
+name = "pyupgrade"
+version = "2.38.4"
+description = "A tool to automatically upgrade syntax for newer versions."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyupgrade-2.38.4-py2.py3-none-any.whl", hash = "sha256:944ff993c396ddc2b9012eb3de4cda138eb4c149b22c6c560d4c8bfd0e180982"},
+ {file = "pyupgrade-2.38.4.tar.gz", hash = "sha256:1eb43a49f416752929741ba4d706bf3f33593d3cac9bdc217fc1ef55c047c1f4"},
+]
+
+[package.dependencies]
+tokenize-rt = "<5"
+
+[[package]]
+name = "pyyaml"
+version = "6.0.1"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
+ {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
+ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
+]
+
+[[package]]
+name = "requests"
+version = "2.32.3"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "rich"
+version = "10.16.2"
+description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
+optional = false
+python-versions = ">=3.6.2,<4.0.0"
+files = [
+ {file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"},
+ {file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.0,<0.5.0"
+commonmark = ">=0.9.0,<0.10.0"
+pygments = ">=2.6.0,<3.0.0"
+
+[package.extras]
+jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
+
+[[package]]
+name = "ruamel-yaml"
+version = "0.18.6"
+description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"},
+ {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"},
+]
+
+[package.dependencies]
+"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""}
+
+[package.extras]
+docs = ["mercurial (>5.7)", "ryd"]
+jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
+
+[[package]]
+name = "ruamel-yaml-clib"
+version = "0.2.8"
+description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"},
+ {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"},
+]
+
+[[package]]
+name = "safety"
+version = "2.3.4"
+description = "Checks installed dependencies for known vulnerabilities and licenses."
+optional = false
+python-versions = "*"
+files = [
+ {file = "safety-2.3.4-py3-none-any.whl", hash = "sha256:6224dcd9b20986a2b2c5e7acfdfba6bca42bb11b2783b24ed04f32317e5167ea"},
+ {file = "safety-2.3.4.tar.gz", hash = "sha256:b9e74e794e82f54d11f4091c5d820c4d2d81de9f953bf0b4f33ac8bc402ae72c"},
+]
+
+[package.dependencies]
+Click = ">=8.0.2"
+dparse = ">=0.6.2"
+packaging = ">=21.0"
+requests = "*"
+"ruamel.yaml" = ">=0.17.21"
+setuptools = ">=19.3"
+
+[package.extras]
+github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"]
+gitlab = ["python-gitlab (>=1.3.0)"]
+
+[[package]]
+name = "setuptools"
+version = "72.1.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
+ {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
+]
+
+[package.extras]
+core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+description = "Tool to Detect Surrounding Shell"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
+ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "2.2.0"
+description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
+optional = false
+python-versions = "*"
+files = [
+ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
+ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
+]
+
+[[package]]
+name = "stevedore"
+version = "5.2.0"
+description = "Manage dynamic plugins for Python applications"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "stevedore-5.2.0-py3-none-any.whl", hash = "sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9"},
+ {file = "stevedore-5.2.0.tar.gz", hash = "sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"},
+]
+
+[package.dependencies]
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+
+[[package]]
+name = "tokenize-rt"
+version = "4.2.1"
+description = "A wrapper around the stdlib `tokenize` which roundtrips."
+optional = false
+python-versions = ">=3.6.1"
+files = [
+ {file = "tokenize_rt-4.2.1-py2.py3-none-any.whl", hash = "sha256:08a27fa032a81cf45e8858d0ac706004fcd523e8463415ddf1442be38e204ea8"},
+ {file = "tokenize_rt-4.2.1.tar.gz", hash = "sha256:0d4f69026fed520f8a1e0103aa36c406ef4661417f20ca643f913e33531b3b94"},
+]
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "tomlkit"
+version = "0.13.0"
+description = "Style preserving TOML library"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "tomlkit-0.13.0-py3-none-any.whl", hash = "sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"},
+ {file = "tomlkit-0.13.0.tar.gz", hash = "sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72"},
+]
+
+[[package]]
+name = "typer"
+version = "0.4.2"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.4.2-py3-none-any.whl", hash = "sha256:023bae00d1baf358a6cc7cea45851639360bb716de687b42b0a4641cd99173f1"},
+ {file = "typer-0.4.2.tar.gz", hash = "sha256:b8261c6c0152dd73478b5ba96ba677e5d6948c715c310f7c91079f311f62ec03"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
+shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.2.2"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
+ {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "virtualenv"
+version = "20.26.3"
+description = "Virtual Python Environment builder"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"},
+ {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"},
+]
+
+[package.dependencies]
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<5"
+
+[package.extras]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
+
+[[package]]
+name = "wrapt"
+version = "1.16.0"
+description = "Module for decorators, wrappers and monkey patching."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"},
+ {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"},
+ {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"},
+ {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"},
+ {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"},
+ {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"},
+ {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"},
+ {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"},
+ {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"},
+ {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"},
+ {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"},
+ {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"},
+ {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"},
+ {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"},
+ {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"},
+ {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"},
+ {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"},
+ {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"},
+ {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"},
+ {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"},
+ {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"},
+ {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"},
+ {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"},
+ {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"},
+ {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"},
+ {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"},
+ {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"},
+ {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"},
+ {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"},
+ {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"},
+ {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"},
+ {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"},
+ {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"},
+ {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"},
+ {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"},
+ {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"},
+ {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"},
+ {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"},
+ {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"},
+ {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"},
+ {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"},
+ {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"},
+ {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"},
+ {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"},
+ {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"},
+ {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"},
+ {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"},
+ {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"},
+ {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"},
+ {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"},
+ {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"},
+ {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"},
+ {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"},
+ {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"},
+ {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"},
+ {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"},
+ {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"},
+ {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"},
+ {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"},
+ {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"},
+ {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"},
+ {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"},
+ {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"},
+ {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"},
+ {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"},
+ {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"},
+ {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"},
+ {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"},
+ {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"},
+ {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.8"
+content-hash = "cfcb196cda412f6139302937640455aa8154d7979c69017fe45ddd528e4a1bf2"
diff --git a/tools/tlc/pyproject.toml b/tools/tlc/pyproject.toml
new file mode 100644
index 0000000..5661abf
--- /dev/null
+++ b/tools/tlc/pyproject.toml
@@ -0,0 +1,147 @@
+# Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/
+[build-system]
+requires = ["poetry_core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry]
+name = "tlc"
+version = "0.9.0"
+description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
+authors = ["Arm Ltd <tf-a@lists.trustedfirmware.org>"]
+license = "BSD-3"
+repository = "https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/"
+homepage = "https://trustedfirmware-a.readthedocs.io/en/latest/index.html"
+
+# Keywords description https://python-poetry.org/docs/pyproject/#keywords
+keywords = [] #! Update me
+
+# Pypi classifiers: https://pypi.org/classifiers/
+classifiers = [
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Operating System :: OS Independent",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "License :: OSI Approved :: BSD License",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+]
+
+[tool.poetry.scripts]
+# Entry points for the package https://python-poetry.org/docs/pyproject/#scripts
+"tlc" = "tlc.__main__:cli"
+
+[tool.poetry.dependencies]
+python = "^3.8"
+
+typer = {extras = ["all"], version = "^0.4.0"}
+rich = "^10.14.0"
+click = "^8.1.7"
+pyyaml = "^6.0.1"
+
+[tool.poetry.dev-dependencies]
+bandit = "^1.7.1"
+darglint = "^1.8.1"
+black = "^24.4.2"
+isort = {extras = ["colors"], version = "^5.10.1"}
+mypy = "^0.910"
+mypy-extensions = "^0.4.3"
+pre-commit = "^2.15.0"
+pydocstyle = "^6.1.1"
+pylint = "^2.11.1"
+pytest = "^7.0.0"
+pyupgrade = "^2.29.1"
+safety = "^2.2.0"
+coverage = "^6.1.2"
+coverage-badge = "^1.1.0"
+pytest-html = "^4.1.1"
+pytest-cov = "^3.0.0"
+
+[tool.black]
+# https://github.com/psf/black
+target-version = ["py38"]
+line-length = 88
+color = true
+
+exclude = '''
+/(
+ \.git
+ | \.hg
+ | \.mypy_cache
+ | \.tox
+ | \.venv
+ | _build
+ | buck-out
+ | build
+ | dist
+ | env
+ | venv
+)/
+'''
+
+[tool.isort]
+# https://github.com/timothycrosley/isort/
+py_version = 38
+line_length = 88
+
+known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"]
+sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
+include_trailing_comma = true
+profile = "black"
+multi_line_output = 3
+indent = 4
+color_output = true
+
+[tool.mypy]
+# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
+python_version = 3.8
+pretty = true
+show_traceback = true
+color_output = true
+
+allow_redefinition = false
+check_untyped_defs = true
+disallow_any_generics = true
+disallow_incomplete_defs = true
+ignore_missing_imports = true
+implicit_reexport = false
+no_implicit_optional = true
+show_column_numbers = true
+show_error_codes = true
+show_error_context = true
+strict_equality = true
+strict_optional = true
+warn_no_return = true
+warn_redundant_casts = true
+warn_return_any = true
+warn_unreachable = true
+warn_unused_configs = true
+warn_unused_ignores = true
+
+
+[tool.pytest.ini_options]
+# https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml
+# Directories that are not visited by pytest collector:
+norecursedirs =["hooks", "*.egg", ".eggs", "dist", "build", "docs", ".tox", ".git", "__pycache__"]
+doctest_optionflags = ["NUMBER", "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
+
+# Extra options:
+addopts = [
+ "--strict-markers",
+ "--tb=short",
+ "--doctest-modules",
+ "--doctest-continue-on-failure",
+]
+
+[tool.coverage.run]
+source = ["tests"]
+
+[coverage.paths]
+source = "tlc"
+
+[coverage.run]
+branch = true
+
+[coverage.report]
+fail_under = 50
+show_missing = true
diff --git a/tools/tlc/setup.cfg b/tools/tlc/setup.cfg
new file mode 100644
index 0000000..3c46a08
--- /dev/null
+++ b/tools/tlc/setup.cfg
@@ -0,0 +1,4 @@
+[darglint]
+# https://github.com/terrencepreilly/darglint
+strictness = long
+docstring_style = google
diff --git a/tools/tlc/tests/conftest.py b/tools/tlc/tests/conftest.py
new file mode 100644
index 0000000..b8f88b5
--- /dev/null
+++ b/tools/tlc/tests/conftest.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+""" Common configurations and fixtures for test environment."""
+
+import pytest
+import yaml
+from click.testing import CliRunner
+
+from tlc.cli import cli
+
+
+@pytest.fixture
+def tmptlstr(tmpdir):
+ return tmpdir.join("tl.bin").strpath
+
+
+@pytest.fixture
+def tmpyamlconfig(tmpdir):
+ return tmpdir.join("config.yaml").strpath
+
+
+@pytest.fixture
+def tmpfdt(tmpdir):
+ fdt = tmpdir.join("fdt.dtb")
+ fdt.write_binary(b"\x00" * 100)
+ return fdt
+
+
+@pytest.fixture(params=[1, 2, 3, 4, 5, 0x100, 0x101, 0x102, 0x104])
+def non_empty_tag_id(request):
+ return request.param
+
+
+@pytest.fixture
+def tmpyamlconfig_blob_file(tmpdir, tmpfdt, non_empty_tag_id):
+ config_path = tmpdir.join("config.yaml")
+
+ config = {
+ "has_checksum": True,
+ "max_size": 0x1000,
+ "entries": [
+ {
+ "tag_id": non_empty_tag_id,
+ "blob_file_path": tmpfdt.strpath,
+ },
+ ],
+ }
+
+ with open(config_path, "w") as f:
+ yaml.safe_dump(config, f)
+
+ return config_path
+
+
+@pytest.fixture
+def tlcrunner(tmptlstr):
+ runner = CliRunner()
+ with runner.isolated_filesystem():
+ runner.invoke(cli, ["create", tmptlstr])
+ return runner
+
+
+@pytest.fixture
+def tlc_entries(tmpfdt):
+ return [(0, "/dev/null"), (1, tmpfdt.strpath), (0x102, tmpfdt.strpath)]
diff --git a/tools/tlc/tests/test_cli.py b/tools/tlc/tests/test_cli.py
new file mode 100644
index 0000000..99b5816
--- /dev/null
+++ b/tools/tlc/tests/test_cli.py
@@ -0,0 +1,413 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Contains unit tests for the CLI functionality."""
+
+from pathlib import Path
+from unittest import mock
+from math import log2, ceil
+
+import pytest
+import pytest
+import yaml
+from click.testing import CliRunner
+
+from tlc.cli import cli
+from tlc.te import TransferEntry
+from tlc.tl import TransferList
+
+
+def test_create_empty_tl(tmpdir):
+ runner = CliRunner()
+ test_file = tmpdir.join("tl.bin")
+
+ result = runner.invoke(cli, ["create", test_file.strpath])
+ assert result.exit_code == 0
+ assert TransferList.fromfile(test_file) is not None
+
+
+def test_create_with_fdt(tmpdir):
+ runner = CliRunner()
+ fdt = tmpdir.join("fdt.dtb")
+ fdt.write_binary(b"\x00" * 100)
+
+ result = runner.invoke(
+ cli,
+ [
+ "create",
+ "--fdt",
+ fdt.strpath,
+ "--size",
+ "1000",
+ tmpdir.join("tl.bin").strpath,
+ ],
+ )
+ assert result.exit_code == 0
+
+
+def test_add_single_entry(tlcrunner, tmptlstr):
+ tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
+
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+ assert tl.entries[0].id == 0
+
+
+def test_add_multiple_entries(tlcrunner, tlc_entries, tmptlstr):
+ for id, path in tlc_entries:
+ tlcrunner.invoke(cli, ["add", "--entry", id, path, tmptlstr])
+
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == len(tlc_entries)
+
+
+def test_info(tlcrunner, tmptlstr, tmpfdt):
+ tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
+ tlcrunner.invoke(cli, ["add", "--fdt", tmpfdt.strpath, tmptlstr])
+
+ result = tlcrunner.invoke(cli, ["info", tmptlstr])
+ assert result.exit_code == 0
+ assert "signature" in result.stdout
+ assert "id" in result.stdout
+
+ result = tlcrunner.invoke(cli, ["info", "--header", tmptlstr])
+ assert result.exit_code == 0
+ assert "signature" in result.stdout
+ assert "id" not in result.stdout
+
+ result = tlcrunner.invoke(cli, ["info", "--entries", tmptlstr])
+ assert result.exit_code == 0
+ assert "signature" not in result.stdout
+ assert "id" in result.stdout
+
+
+def test_raises_max_size_error(tmptlstr, tmpfdt):
+ tmpfdt.write_binary(bytes(6000))
+
+ runner = CliRunner()
+ result = runner.invoke(cli, ["create", "--fdt", tmpfdt, tmptlstr])
+
+ assert result.exception
+ assert isinstance(result.exception, MemoryError)
+ assert "TL max size exceeded, consider increasing with the option -s" in str(
+ result.exception
+ )
+ assert "TL size has exceeded the maximum allocation" in str(
+ result.exception.__cause__
+ )
+
+
+def test_info_get_fdt_offset(tmptlstr, tmpfdt):
+ runner = CliRunner()
+ with runner.isolated_filesystem():
+ runner.invoke(cli, ["create", "--size", "1000", tmptlstr])
+ runner.invoke(cli, ["add", "--entry", "1", tmpfdt.strpath, tmptlstr])
+ result = runner.invoke(cli, ["info", "--fdt-offset", tmptlstr])
+
+ assert result.exit_code == 0
+ assert result.output.strip("\n").isdigit()
+
+
+def test_remove_tag(tlcrunner, tmptlstr):
+ tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
+ result = tlcrunner.invoke(cli, ["info", tmptlstr])
+
+ assert result.exit_code == 0
+ assert "signature" in result.stdout
+
+ tlcrunner.invoke(cli, ["remove", "--tags", "0", tmptlstr])
+ tl = TransferList.fromfile(tmptlstr)
+
+ assert result.exit_code == 0
+ assert len(tl.entries) == 0
+
+
+def test_unpack_tl(tlcrunner, tmptlstr, tmpfdt, tmpdir):
+ with tlcrunner.isolated_filesystem(temp_dir=tmpdir):
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["unpack", tmptlstr])
+ assert Path("te_0_1.bin").exists()
+
+
+def test_unpack_multiple_tes(tlcrunner, tlc_entries, tmptlstr, tmpdir):
+ with tlcrunner.isolated_filesystem(temp_dir=tmpdir):
+ for id, path in tlc_entries:
+ tlcrunner.invoke(cli, ["add", "--entry", id, path, tmptlstr])
+
+ assert all(
+ filter(
+ lambda te: (Path(tmpdir.strpath) / f"te_{te[0]}.bin").exists(), tlc_entries
+ )
+ )
+
+
+def test_unpack_into_dir(tlcrunner, tmpdir, tmptlstr, tmpfdt):
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["unpack", "-C", tmpdir.strpath, tmptlstr])
+
+ assert (Path(tmpdir.strpath) / "te_0_1.bin").exists()
+
+
+def test_unpack_into_dir_with_conflicting_tags(tlcrunner, tmpdir, tmptlstr, tmpfdt):
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["unpack", "-C", tmpdir.strpath, tmptlstr])
+
+ assert (Path(tmpdir.strpath) / "te_0_1.bin").exists()
+ assert (Path(tmpdir.strpath) / "te_1_1.bin").exists()
+
+
+def test_validate_invalid_signature(tmptlstr, tlcrunner, monkeypatch):
+ tl = TransferList()
+ tl.signature = 0xDEADBEEF
+
+ mock_open = lambda tmptlstr, mode: mock.mock_open(read_data=tl.header_to_bytes())()
+ monkeypatch.setattr("builtins.open", mock_open)
+
+ result = tlcrunner.invoke(cli, ["validate", tmptlstr])
+ assert result.exit_code != 0
+
+
+def test_validate_misaligned_entries(tmptlstr, tlcrunner, monkeypatch):
+ """Base address of a TE must be 8-byte aligned."""
+ mock_open = lambda tmptlstr, mode: mock.mock_open(
+ read_data=TransferList().header_to_bytes()
+ + bytes(5)
+ + TransferEntry(0, 0, bytes(0)).header_to_bytes
+ )()
+ monkeypatch.setattr("builtins.open", mock_open)
+
+ result = tlcrunner.invoke(cli, ["validate", tmptlstr])
+
+ assert result.exit_code == 1
+
+
+@pytest.mark.parametrize(
+ "version", [0, TransferList.version, TransferList.version + 1, 1 << 8]
+)
+def test_validate_unsupported_version(version, tmptlstr, tlcrunner, monkeypatch):
+ tl = TransferList()
+ tl.version = version
+
+ mock_open = lambda tmptlstr, mode: mock.mock_open(read_data=tl.header_to_bytes())()
+ monkeypatch.setattr("builtins.open", mock_open)
+
+ result = tlcrunner.invoke(cli, ["validate", tmptlstr])
+
+ if version >= TransferList.version and version <= 0xFF:
+ assert result.exit_code == 0
+ else:
+ assert result.exit_code == 1
+
+
+def test_create_entry_from_yaml_and_blob_file(
+ tlcrunner, tmpyamlconfig_blob_file, tmptlstr, non_empty_tag_id
+):
+ tlcrunner.invoke(
+ cli,
+ [
+ "create",
+ "--from-yaml",
+ tmpyamlconfig_blob_file.strpath,
+ tmptlstr,
+ ],
+ )
+
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+ assert tl.entries[0].id == non_empty_tag_id
+
+
+@pytest.mark.parametrize(
+ "entry",
+ [
+ {"tag_id": 0},
+ {
+ "tag_id": 0x104,
+ "addr": 0x0400100000000010,
+ "size": 0x0003300000000000,
+ },
+ {
+ "tag_id": 0x100,
+ "pp_addr": 100,
+ },
+ {
+ "tag_id": "optee_pageable_part",
+ "pp_addr": 100,
+ },
+ ],
+)
+def test_create_from_yaml_check_sum_bytes(tlcrunner, tmpyamlconfig, tmptlstr, entry):
+ """Test creating a TL from a yaml file, but only check that the sum of the
+ data in the yaml file matches the sum of the data in the TL. This means
+ you don't have to type the exact sequence of expected bytes. All the data
+ in the yaml file must be integers (except for the tag IDs, which can be
+ strings).
+ """
+ # create yaml config file
+ config = {
+ "has_checksum": True,
+ "max_size": 0x1000,
+ "entries": [entry],
+ }
+ with open(tmpyamlconfig, "w") as f:
+ yaml.safe_dump(config, f)
+
+ # invoke TLC
+ tlcrunner.invoke(
+ cli,
+ [
+ "create",
+ "--from-yaml",
+ tmpyamlconfig,
+ tmptlstr,
+ ],
+ )
+
+ # open created TL, and check
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+
+ # Check that the sum of all the data in the transfer entry in the yaml file
+ # is the same as the sum of all the data in the transfer list. Don't count
+ # the tag id or the TE headers.
+
+ # every item in the entry dict must be an integer
+ yaml_total = 0
+ for key, data in iter_nested_dict(entry):
+ if key != "tag_id":
+ num_bytes = ceil(log2(data + 1) / 8)
+ yaml_total += sum(data.to_bytes(num_bytes, "little"))
+
+ tl_total = sum(tl.entries[0].data)
+
+ assert tl_total == yaml_total
+
+
+@pytest.mark.parametrize(
+ "entry,expected",
+ [
+ (
+ {
+ "tag_id": 0x102,
+ "ep_info": {
+ "h": {
+ "type": 0x01,
+ "version": 0x02,
+ "attr": 8,
+ },
+ "pc": 67239936,
+ "spsr": 965,
+ "args": [67112976, 67112960, 0, 0, 0, 0, 0, 0],
+ },
+ },
+ (
+ "0x00580201 0x00000008 0x04020000 0x00000000 "
+ "0x000003C5 0x00000000 0x04001010 0x00000000 "
+ "0x04001000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000"
+ ),
+ ),
+ (
+ {
+ "tag_id": 0x102,
+ "ep_info": {
+ "h": {
+ "type": 0x01,
+ "version": 0x02,
+ "attr": "EP_NON_SECURE | EP_ST_ENABLE",
+ },
+ "pc": 67239936,
+ "spsr": 965,
+ "args": [67112976, 67112960, 0, 0, 0, 0, 0, 0],
+ },
+ },
+ (
+ "0x00580201 0x00000005 0x04020000 0x00000000 "
+ "0x000003C5 0x00000000 0x04001010 0x00000000 "
+ "0x04001000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000"
+ ),
+ ),
+ ],
+)
+def test_create_from_yaml_check_exact_data(
+ tlcrunner, tmpyamlconfig, tmptlstr, entry, expected
+):
+ """Test creating a TL from a yaml file, checking the exact sequence of
+ bytes. This is useful for checking that the alignment is correct. You can
+ get the expected sequence of bytes by copying it from the ArmDS debugger.
+ """
+ # create yaml config file
+ config = {
+ "has_checksum": True,
+ "max_size": 0x1000,
+ "entries": [entry],
+ }
+ with open(tmpyamlconfig, "w") as f:
+ yaml.safe_dump(config, f)
+
+ # invoke TLC
+ tlcrunner.invoke(
+ cli,
+ [
+ "create",
+ "--from-yaml",
+ tmpyamlconfig,
+ tmptlstr,
+ ],
+ )
+
+ # open TL and check
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+
+ # check expected and actual data
+ actual = tl.entries[0].data
+ actual = bytes_to_hex(actual)
+
+ assert actual == expected
+
+
+def bytes_to_hex(data: bytes) -> str:
+ """Convert bytes to a hex string in the same format as the debugger in
+ ArmDS
+
+ You can copy data from the debugger in Arm Development Studio and put it
+ into a unit test. You can then run this function on the output from tlc,
+ and compare it to the data you copied.
+
+ The format is groups of 4 bytes with 0x prefixes separated by spaces.
+ Little endian is used.
+ """
+ words_hex = []
+ for i in range(0, len(data), 4):
+ word = data[i : i + 4]
+ word_int = int.from_bytes(word, "little")
+ word_hex = "0x" + f"{word_int:0>8x}".upper()
+ words_hex.append(word_hex)
+
+ return " ".join(words_hex)
+
+
+def iter_nested_dict(dictionary: dict):
+ for key, value in dictionary.items():
+ if isinstance(value, dict):
+ yield from iter_nested_dict(value)
+ else:
+ yield key, value
diff --git a/tools/tlc/tests/test_transfer_list.py b/tools/tlc/tests/test_transfer_list.py
new file mode 100644
index 0000000..e8c430e
--- /dev/null
+++ b/tools/tlc/tests/test_transfer_list.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Contains unit tests for the types TransferEntry and TransferList."""
+
+import math
+
+import pytest
+
+from tlc.te import TransferEntry
+from tlc.tl import TransferList
+
+large_data = 0xDEADBEEF.to_bytes(4, "big")
+small_data = 0x1234.to_bytes(3, "big")
+test_entries = [
+ (0, b""),
+ (1, small_data),
+ (1, large_data),
+ (0xFFFFFF, small_data),
+ (0xFFFFFF, large_data),
+]
+
+
+@pytest.mark.parametrize(
+ "size,csum",
+ [
+ (-1, None),
+ (0x18, 0x9E),
+ (0x1000, 0xA6),
+ (0x2000, 0x96),
+ (0x4000, 0x76),
+ ],
+)
+def test_make_transfer_list(size, csum):
+ if size < 8:
+ with pytest.raises(AssertionError):
+ tl = TransferList(size)
+ else:
+ tl = TransferList(size)
+
+ assert tl.signature == 0x4A0FB10B
+ assert not tl.entries
+ assert tl.sum_of_bytes() == 0
+ assert tl.checksum == csum
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_add_transfer_entry(tag_id, data):
+ tl = TransferList(0x1000)
+ te = TransferEntry(tag_id, len(data), data)
+
+ tl.add_transfer_entry(tag_id, data)
+
+ assert te in tl.entries
+ assert tl.size == TransferList.hdr_size + te.size
+
+
+@pytest.mark.parametrize(
+ ("tag_id", "data"),
+ [
+ (-1, None), # tag out of range
+ (1, None), # no data provided
+ (1, bytes(8000)), # very large data > total size
+ (0x100000, b"0dd0edfe"), # tag out of range
+ ],
+)
+def test_add_out_of_range_transfer_entry(tag_id, data):
+ tl = TransferList()
+
+ with pytest.raises(Exception):
+ tl.add_transfer_entry(tag_id, data)
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_calculate_te_sum_of_bytes(tag_id, data):
+ te = TransferEntry(tag_id, len(data), data)
+ csum = (
+ sum(data)
+ + sum(len(data).to_bytes(4, "big"))
+ + te.hdr_size
+ + sum(tag_id.to_bytes(4, "big"))
+ ) % 256
+ assert te.sum_of_bytes == csum
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_calculate_tl_checksum(tag_id, data):
+ tl = TransferList(0x1000)
+
+ tl.add_transfer_entry(tag_id, data)
+ assert tl.sum_of_bytes() == 0
+
+
+def test_empty_transfer_list_blob(tmpdir):
+ """Check that we can correctly create a transfer list header."""
+ test_file = tmpdir.join("test_tl_blob.bin")
+ tl = TransferList()
+ tl.write_to_file(test_file)
+
+ with open(test_file, "rb") as f:
+ assert f.read(tl.hdr_size) == tl.header_to_bytes()
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_single_te_transfer_list(tag_id, data, tmpdir):
+ """Check that we can create a complete TL with a single TE."""
+ test_file = tmpdir.join("test_tl_blob.bin")
+ tl = TransferList(0x1000)
+
+ tl.add_transfer_entry(tag_id, data)
+ tl.write_to_file(test_file)
+
+ te = tl.entries[0]
+
+ with open(test_file, "rb") as f:
+ assert f.read(tl.hdr_size) == tl.header_to_bytes()
+ assert int.from_bytes(f.read(3), "little") == te.id
+ assert int.from_bytes(f.read(1), "little") == te.hdr_size
+ assert int.from_bytes(f.read(4), "little") == te.data_size
+ assert f.read(te.data_size) == te.data
+
+
+def test_multiple_te_transfer_list(tmpdir):
+ """Check that we can create a TL with multiple TE's."""
+ test_file = tmpdir.join("test_tl_blob.bin")
+ tl = TransferList(0x1000)
+
+ for tag_id, data in test_entries:
+ tl.add_transfer_entry(tag_id, data)
+
+ tl.write_to_file(test_file)
+
+ with open(test_file, "rb") as f:
+ assert f.read(tl.hdr_size) == tl.header_to_bytes()
+ # Ensure that TE's have the correct alignment
+ for tag_id, data in test_entries:
+ f.seek(int(math.ceil(f.tell() / 2**tl.alignment) * 2**tl.alignment))
+ print(f.tell())
+ assert int.from_bytes(f.read(3), "little") == tag_id
+ assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
+ # Make sure the data in the TE matches the data in the original case
+ data_size = int.from_bytes(f.read(4), "little")
+ assert f.read(data_size) == data
+
+
+def test_read_empty_transfer_list_from_file(tmpdir):
+ test_file = tmpdir.join("test_tl_blob.bin")
+ original_tl = TransferList(0x1000)
+ original_tl.write_to_file(test_file)
+
+ # Read the contents of the file we just wrote
+ tl = TransferList.fromfile(test_file)
+ assert tl.header_to_bytes() == original_tl.header_to_bytes()
+ assert tl.sum_of_bytes() == 0
+
+
+def test_read_single_transfer_list_from_file(tmpdir):
+ test_file = tmpdir.join("test_tl_blob.bin")
+ original_tl = TransferList(0x1000)
+
+ original_tl.add_transfer_entry(test_entries[0][0], test_entries[0][1])
+ original_tl.write_to_file(test_file)
+
+ # Read the contents of the file we just wrote
+ tl = TransferList.fromfile(test_file)
+ assert tl.entries
+
+ te = tl.entries[0]
+ assert te.id == test_entries[0][0]
+ assert te.data == test_entries[0][1]
+ assert tl.sum_of_bytes() == 0
+
+
+def test_read_multiple_transfer_list_from_file(tmpdir):
+ test_file = tmpdir.join("test_tl_blob.bin")
+ original_tl = TransferList(0x1000)
+
+ for tag_id, data in test_entries:
+ original_tl.add_transfer_entry(tag_id, data)
+
+ original_tl.write_to_file(test_file)
+
+ # Read the contents of the file we just wrote
+ tl = TransferList.fromfile(test_file)
+
+ # The TE we derive from the file might have a an associated offset, compare
+ # the TE's based on the header in bytes, which doesn't account for this.
+ for te0, te1 in zip(tl.entries, original_tl.entries):
+ assert te0.header_to_bytes() == te1.header_to_bytes()
+
+ assert tl.sum_of_bytes() == 0
+
+
+@pytest.mark.parametrize("tag", [tag for tag, _ in test_entries])
+def test_remove_tag_from_file(tag):
+ tl = TransferList(0x1000)
+
+ for tag_id, data in test_entries:
+ tl.add_transfer_entry(tag_id, data)
+
+ removed_entries = list(filter(lambda te: te.id == tag, tl.entries))
+ original_size = tl.size
+ tl.remove_tag(tag)
+
+ assert not any(tag == te.id for te in tl.entries)
+ assert tl.size == original_size - sum(map(lambda te: te.size, removed_entries))
+
+
+def test_get_fdt_offset(tmpdir):
+ tl = TransferList(0x1000)
+ tl.add_transfer_entry(1, 0xEDFE0DD0.to_bytes(4, "big"))
+ f = tmpdir.join("blob.bin")
+
+ tl.write_to_file(f)
+
+ blob_tl = TransferList.fromfile(f)
+
+ assert blob_tl.hdr_size + TransferEntry.hdr_size == blob_tl.get_entry_data_offset(1)
+
+
+def test_get_missing_fdt_offset(tmpdir):
+ tl = TransferList(0x1000)
+ f = tmpdir.join("blob.bin")
+
+ tl.write_to_file(f)
+ blob_tl = TransferList.fromfile(f)
+
+ with pytest.raises(ValueError):
+ blob_tl.get_entry_data_offset(1)
diff --git a/tools/tlc/tlc/__init__.py b/tools/tlc/tlc/__init__.py
new file mode 100644
index 0000000..82f5f5b
--- /dev/null
+++ b/tools/tlc/tlc/__init__.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."""
+
+import sys
+
+if sys.version_info >= (3, 8):
+ from importlib import metadata as importlib_metadata
+else:
+ import importlib_metadata
+
+
+def get_version() -> str:
+ try:
+ return importlib_metadata.version(__name__)
+ except importlib_metadata.PackageNotFoundError: # pragma: no cover
+ return "unknown"
+
+
+version: str = get_version()
diff --git a/tools/tlc/tlc/__main__.py b/tools/tlc/tlc/__main__.py
new file mode 100644
index 0000000..03ffa0e
--- /dev/null
+++ b/tools/tlc/tlc/__main__.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+from tlc.cli import cli
+
+if __name__ == "__main__":
+ cli()
diff --git a/tools/tlc/tlc/cli.py b/tools/tlc/tlc/cli.py
new file mode 100644
index 0000000..1d4949d
--- /dev/null
+++ b/tools/tlc/tlc/cli.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Module defining the Transfer List Compiler (TLC) command line interface."""
+
+from pathlib import Path
+
+import click
+import yaml
+
+from tlc.tl import *
+
+
+@click.group()
+@click.version_option()
+def cli():
+ pass
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(dir_okay=False))
+@click.option(
+ "-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List"
+)
+@click.option(
+ "--fdt",
+ type=click.Path(exists=True),
+ help="Path to flattened device tree (FDT).",
+)
+@click.option(
+ "--entry",
+ type=(int, click.Path(exists=True)),
+ multiple=True,
+ help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
+)
+@click.option(
+ "--flags",
+ default=TRANSFER_LIST_ENABLE_CHECKSUM,
+ show_default=True,
+ help="Settings for the TL's properties.",
+)
+@click.option(
+ "--from-yaml",
+ type=click.Path(exists=True),
+ help="Create the transfer list from a YAML config file.",
+)
+def create(filename, size, fdt, entry, flags, from_yaml):
+ """Create a new Transfer List."""
+ try:
+ if from_yaml:
+ with open(from_yaml, "r") as f:
+ config = yaml.safe_load(f)
+
+ tl = TransferList.from_dict(config)
+ else:
+ tl = TransferList(size)
+
+ entry = (*entry, (1, fdt)) if fdt else entry
+
+ for id, path in entry:
+ tl.add_transfer_entry_from_file(id, path)
+ except MemoryError as mem_excp:
+ raise MemoryError(
+ "TL max size exceeded, consider increasing with the option -s"
+ ) from mem_excp
+
+ tl.write_to_file(filename)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "--fdt-offset",
+ is_flag=True,
+ help="Returns the offset of FDT in the TL if it is present.",
+)
+@click.option(
+ "--header",
+ is_flag=True,
+ help="Print the Transfer List header.",
+)
+@click.option(
+ "--entries",
+ is_flag=True,
+ help="Print the Transfer List entries.",
+)
+def info(filename, fdt_offset, header, entries):
+ """Print the contents of an existing Transfer List.
+
+ This command allows you to extract the data stored in a binary blob
+ representing a transfer list (TL). The transfer list must comply with the
+ version of the firmware handoff specification supported by this tool.
+ """
+ tl = TransferList.fromfile(filename)
+
+ if fdt_offset:
+ return print(tl.get_entry_data_offset(1))
+
+ if header and entries or not (header or entries):
+ print(tl, sep="")
+ if tl.entries:
+ print("----", tl.get_transfer_entries_str(), sep="\n")
+ elif entries:
+ print(tl.get_transfer_entries_str())
+ elif header:
+ print(tl)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "--tags",
+ type=int,
+ multiple=True,
+ help="Tags to be removed from TL.",
+)
+def remove(filename, tags):
+ """Remove Transfer Entries with given tags.
+
+ Remove Transfer Entries with given tags from a Transfer List."""
+ tl = TransferList.fromfile(filename)
+
+ for tag in tags:
+ tl.remove_tag(tag)
+ tl.write_to_file(filename)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "--entry",
+ type=(int, click.Path(exists=True)),
+ multiple=True,
+ help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
+)
+def add(filename, entry):
+ """Update an existing Transfer List with given images."""
+ tl = TransferList.fromfile(filename)
+
+ for id, path in entry:
+ tl.add_transfer_entry_from_file(id, path)
+
+ tl.write_to_file(filename)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "-C", type=click.Path(exists=True), help="Output directory for extracted images."
+)
+def unpack(filename, c):
+ """Unpack images from a Transfer List."""
+ tl = TransferList.fromfile(filename)
+ pwd = Path(".") if not c else Path(c)
+
+ for i, te in enumerate(tl.entries):
+ with open(pwd / f"te_{i}_{te.id}.bin", "wb") as f:
+ f.write(te.data)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+def validate(filename):
+ """Validate the contents of an existing Transfer List."""
+ TransferList.fromfile(filename)
+ print("Valid TL!")
diff --git a/tools/tlc/tlc/te.py b/tools/tlc/tlc/te.py
new file mode 100644
index 0000000..cf7aa67
--- /dev/null
+++ b/tools/tlc/tlc/te.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Module containing definitions pertaining to the 'Transfer Entry' (TE) type."""
+
+from typing import ClassVar
+
+import struct
+from dataclasses import dataclass
+
+
+@dataclass
+class TransferEntry:
+ """Class representing a Transfer Entry."""
+
+ id: int
+ data_size: int
+ data: bytes
+ hdr_size: int = 8
+ offset: int = 0
+ # Header encoding, with little-endian byte order.
+ encoding: ClassVar[str] = "<BI"
+
+ def __post_init__(self):
+ if self.id < 0 or self.id > 0xFFFFFF:
+ raise ValueError(
+ f"Out of bounds tag ID: {self.id:x}.\n"
+ f"Valid range is from 0 to 0xFFFFFF. Please ensure the tag ID is within this range."
+ )
+
+ def __str__(self) -> str:
+ return "\n".join(
+ [
+ f"{k:<10} {hex(v)}"
+ for k, v in vars(self).items()
+ if not isinstance(v, bytes)
+ ]
+ )
+
+ @property
+ def size(self) -> int:
+ return self.hdr_size + len(self.data)
+
+ @property
+ def sum_of_bytes(self) -> int:
+ return (sum(self.header_to_bytes()) + sum(self.data)) % 256
+
+ def header_to_bytes(self) -> bytes:
+ return self.id.to_bytes(3, "little") + struct.pack(
+ self.encoding, self.hdr_size, self.data_size
+ )
diff --git a/tools/tlc/tlc/tl.py b/tools/tlc/tlc/tl.py
new file mode 100644
index 0000000..3f0065d
--- /dev/null
+++ b/tools/tlc/tlc/tl.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Module containing definitions pertaining to the 'Transfer List' (TL) type."""
+
+import typing
+
+import math
+import struct
+from dataclasses import dataclass
+from functools import reduce
+from pathlib import Path
+
+from tlc.te import TransferEntry
+
+TRANSFER_LIST_ENABLE_CHECKSUM = 0b1
+
+# Description of each TE type. For each TE, there is a tag ID, a format (to be
+# used in struct.pack to encode the TE), and a list of field names that can
+# appear in the yaml file for that TE. Some fields are missing, if that TE has
+# to be processed differently, or if it can only be added with a blob file.
+transfer_entry_formats = {
+ 0: {
+ "tag_name": "empty",
+ "format": "4x",
+ "fields": [],
+ },
+ 1: {
+ "tag_name": "fdt",
+ },
+ 2: {
+ "tag_name": "hob_block",
+ },
+ 3: {
+ "tag_name": "hob_list",
+ },
+ 4: {
+ "tag_name": "acpi_table_aggregate",
+ },
+ 5: {
+ "tag_name": "tpm_event_log_table",
+ "fields": ["event_log", "flags"],
+ },
+ 6: {
+ "tag_name": "tpm_crb_base_address_table",
+ "format": "QI",
+ "fields": ["crb_base_address", "crb_size"],
+ },
+ 0x100: {
+ "tag_name": "optee_pageable_part",
+ "format": "Q",
+ "fields": ["pp_addr"],
+ },
+ 0x101: {
+ "tag_name": "dt_spmc_manifest",
+ },
+ 0x102: {
+ "tag_name": "exec_ep_info",
+ "format": "2BHIQI4x8Q",
+ "fields": ["ep_info"],
+ },
+ 0x104: {
+ "tag_name": "sram_layout",
+ "format": "2Q",
+ "fields": ["addr", "size"],
+ },
+}
+tag_name_to_tag_id = {
+ te["tag_name"]: tag_id for tag_id, te in transfer_entry_formats.items()
+}
+
+
+class TransferList:
+ """Class representing a Transfer List based on version 1.0 of the Firmware Handoff specification."""
+
+ # Header encoding, with little-endian byte order.
+ encoding = "<I4B4I"
+ hdr_size = 0x18
+ signature = 0x4A0FB10B
+ version = 1
+
+ def __init__(
+ self, max_size: int = hdr_size, flags: int = TRANSFER_LIST_ENABLE_CHECKSUM
+ ) -> None:
+ assert max_size >= self.hdr_size
+ self.checksum: int = 0
+ self.alignment: int = 3
+ self.size = self.hdr_size
+ self.total_size = max_size
+ self.flags = flags
+ self.entries: typing.List["TransferEntry"] = []
+ self.update_checksum()
+
+ def __str__(self) -> str:
+ return "\n".join(
+ [
+ f"{k:<10} {hex(v)}"
+ for k, v in vars(self).items()
+ if not isinstance(v, list)
+ ]
+ )
+
+ def get_transfer_entries_str(self):
+ return "\n----\n".join([str(te) for _, te in enumerate(self.entries)])
+
+ @classmethod
+ def fromfile(cls, filepath: Path) -> "TransferList":
+ tl = cls()
+
+ with open(filepath, "rb") as f:
+ (
+ tl.signature,
+ tl.checksum,
+ tl.version,
+ tl.hdr_size,
+ tl.alignment,
+ used_size,
+ tl.total_size,
+ tl.flags,
+ _,
+ ) = struct.unpack(
+ cls.encoding,
+ f.read(tl.hdr_size),
+ )
+
+ if tl.signature != TransferList.signature:
+ raise ValueError(f"Invalid TL signature 0x{tl.signature:x}!")
+ elif tl.version == 0 or tl.version > 0xFF:
+ raise ValueError(f"Invalid TL version 0x{tl.version:x}!")
+ else:
+ while tl.size < used_size:
+ # We add an extra padding byte into the header so we can extract
+ # the 3-byte wide ID as a 4-byte uint, shift out this padding
+ # once we have the id.
+ te_base = f.tell()
+ (id, hdr_size, data_size) = struct.unpack(
+ TransferEntry.encoding[0] + "I" + TransferEntry.encoding[1:],
+ b"\x00" + f.read(TransferEntry.hdr_size),
+ )
+
+ id >>= 8
+
+ te = tl.add_transfer_entry(id, f.read(data_size))
+ te.offset = te_base
+ f.seek(align(te_base + hdr_size + data_size, 2**tl.alignment))
+
+ return tl
+
+ @classmethod
+ def from_dict(cls, config: dict):
+ """Create a TL from data in a dictionary
+
+ The dictionary should have the same format as the yaml config files.
+ See the readme for more detail.
+
+ :param config: Dictionary containing the data described above.
+ """
+ # get settings from config and set defaults
+ max_size = config.get("max_size", 0x1000)
+ has_checksum = config.get("has_checksum", True)
+
+ flags = TRANSFER_LIST_ENABLE_CHECKSUM if has_checksum else 0
+
+ tl = cls(max_size, flags)
+
+ for entry in config["entries"]:
+ tl.add_transfer_entry_from_dict(entry)
+
+ return tl
+
+ def header_to_bytes(self) -> bytes:
+ return struct.pack(
+ self.encoding,
+ self.signature,
+ self.checksum,
+ self.version,
+ self.hdr_size,
+ self.alignment,
+ self.size,
+ self.total_size,
+ self.flags,
+ 0,
+ )
+
+ def update_checksum(self) -> None:
+ """Calculates the checksum based on the sum of bytes."""
+ self.checksum = 256 - ((self.sum_of_bytes() - self.checksum) % 256)
+
+ def sum_of_bytes(self) -> int:
+ """Sum of all bytes between the base address and the end of that last TE (modulo 0xff)."""
+ return (
+ sum(self.header_to_bytes()) + sum(te.sum_of_bytes for te in self.entries)
+ ) % 256
+
+ def get_entry_data_offset(self, tag_id: int) -> int:
+ """Returns offset of data of a TE from the base of the TL."""
+ for te in self.entries:
+ if te.id == tag_id:
+ return te.offset + te.hdr_size
+
+ raise ValueError(f"Tag {tag_id} not found in TL!")
+
+ def add_transfer_entry(self, tag_id: int, data: bytes) -> "TransferEntry":
+ """Appends a TransferEntry into the internal list of TE's."""
+ if not (self.total_size >= self.size + TransferEntry.hdr_size + len(data)):
+ raise MemoryError(
+ f"TL size has exceeded the maximum allocation {self.total_size}."
+ )
+ else:
+ te = TransferEntry(tag_id, len(data), data)
+ self.entries.append(te)
+ self.size += te.size
+ self.update_checksum()
+ return te
+
+ def add_transfer_entry_from_struct_format(
+ self, tag_id: int, struct_format: str, *args
+ ):
+ struct_format = "<" + struct_format
+ data = struct.pack(struct_format, *args)
+ return self.add_transfer_entry(tag_id, data)
+
+ def add_entry_point_info_transfer_entry(self, entry: dict) -> "TransferEntry":
+ """Add entry_point_info transfer entry
+
+ :param entry: Dictionary of the transfer entry, in the same format as
+ the YAML file.
+ """
+ ep_info = entry["ep_info"]
+ header = ep_info["h"]
+
+ # size of the entry_point_info struct
+ entry_point_size = 88
+
+ attr = header["attr"]
+ if type(attr) is str:
+ # convert string of flags names to an integer
+
+ # bit number | 0 | 1 |
+ # ------------|-----------------------|----------------------|
+ # 0 | secure | non-secure |
+ # 1 | little endian | big-endian |
+ # 2 | disable secure timer | enable secure timer |
+ # 3 | executable | non-executable |
+ # 4 | first exe | not first exe |
+ #
+ # Bit 5 and bit 0 are used to determine the security state.
+
+ flag_names = {
+ "EP_SECURE": 0x0,
+ "EP_NON_SECURE": 0x1,
+ "EP_REALM": 0x21,
+ "EP_EE_LITTLE": 0x0,
+ "EP_EE_BIG": 0x2,
+ "EP_ST_DISABLE": 0x0,
+ "EP_ST_ENABLE": 0x4,
+ "EP_NON_EXECUTABLE": 0x0,
+ "EP_EXECUTABLE": 0x8,
+ "EP_FIRST_EXE": 0x10,
+ }
+
+ # create list of integer flags, then bitwise-or them together
+ flags = [flag_names[f.strip()] for f in attr.split("|")]
+ attr = reduce(lambda x, y: x | y, flags)
+
+ return self.add_transfer_entry_from_struct_format(
+ 0x102,
+ transfer_entry_formats[0x102]["format"],
+ header["type"],
+ header["version"],
+ entry_point_size,
+ attr,
+ ep_info["pc"],
+ ep_info["spsr"],
+ *ep_info["args"],
+ )
+
+ def add_transfer_entry_from_dict(
+ self,
+ entry: dict,
+ ) -> "TransferEntry":
+ """Add a transfer entry from data in a dictionary
+
+ The dictionary should have the same format as the entries in the yaml
+ config files. See the readme for more detail.
+
+ :param entry: Dictionary containing the data described above.
+ """
+ # Tag_id is either a tag name or a tag id. Use it to get the TE format.
+ tag_id = entry["tag_id"]
+ if tag_id in tag_name_to_tag_id:
+ tag_id = tag_name_to_tag_id[tag_id]
+ te_format = transfer_entry_formats[tag_id]
+ tag_name = te_format["tag_name"]
+
+ if "blob_file_path" in entry:
+ return self.add_transfer_entry_from_file(tag_id, entry["blob_file_path"])
+ elif tag_name == "tpm_event_log_table":
+ with open(entry["event_log"], "rb") as f:
+ event_log_data = f.read()
+
+ flags_bytes = entry["flags"].to_bytes(4, "little")
+ data = flags_bytes + event_log_data
+
+ return self.add_transfer_entry(tag_id, data)
+ elif tag_name == "exec_ep_info":
+ return self.add_entry_point_info_transfer_entry(entry)
+ elif "format" in te_format and "fields" in te_format:
+ fields = [entry[field] for field in te_format["fields"]]
+ return self.add_transfer_entry_from_struct_format(
+ tag_id, te_format["format"], *fields
+ )
+ else:
+ raise ValueError(f"Invalid transfer entry {entry}.")
+
+ def add_transfer_entry_from_file(self, tag_id: int, path: Path) -> "TransferEntry":
+ with open(path, "rb") as f:
+ return self.add_transfer_entry(tag_id, f.read())
+
+ def write_to_file(self, file: Path) -> None:
+ """Write the contents of the TL to a file."""
+ with open(file, "wb") as f:
+ f.write(self.header_to_bytes())
+ for te in self.entries:
+ assert f.tell() + te.hdr_size + te.data_size < self.total_size
+ te_base = f.tell()
+ f.write(te.header_to_bytes())
+ f.write(te.data)
+ # Ensure the next TE has the correct alignment
+ f.write(
+ bytes(
+ (
+ align(
+ te_base + te.hdr_size + te.data_size, 2**self.alignment
+ )
+ - f.tell()
+ )
+ )
+ )
+
+ def remove_tag(self, tag: int) -> None:
+ self.entries = list(filter(lambda te: te.id != tag, self.entries))
+ self.size = self.hdr_size + sum(map(lambda te: te.size, self.entries))
+ self.update_checksum()
+
+
+def align(n, alignment):
+ return int(math.ceil(n / alignment) * alignment)