123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- /*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <common/debug.h>
- #if MEASURED_BOOT
- #include <common/desc_image_load.h>
- #endif
- #include <common/fdt_wrappers.h>
- #include <lib/fconf/fconf.h>
- #include <lib/fconf/fconf_dyn_cfg_getter.h>
- #include <libfdt.h>
- #include <plat/arm/common/arm_dyn_cfg_helpers.h>
- #include <plat/arm/common/plat_arm.h>
- #define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
- #define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
- #if MEASURED_BOOT
- #ifdef SPD_opteed
- /*
- * Currently OP-TEE does not support reading DTBs from Secure memory
- * and this property should be removed when this feature is supported.
- */
- #define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr"
- #endif /* SPD_opteed */
- #define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
- #define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
- #define DTB_PROP_HW_LOG_MAX_SIZE "tpm_event_log_max_size"
- #endif /* MEASURED_BOOT */
- static size_t event_log_max_size __unused;
- /*******************************************************************************
- * Validate the tb_fw_config is a valid DTB file and returns the node offset
- * to "arm,tb_fw" property.
- * Arguments:
- * void *dtb - pointer to the TB_FW_CONFIG in memory
- * int *node - Returns the node offset to "arm,tb_fw" property if found.
- *
- * Returns 0 on success and -1 on error.
- ******************************************************************************/
- int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
- {
- assert(dtb != NULL);
- assert(node != NULL);
- /* Check if the pointer to DT is correct */
- if (fdt_check_header(dtb) != 0) {
- WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG");
- return -1;
- }
- /* Assert the node offset point to "arm,tb_fw" compatible property */
- *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
- if (*node < 0) {
- WARN("The compatible property '%s' not%s", "arm,tb_fw",
- " found in the config\n");
- return -1;
- }
- VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n");
- return 0;
- }
- /*
- * This function writes the Mbed TLS heap address and size in the DTB. When it
- * is called, it is guaranteed that a DTB is available. However it is not
- * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
- * return error code from here and it's the responsibility of the caller to
- * determine the action upon error.
- *
- * This function is supposed to be called only by BL1.
- *
- * Returns:
- * 0 = success
- * -1 = error
- */
- int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size)
- {
- int dtb_root;
- /*
- * Verify that the DTB is valid, before attempting to write to it,
- * and get the DTB root node.
- */
- int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
- if (err < 0) {
- ERROR("Invalid%s loaded. Unable to get root node\n",
- " TB_FW_CONFIG");
- return -1;
- }
- /*
- * Write the heap address and size in the DTB.
- *
- * NOTE: The variables heap_addr and heap_size are corrupted
- * by the "fdtw_write_inplace_cells" function. After the
- * function calls they must NOT be reused.
- */
- err = fdtw_write_inplace_cells(dtb, dtb_root,
- DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR);
- return -1;
- }
- err = fdtw_write_inplace_cells(dtb, dtb_root,
- DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE);
- return -1;
- }
- return 0;
- }
- #if MEASURED_BOOT
- #if DICE_PROTECTION_ENVIRONMENT
- #include <common/desc_image_load.h>
- #define DTB_PROP_DPE_CTX_HANDLE "dpe_ctx_handle"
- static int arm_set_dpe_context_handle(uintptr_t config_base,
- int *ctx_handle)
- {
- /* As libfdt uses void *, we can't avoid this cast */
- void *dtb = (void *)config_base;
- const char *compatible = "arm,dpe_ctx_handle";
- int err, node;
- /*
- * Verify that the DTB is valid, before attempting to write to it,
- * and get the DTB root node.
- */
- /* Check if the pointer to DT is correct */
- err = fdt_check_header(dtb);
- if (err < 0) {
- WARN("Invalid DTB file passed\n");
- return err;
- }
- /* Assert the node offset point to compatible property */
- node = fdt_node_offset_by_compatible(dtb, -1, compatible);
- if (node < 0) {
- WARN("The compatible property '%s' not%s", compatible,
- " found in the config\n");
- return node;
- }
- VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
- err = fdtw_write_inplace_cells(dtb, node,
- DTB_PROP_DPE_CTX_HANDLE, 1, ctx_handle);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_DPE_CTX_HANDLE);
- } else {
- /*
- * Ensure that the info written to the DTB is visible
- * to other images.
- */
- flush_dcache_range(config_base, fdt_totalsize(dtb));
- }
- return err;
- }
- /*
- * This function writes the DPE context handle value to the NT_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- int arm_set_nt_fw_info(int *ctx_handle)
- {
- uintptr_t config_base;
- const bl_mem_params_node_t *cfg_mem_params;
- /* Get the config load address and size from NT_FW_CONFIG */
- cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
- assert(cfg_mem_params != NULL);
- config_base = cfg_mem_params->image_info.image_base;
- /* Write the context handle value in the DTB */
- return arm_set_dpe_context_handle(config_base, ctx_handle);
- }
- /*
- * This function writes the DPE context handle value to the TB_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL1.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- int arm_set_tb_fw_info(int *ctx_handle)
- {
- /*
- * Read tb_fw_config device tree for Event Log properties
- * and write the Event Log address and its size in the DTB
- */
- const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
- uintptr_t tb_fw_cfg_dtb;
- tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
- assert(tb_fw_config_info != NULL);
- tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
- /* Write the context handle value in the DTB */
- return arm_set_dpe_context_handle(tb_fw_cfg_dtb, ctx_handle);
- }
- /*
- * This function reads the initial DPE context handle from TB_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- int arm_get_tb_fw_info(int *ctx_handle)
- {
- /* As libfdt uses void *, we can't avoid this cast */
- const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
- int node, rc;
- tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
- assert(tb_fw_config_info != NULL);
- void *dtb = (void *)tb_fw_config_info->config_addr;
- const char *compatible = "arm,dpe_ctx_handle";
- /* Assert the node offset point to compatible property */
- node = fdt_node_offset_by_compatible(dtb, -1, compatible);
- if (node < 0) {
- WARN("The compatible property '%s'%s", compatible,
- " not specified in TB_FW config.\n");
- return node;
- }
- VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
- rc = fdt_read_uint32(dtb, node, DTB_PROP_DPE_CTX_HANDLE, (uint32_t *)ctx_handle);
- if (rc != 0) {
- ERROR("%s%s", DTB_PROP_DPE_CTX_HANDLE,
- " not specified in TB_FW config.\n");
- }
- return rc;
- }
- #else
- /*
- * Write the Event Log address and its size in the DTB.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- static int arm_set_event_log_info(uintptr_t config_base,
- #ifdef SPD_opteed
- uintptr_t sm_log_addr,
- #endif
- uintptr_t log_addr, size_t log_size)
- {
- /* As libfdt uses void *, we can't avoid this cast */
- void *dtb = (void *)config_base;
- const char *compatible = "arm,tpm_event_log";
- int err, node;
- /*
- * Verify that the DTB is valid, before attempting to write to it,
- * and get the DTB root node.
- */
- /* Check if the pointer to DT is correct */
- err = fdt_check_header(dtb);
- if (err < 0) {
- WARN("Invalid DTB file passed\n");
- return err;
- }
- /* Assert the node offset point to compatible property */
- node = fdt_node_offset_by_compatible(dtb, -1, compatible);
- if (node < 0) {
- WARN("The compatible property '%s' not%s", compatible,
- " found in the config\n");
- return node;
- }
- VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
- #ifdef SPD_opteed
- if (sm_log_addr != 0UL) {
- err = fdtw_write_inplace_cells(dtb, node,
- DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR);
- return err;
- }
- }
- #endif
- err = fdtw_write_inplace_cells(dtb, node,
- DTB_PROP_HW_LOG_ADDR, 2, &log_addr);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_HW_LOG_ADDR);
- return err;
- }
- assert(event_log_max_size != 0U);
- err = fdtw_write_inplace_cells(dtb, node,
- DTB_PROP_HW_LOG_MAX_SIZE, 1,
- &event_log_max_size);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_HW_LOG_MAX_SIZE);
- return err;
- }
- err = fdtw_write_inplace_cells(dtb, node,
- DTB_PROP_HW_LOG_SIZE, 1, &log_size);
- if (err < 0) {
- ERROR("%sDTB property '%s'\n",
- "Unable to write ", DTB_PROP_HW_LOG_SIZE);
- } else {
- /*
- * Ensure that the info written to the DTB is visible
- * to other images.
- */
- flush_dcache_range(config_base, fdt_totalsize(dtb));
- }
- return err;
- }
- /*
- * This function writes the Event Log address and its size
- * in the TOS_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size)
- {
- uintptr_t config_base;
- const bl_mem_params_node_t *cfg_mem_params;
- int err;
- assert(log_addr != 0UL);
- /* Get the config load address and size of TOS_FW_CONFIG */
- cfg_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
- assert(cfg_mem_params != NULL);
- config_base = cfg_mem_params->image_info.image_base;
- /* Write the Event Log address and its size in the DTB */
- err = arm_set_event_log_info(config_base,
- #ifdef SPD_opteed
- 0UL,
- #endif
- log_addr, log_size);
- if (err < 0) {
- ERROR("%sEvent Log data to TOS_FW_CONFIG\n",
- "Unable to write ");
- }
- return err;
- }
- /*
- * This function writes the Event Log address and its size
- * in the NT_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- int arm_set_nt_fw_info(
- #ifdef SPD_opteed
- uintptr_t log_addr,
- #endif
- size_t log_size, uintptr_t *ns_log_addr)
- {
- uintptr_t config_base;
- uintptr_t ns_addr;
- const bl_mem_params_node_t *cfg_mem_params;
- int err;
- assert(ns_log_addr != NULL);
- /* Get the config load address and size from NT_FW_CONFIG */
- cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
- assert(cfg_mem_params != NULL);
- config_base = cfg_mem_params->image_info.image_base;
- /* Calculate Event Log address in Non-secure memory */
- ns_addr = cfg_mem_params->image_info.image_base +
- cfg_mem_params->image_info.image_max_size;
- /* Check for memory space */
- if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) {
- return -1;
- }
- /* Write the Event Log address and its size in the DTB */
- err = arm_set_event_log_info(config_base,
- #ifdef SPD_opteed
- log_addr,
- #endif
- ns_addr, log_size);
- /* Return Event Log address in Non-secure memory */
- *ns_log_addr = (err < 0) ? 0UL : ns_addr;
- return err;
- }
- /*
- * This function writes the Event Log address and its size
- * in the TB_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL1.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- */
- int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size, size_t log_max_size)
- {
- /*
- * Read tb_fw_config device tree for Event Log properties
- * and write the Event Log address and its size in the DTB
- */
- const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
- uintptr_t tb_fw_cfg_dtb;
- int err;
- tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
- assert(tb_fw_config_info != NULL);
- tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
- event_log_max_size = log_max_size;
- err = arm_set_event_log_info(tb_fw_cfg_dtb,
- #ifdef SPD_opteed
- 0UL,
- #endif
- log_addr, log_size);
- return err;
- }
- /*
- * This function reads the Event Log address and its size
- * properties present in TB_FW_CONFIG DTB.
- *
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- * 0 = success
- * < 0 = error
- * Alongside returns Event Log address and its size.
- */
- int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size,
- size_t *log_max_size)
- {
- /* As libfdt uses void *, we can't avoid this cast */
- const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
- int node, rc;
- tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
- assert(tb_fw_config_info != NULL);
- void *dtb = (void *)tb_fw_config_info->config_addr;
- const char *compatible = "arm,tpm_event_log";
- /* Assert the node offset point to compatible property */
- node = fdt_node_offset_by_compatible(dtb, -1, compatible);
- if (node < 0) {
- WARN("The compatible property '%s'%s", compatible,
- " not specified in TB_FW config.\n");
- return node;
- }
- VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
- rc = fdt_read_uint64(dtb, node, DTB_PROP_HW_LOG_ADDR, log_addr);
- if (rc != 0) {
- ERROR("%s%s", DTB_PROP_HW_LOG_ADDR,
- " not specified in TB_FW config.\n");
- return rc;
- }
- rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_SIZE, (uint32_t *)log_size);
- if (rc != 0) {
- ERROR("%s%s", DTB_PROP_HW_LOG_SIZE,
- " not specified in TB_FW config.\n");
- return rc;
- }
- rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_MAX_SIZE,
- (uint32_t *)log_max_size);
- if (rc != 0) {
- ERROR("%s%s", DTB_PROP_HW_LOG_MAX_SIZE,
- " not specified in TB_FW config.\n");
- return rc;
- } else {
- event_log_max_size = *log_max_size;
- }
- return rc;
- }
- #endif /* DICE_PROTECTION_ENVIRONMENT */
- #endif /* MEASURED_BOOT */
|