1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2022, Linaro. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <arch_helpers.h> 11*91f16700Schasinglulu #if MEASURED_BOOT 12*91f16700Schasinglulu #include <common/desc_image_load.h> 13*91f16700Schasinglulu #endif 14*91f16700Schasinglulu #include <common/fdt_wrappers.h> 15*91f16700Schasinglulu #include <libfdt.h> 16*91f16700Schasinglulu #include <platform_def.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr" 19*91f16700Schasinglulu #define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size" 20*91f16700Schasinglulu 21*91f16700Schasinglulu #if MEASURED_BOOT 22*91f16700Schasinglulu 23*91f16700Schasinglulu static int imx8m_event_log_fdt_init_overlay(uintptr_t dt_base, int dt_size) 24*91f16700Schasinglulu { 25*91f16700Schasinglulu int ret; 26*91f16700Schasinglulu int offset; 27*91f16700Schasinglulu void *dtb = (void *)dt_base; 28*91f16700Schasinglulu 29*91f16700Schasinglulu ret = fdt_create_empty_tree(dtb, dt_size); 30*91f16700Schasinglulu if (ret < 0) { 31*91f16700Schasinglulu ERROR("cannot create empty dtb tree: %s\n", 32*91f16700Schasinglulu fdt_strerror(ret)); 33*91f16700Schasinglulu return ret; 34*91f16700Schasinglulu } 35*91f16700Schasinglulu 36*91f16700Schasinglulu offset = fdt_path_offset(dtb, "/"); 37*91f16700Schasinglulu if (offset < 0) { 38*91f16700Schasinglulu ERROR("cannot find root of the tree: %s\n", 39*91f16700Schasinglulu fdt_strerror(offset)); 40*91f16700Schasinglulu return offset; 41*91f16700Schasinglulu } 42*91f16700Schasinglulu 43*91f16700Schasinglulu offset = fdt_add_subnode(dtb, offset, "fragment@0"); 44*91f16700Schasinglulu if (offset < 0) { 45*91f16700Schasinglulu ERROR("cannot add fragment node: %s\n", 46*91f16700Schasinglulu fdt_strerror(offset)); 47*91f16700Schasinglulu return offset; 48*91f16700Schasinglulu } 49*91f16700Schasinglulu 50*91f16700Schasinglulu ret = fdt_setprop_string(dtb, offset, "target-path", "/"); 51*91f16700Schasinglulu if (ret < 0) { 52*91f16700Schasinglulu ERROR("cannot set target-path property: %s\n", 53*91f16700Schasinglulu fdt_strerror(ret)); 54*91f16700Schasinglulu return ret; 55*91f16700Schasinglulu } 56*91f16700Schasinglulu 57*91f16700Schasinglulu offset = fdt_add_subnode(dtb, offset, "__overlay__"); 58*91f16700Schasinglulu if (offset < 0) { 59*91f16700Schasinglulu ERROR("cannot add __overlay__ node: %s\n", 60*91f16700Schasinglulu fdt_strerror(offset)); 61*91f16700Schasinglulu return ret; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu offset = fdt_add_subnode(dtb, offset, "tpm_event_log"); 65*91f16700Schasinglulu if (offset < 0) { 66*91f16700Schasinglulu ERROR("cannot add tpm_event_log node: %s\n", 67*91f16700Schasinglulu fdt_strerror(offset)); 68*91f16700Schasinglulu return offset; 69*91f16700Schasinglulu } 70*91f16700Schasinglulu 71*91f16700Schasinglulu ret = fdt_setprop_string(dtb, offset, "compatible", 72*91f16700Schasinglulu "arm,tpm_event_log"); 73*91f16700Schasinglulu if (ret < 0) { 74*91f16700Schasinglulu ERROR("cannot set compatible property: %s\n", 75*91f16700Schasinglulu fdt_strerror(ret)); 76*91f16700Schasinglulu return ret; 77*91f16700Schasinglulu } 78*91f16700Schasinglulu 79*91f16700Schasinglulu ret = fdt_setprop_u64(dtb, offset, "tpm_event_log_addr", 0); 80*91f16700Schasinglulu if (ret < 0) { 81*91f16700Schasinglulu ERROR("cannot set tpm_event_log_addr property: %s\n", 82*91f16700Schasinglulu fdt_strerror(ret)); 83*91f16700Schasinglulu return ret; 84*91f16700Schasinglulu } 85*91f16700Schasinglulu 86*91f16700Schasinglulu ret = fdt_setprop_u32(dtb, offset, "tpm_event_log_size", 0); 87*91f16700Schasinglulu if (ret < 0) { 88*91f16700Schasinglulu ERROR("cannot set tpm_event_log_size property: %s\n", 89*91f16700Schasinglulu fdt_strerror(ret)); 90*91f16700Schasinglulu return ret; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu return ret; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu /* 97*91f16700Schasinglulu * Write the Event Log address and its size in the DTB. 98*91f16700Schasinglulu * 99*91f16700Schasinglulu * This function is supposed to be called only by BL2. 100*91f16700Schasinglulu * 101*91f16700Schasinglulu * Returns: 102*91f16700Schasinglulu * 0 = success 103*91f16700Schasinglulu * < 0 = error 104*91f16700Schasinglulu */ 105*91f16700Schasinglulu static int imx8m_set_event_log_info(uintptr_t config_base, 106*91f16700Schasinglulu uintptr_t log_addr, size_t log_size) 107*91f16700Schasinglulu { 108*91f16700Schasinglulu /* As libfdt uses void *, we can't avoid this cast */ 109*91f16700Schasinglulu void *dtb = (void *)config_base; 110*91f16700Schasinglulu const char *compatible_tpm = "arm,tpm_event_log"; 111*91f16700Schasinglulu uint64_t base = cpu_to_fdt64(log_addr); 112*91f16700Schasinglulu uint32_t sz = cpu_to_fdt32(log_size); 113*91f16700Schasinglulu int err, node; 114*91f16700Schasinglulu 115*91f16700Schasinglulu err = fdt_open_into(dtb, dtb, PLAT_IMX8M_DTO_MAX_SIZE); 116*91f16700Schasinglulu if (err < 0) { 117*91f16700Schasinglulu ERROR("Invalid Device Tree at %p: error %d\n", dtb, err); 118*91f16700Schasinglulu return err; 119*91f16700Schasinglulu } 120*91f16700Schasinglulu 121*91f16700Schasinglulu /* 122*91f16700Schasinglulu * Verify that the DTB is valid, before attempting to write to it, 123*91f16700Schasinglulu * and get the DTB root node. 124*91f16700Schasinglulu */ 125*91f16700Schasinglulu 126*91f16700Schasinglulu /* Check if the pointer to DT is correct */ 127*91f16700Schasinglulu err = fdt_check_header(dtb); 128*91f16700Schasinglulu if (err < 0) { 129*91f16700Schasinglulu WARN("Invalid DTB file passed\n"); 130*91f16700Schasinglulu return err; 131*91f16700Schasinglulu } 132*91f16700Schasinglulu 133*91f16700Schasinglulu /* 134*91f16700Schasinglulu * Find the TPM node in device tree. 135*91f16700Schasinglulu */ 136*91f16700Schasinglulu node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm); 137*91f16700Schasinglulu if (node < 0) { 138*91f16700Schasinglulu ERROR("The compatible property '%s' not%s", compatible_tpm, 139*91f16700Schasinglulu " found in the config\n"); 140*91f16700Schasinglulu return node; 141*91f16700Schasinglulu } 142*91f16700Schasinglulu 143*91f16700Schasinglulu err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8); 144*91f16700Schasinglulu if (err < 0) { 145*91f16700Schasinglulu ERROR("Failed to add log addr err %d\n", err); 146*91f16700Schasinglulu return err; 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4); 150*91f16700Schasinglulu if (err < 0) { 151*91f16700Schasinglulu ERROR("Failed to add log addr err %d\n", err); 152*91f16700Schasinglulu return err; 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu err = fdt_pack(dtb); 156*91f16700Schasinglulu if (err < 0) { 157*91f16700Schasinglulu ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, err); 158*91f16700Schasinglulu return err; 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu /* 162*91f16700Schasinglulu * Ensure that the info written to the DTB is visible 163*91f16700Schasinglulu * to other images. 164*91f16700Schasinglulu */ 165*91f16700Schasinglulu flush_dcache_range(config_base, fdt_totalsize(dtb)); 166*91f16700Schasinglulu 167*91f16700Schasinglulu return err; 168*91f16700Schasinglulu } 169*91f16700Schasinglulu 170*91f16700Schasinglulu /* 171*91f16700Schasinglulu * This function writes the Event Log address and its size 172*91f16700Schasinglulu * in the QEMU DTB. 173*91f16700Schasinglulu * 174*91f16700Schasinglulu * This function is supposed to be called only by BL2. 175*91f16700Schasinglulu * 176*91f16700Schasinglulu * Returns: 177*91f16700Schasinglulu * 0 = success 178*91f16700Schasinglulu * < 0 = error 179*91f16700Schasinglulu */ 180*91f16700Schasinglulu int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr) 181*91f16700Schasinglulu { 182*91f16700Schasinglulu uintptr_t ns_addr; 183*91f16700Schasinglulu int err; 184*91f16700Schasinglulu 185*91f16700Schasinglulu assert(ns_log_addr != NULL); 186*91f16700Schasinglulu 187*91f16700Schasinglulu ns_addr = PLAT_IMX8M_DTO_BASE + PLAT_IMX8M_DTO_MAX_SIZE; 188*91f16700Schasinglulu 189*91f16700Schasinglulu imx8m_event_log_fdt_init_overlay(PLAT_IMX8M_DTO_BASE, 190*91f16700Schasinglulu PLAT_IMX8M_DTO_MAX_SIZE); 191*91f16700Schasinglulu 192*91f16700Schasinglulu /* Write the Event Log address and its size in the DTB */ 193*91f16700Schasinglulu err = imx8m_set_event_log_info(PLAT_IMX8M_DTO_BASE, 194*91f16700Schasinglulu ns_addr, log_size); 195*91f16700Schasinglulu 196*91f16700Schasinglulu /* Return Event Log address in Non-secure memory */ 197*91f16700Schasinglulu *ns_log_addr = (err < 0) ? 0UL : ns_addr; 198*91f16700Schasinglulu return err; 199*91f16700Schasinglulu } 200*91f16700Schasinglulu 201*91f16700Schasinglulu #endif /* MEASURED_BOOT */ 202