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