Merge "fix(ast2700): fix mpll calculate statement" into integration
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/docs/tools/transfer-list-compiler.rst b/docs/tools/transfer-list-compiler.rst
index c8ef7ac..fa660dc 100644
--- a/docs/tools/transfer-list-compiler.rst
+++ b/docs/tools/transfer-list-compiler.rst
@@ -59,6 +59,12 @@
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -186,9 +192,120 @@
#. 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/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/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 71b3cb1..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,11 +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";
@@ -111,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/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/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/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..9f0b190 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1303,7 +1303,7 @@
* before exiting coherency.
*/
if (is_feat_spe_supported()) {
- spe_disable();
+ spe_stop();
}
}
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 51d696c..bd3faec 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -8,6 +8,7 @@
#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.
@@ -19,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/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 632e84c..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) {
@@ -142,8 +149,8 @@
bl33_image_ep_info.args.arg0 =
FW_NS_HANDOFF_BASE + ARM_PRELOADED_DTB_OFFSET;
- bl33_image_ep_info.args.arg1 = TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
+ 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;
@@ -357,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();
@@ -399,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
@@ -516,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 || RESET_TO_BL31)
- 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_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/poetry.lock b/poetry.lock
index 31590de..b465f48 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -251,13 +251,13 @@
[[package]]
name = "importlib-metadata"
-version = "8.1.0"
+version = "8.2.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-8.1.0-py3-none-any.whl", hash = "sha256:3cd29f739ed65973840b068e3132135ce954c254d48b5b640484467ef7ab3c8c"},
- {file = "importlib_metadata-8.1.0.tar.gz", hash = "sha256:fcdcb1d5ead7bdf3dd32657bb94ebe9d2aabfe89a19782ddc32da5041d6ebfb4"},
+ {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]
@@ -447,13 +447,13 @@
[[package]]
name = "pip"
-version = "24.1.2"
+version = "24.2"
description = "The PyPA recommended tool for installing Python packages."
optional = false
python-versions = ">=3.8"
files = [
- {file = "pip-24.1.2-py3-none-any.whl", hash = "sha256:7cd207eed4c60b0f411b444cd1464198fe186671c323b6cd6d433ed80fc9d247"},
- {file = "pip-24.1.2.tar.gz", hash = "sha256:e5458a0b89f2755e0ee8c0c77613fe5273e05f337907874d64f13171a898a7ff"},
+ {file = "pip-24.2-py3-none-any.whl", hash = "sha256:2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2"},
+ {file = "pip-24.2.tar.gz", hash = "sha256:5b5e490b5e9cb275c879595064adce9ebd31b854e3e803740b72f9ccf34a45b8"},
]
[[package]]
@@ -645,13 +645,13 @@
[[package]]
name = "setuptools"
-version = "71.1.0"
+version = "72.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"},
- {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"},
+ {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
+ {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
]
[package.extras]
@@ -893,6 +893,7 @@
[package.dependencies]
click = "^8.1.7"
+pyyaml = "^6.0.1"
rich = "^10.14.0"
typer = {version = "^0.4.0", extras = ["all"]}
@@ -1004,4 +1005,4 @@
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "3dd9c0d7ea3f1ef33abf600002406dbe51dba2e4ed21175b1f1e7ac64cd0e387"
+content-hash = "8798a2d1efd456c3b68ae464a216f015afaa1bbb653a905148bef17ab8ce278e"
diff --git a/pyproject.toml b/pyproject.toml
index d7d2efa..03d898e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,7 +16,10 @@
python = "^3.8"
tlc = {path = "tools/tlc"}
-[tool.poetry.group.doc.dependencies]
+[tool.poetry.group.docs]
+optional = true
+
+[tool.poetry.group.docs.dependencies]
sphinx = "^5.3.0"
myst-parser = "^0.18.1"
sphinxcontrib-plantuml = "^0.24.1"
diff --git a/tools/tlc/assets/images/coverage.svg b/tools/tlc/assets/images/coverage.svg
index 3438732..b6c4e36 100644
--- a/tools/tlc/assets/images/coverage.svg
+++ b/tools/tlc/assets/images/coverage.svg
@@ -15,7 +15,7 @@
<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">97%</text>
- <text x="80" y="14">97%</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
index 5a39322..839f236 100644
--- a/tools/tlc/poetry.lock
+++ b/tools/tlc/poetry.lock
@@ -386,13 +386,13 @@
[[package]]
name = "exceptiongroup"
-version = "1.2.1"
+version = "1.2.2"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"},
- {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"},
+ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
+ {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[package.extras]
@@ -1107,18 +1107,19 @@
[[package]]
name = "setuptools"
-version = "70.2.0"
+version = "72.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "setuptools-70.2.0-py3-none-any.whl", hash = "sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05"},
- {file = "setuptools-70.2.0.tar.gz", hash = "sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1"},
+ {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.10.0)", "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.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+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"
@@ -1191,13 +1192,13 @@
[[package]]
name = "tomlkit"
-version = "0.12.5"
+version = "0.13.0"
description = "Style preserving TOML library"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"},
- {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"},
+ {file = "tomlkit-0.13.0-py3-none-any.whl", hash = "sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"},
+ {file = "tomlkit-0.13.0.tar.gz", hash = "sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72"},
]
[[package]]
@@ -1352,4 +1353,4 @@
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "60bdb4a8b67815f01b4e7089d9f7664afcb9041fa8adf5aa92d977f4e2d5b4b2"
+content-hash = "cfcb196cda412f6139302937640455aa8154d7979c69017fe45ddd528e4a1bf2"
diff --git a/tools/tlc/pyproject.toml b/tools/tlc/pyproject.toml
index 30875a5..5661abf 100644
--- a/tools/tlc/pyproject.toml
+++ b/tools/tlc/pyproject.toml
@@ -37,6 +37,7 @@
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"
diff --git a/tools/tlc/tests/conftest.py b/tools/tlc/tests/conftest.py
index 6b28e43..b8f88b5 100644
--- a/tools/tlc/tests/conftest.py
+++ b/tools/tlc/tests/conftest.py
@@ -10,6 +10,7 @@
""" Common configurations and fixtures for test environment."""
import pytest
+import yaml
from click.testing import CliRunner
from tlc.cli import cli
@@ -21,12 +22,43 @@
@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()
diff --git a/tools/tlc/tests/test_cli.py b/tools/tlc/tests/test_cli.py
index d79773b..99b5816 100644
--- a/tools/tlc/tests/test_cli.py
+++ b/tools/tlc/tests/test_cli.py
@@ -11,8 +11,11 @@
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
@@ -203,3 +206,208 @@
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/tlc/cli.py b/tools/tlc/tlc/cli.py
index e574e59..1d4949d 100644
--- a/tools/tlc/tlc/cli.py
+++ b/tools/tlc/tlc/cli.py
@@ -12,6 +12,7 @@
from pathlib import Path
import click
+import yaml
from tlc.tl import *
@@ -44,15 +45,26 @@
show_default=True,
help="Settings for the TL's properties.",
)
-def create(filename, size, fdt, entry, flags):
+@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."""
- tl = TransferList(size)
+ try:
+ if from_yaml:
+ with open(from_yaml, "r") as f:
+ config = yaml.safe_load(f)
- entry = (*entry, (1, fdt)) if fdt else entry
+ tl = TransferList.from_dict(config)
+ else:
+ tl = TransferList(size)
- try:
- for id, path in entry:
- tl.add_transfer_entry_from_file(id, path)
+ 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"
diff --git a/tools/tlc/tlc/tl.py b/tools/tlc/tlc/tl.py
index a409651..3f0065d 100644
--- a/tools/tlc/tlc/tl.py
+++ b/tools/tlc/tlc/tl.py
@@ -13,12 +13,67 @@
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."""
@@ -96,6 +151,28 @@
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,
@@ -141,6 +218,106 @@
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())