11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2a4f139d7SJerome Forissier /* 3a4f139d7SJerome Forissier * Copyright (c) 2016, Linaro Limited 4a4f139d7SJerome Forissier */ 5a4f139d7SJerome Forissier 67ba16abbSJerome Forissier #include <assert.h> 7e6027f48SAlvin Chang #include <config.h> 8e6027f48SAlvin Chang #include <initcall.h> 9a4f139d7SJerome Forissier #include <kernel/dt.h> 109e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 117acb3a47SLudovic Barre #include <kernel/interrupt.h> 129fe4c797SJerome Forissier #include <libfdt.h> 137ba16abbSJerome Forissier #include <mm/core_memprot.h> 147ba16abbSJerome Forissier #include <mm/core_mmu.h> 15e6027f48SAlvin Chang #include <stdio.h> 16a4f139d7SJerome Forissier #include <string.h> 177ba16abbSJerome Forissier #include <trace.h> 18a4f139d7SJerome Forissier 19e6027f48SAlvin Chang static struct dt_descriptor external_dt __nex_bss; 20e6027f48SAlvin Chang 214bc2c5f0SSungbae Yoo #if defined(CFG_CORE_FFA) 224bc2c5f0SSungbae Yoo static void *manifest_dt __nex_bss; 234bc2c5f0SSungbae Yoo #endif 244bc2c5f0SSungbae Yoo 25a4f139d7SJerome Forissier const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs) 26a4f139d7SJerome Forissier { 27a4f139d7SJerome Forissier const struct dt_device_match *dm; 28a4f139d7SJerome Forissier const struct dt_driver *drv; 29a4f139d7SJerome Forissier 30db783ff8SEtienne Carriere for_each_dt_driver(drv) { 31db783ff8SEtienne Carriere for (dm = drv->match_table; dm; dm++) { 32db783ff8SEtienne Carriere if (!dm->compatible) { 33db783ff8SEtienne Carriere break; 34db783ff8SEtienne Carriere } 35a4f139d7SJerome Forissier if (!fdt_node_check_compatible(fdt, offs, 36db783ff8SEtienne Carriere dm->compatible)) { 37a4f139d7SJerome Forissier return drv; 38db783ff8SEtienne Carriere } 39db783ff8SEtienne Carriere } 40db783ff8SEtienne Carriere } 41a4f139d7SJerome Forissier 42a4f139d7SJerome Forissier return NULL; 43a4f139d7SJerome Forissier } 44a4f139d7SJerome Forissier 4550f3b323SPeng Fan bool dt_have_prop(const void *fdt, int offs, const char *propname) 4650f3b323SPeng Fan { 4750f3b323SPeng Fan const void *prop; 4850f3b323SPeng Fan 4950f3b323SPeng Fan prop = fdt_getprop(fdt, offs, propname, NULL); 5050f3b323SPeng Fan 5150f3b323SPeng Fan return prop; 5250f3b323SPeng Fan } 5350f3b323SPeng Fan 5495cdc5e0SCedric Neveux int dt_disable_status(void *fdt, int node) 5595cdc5e0SCedric Neveux { 5695cdc5e0SCedric Neveux const char *prop = NULL; 5795cdc5e0SCedric Neveux int len = 0; 5895cdc5e0SCedric Neveux 5995cdc5e0SCedric Neveux prop = fdt_getprop(fdt, node, "status", &len); 6095cdc5e0SCedric Neveux if (!prop) { 6195cdc5e0SCedric Neveux if (fdt_setprop_string(fdt, node, "status", "disabled")) 6295cdc5e0SCedric Neveux return -1; 6395cdc5e0SCedric Neveux } else { 6495cdc5e0SCedric Neveux /* 6595cdc5e0SCedric Neveux * Status is there, modify it. 6695cdc5e0SCedric Neveux * Ask to set "disabled" value to the property. The value 6795cdc5e0SCedric Neveux * will be automatically truncated with "len" size by the 6895cdc5e0SCedric Neveux * fdt_setprop_inplace function. 6995cdc5e0SCedric Neveux * Setting a value different from "ok" or "okay" will disable 7095cdc5e0SCedric Neveux * the property. 7195cdc5e0SCedric Neveux * Setting a truncated value of "disabled" with the original 7295cdc5e0SCedric Neveux * property "len" is preferred to not increase the DT size and 7395cdc5e0SCedric Neveux * losing time in recalculating the overall DT offsets. 7495cdc5e0SCedric Neveux * If original length of the status property is larger than 7595cdc5e0SCedric Neveux * "disabled", the property will start with "disabled" and be 7695cdc5e0SCedric Neveux * completed with the rest of the original property. 7795cdc5e0SCedric Neveux */ 7895cdc5e0SCedric Neveux if (fdt_setprop_inplace(fdt, node, "status", "disabled", len)) 7995cdc5e0SCedric Neveux return -1; 8095cdc5e0SCedric Neveux } 8195cdc5e0SCedric Neveux 8295cdc5e0SCedric Neveux return 0; 8395cdc5e0SCedric Neveux } 8495cdc5e0SCedric Neveux 8595cdc5e0SCedric Neveux int dt_enable_secure_status(void *fdt, int node) 8695cdc5e0SCedric Neveux { 8795cdc5e0SCedric Neveux if (dt_disable_status(fdt, node)) { 8895cdc5e0SCedric Neveux EMSG("Unable to disable Normal Status"); 8995cdc5e0SCedric Neveux return -1; 9095cdc5e0SCedric Neveux } 9195cdc5e0SCedric Neveux 9295cdc5e0SCedric Neveux if (fdt_setprop_string(fdt, node, "secure-status", "okay")) 9395cdc5e0SCedric Neveux return -1; 9495cdc5e0SCedric Neveux 9595cdc5e0SCedric Neveux return 0; 9695cdc5e0SCedric Neveux } 9795cdc5e0SCedric Neveux 98a5d5bbc8SVesa Jääskeläinen int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, 99a5d5bbc8SVesa Jääskeläinen enum dt_map_dev_directive mapping) 1007ba16abbSJerome Forissier { 1017ba16abbSJerome Forissier enum teecore_memtypes mtype; 1027ba16abbSJerome Forissier paddr_t pbase; 1037ba16abbSJerome Forissier vaddr_t vbase; 104df7cecc0SLionel Debieve size_t sz; 1057ba16abbSJerome Forissier int st; 1067ba16abbSJerome Forissier 1077ba16abbSJerome Forissier assert(cpu_mmu_enabled()); 1087ba16abbSJerome Forissier 109f354a5d8SGatien Chevallier st = fdt_get_status(fdt, offs); 1107ba16abbSJerome Forissier if (st == DT_STATUS_DISABLED) 1117ba16abbSJerome Forissier return -1; 1127ba16abbSJerome Forissier 113f354a5d8SGatien Chevallier pbase = fdt_reg_base_address(fdt, offs); 114c0cfb36cSEtienne Carriere if (pbase == DT_INFO_INVALID_REG) 1157ba16abbSJerome Forissier return -1; 116f354a5d8SGatien Chevallier sz = fdt_reg_size(fdt, offs); 117df7cecc0SLionel Debieve if (sz == DT_INFO_INVALID_REG_SIZE) 1187ba16abbSJerome Forissier return -1; 1197ba16abbSJerome Forissier 120a5d5bbc8SVesa Jääskeläinen switch (mapping) { 121a5d5bbc8SVesa Jääskeläinen case DT_MAP_AUTO: 1227ba16abbSJerome Forissier if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC)) 1237ba16abbSJerome Forissier mtype = MEM_AREA_IO_SEC; 1247ba16abbSJerome Forissier else 1257ba16abbSJerome Forissier mtype = MEM_AREA_IO_NSEC; 126a5d5bbc8SVesa Jääskeläinen break; 127a5d5bbc8SVesa Jääskeläinen case DT_MAP_SECURE: 128a5d5bbc8SVesa Jääskeläinen mtype = MEM_AREA_IO_SEC; 129a5d5bbc8SVesa Jääskeläinen break; 130a5d5bbc8SVesa Jääskeläinen case DT_MAP_NON_SECURE: 131a5d5bbc8SVesa Jääskeläinen mtype = MEM_AREA_IO_NSEC; 132a5d5bbc8SVesa Jääskeläinen break; 133a5d5bbc8SVesa Jääskeläinen default: 134a5d5bbc8SVesa Jääskeläinen panic("Invalid mapping specified"); 135a5d5bbc8SVesa Jääskeläinen break; 136a5d5bbc8SVesa Jääskeläinen } 1377ba16abbSJerome Forissier 1387ba16abbSJerome Forissier /* Check if we have a mapping, create one if needed */ 139bc9618c0SAnton Rybakov vbase = (vaddr_t)core_mmu_add_mapping(mtype, pbase, sz); 140bc9618c0SAnton Rybakov if (!vbase) { 1417ba16abbSJerome Forissier EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, 14223b1daf4SPeng Fan (size_t)sz, pbase); 1437ba16abbSJerome Forissier return -1; 1447ba16abbSJerome Forissier } 1457ba16abbSJerome Forissier 1467ba16abbSJerome Forissier *base = vbase; 1477ba16abbSJerome Forissier *size = sz; 1487ba16abbSJerome Forissier return 0; 1497ba16abbSJerome Forissier } 1507ba16abbSJerome Forissier 1519fe4c797SJerome Forissier /* Read a physical address (n=1 or 2 cells) */ 152f354a5d8SGatien Chevallier static paddr_t fdt_read_paddr(const uint32_t *cell, int n) 1539fe4c797SJerome Forissier { 1549fe4c797SJerome Forissier paddr_t addr; 1559fe4c797SJerome Forissier 1569fe4c797SJerome Forissier if (n < 1 || n > 2) 1579fe4c797SJerome Forissier goto bad; 1589fe4c797SJerome Forissier 1599fe4c797SJerome Forissier addr = fdt32_to_cpu(*cell); 1609fe4c797SJerome Forissier cell++; 1619fe4c797SJerome Forissier if (n == 2) { 1629fe4c797SJerome Forissier #ifdef ARM32 1639fe4c797SJerome Forissier if (addr) { 1649fe4c797SJerome Forissier /* High order 32 bits can't be nonzero */ 1659fe4c797SJerome Forissier goto bad; 1669fe4c797SJerome Forissier } 1679fe4c797SJerome Forissier addr = fdt32_to_cpu(*cell); 1689fe4c797SJerome Forissier #else 1699fe4c797SJerome Forissier addr = (addr << 32) | fdt32_to_cpu(*cell); 1709fe4c797SJerome Forissier #endif 1719fe4c797SJerome Forissier } 1729fe4c797SJerome Forissier 1739fe4c797SJerome Forissier return addr; 1749fe4c797SJerome Forissier bad: 175c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1769fe4c797SJerome Forissier 1779fe4c797SJerome Forissier } 1789fe4c797SJerome Forissier 179f354a5d8SGatien Chevallier paddr_t fdt_reg_base_address(const void *fdt, int offs) 1809fe4c797SJerome Forissier { 1819fe4c797SJerome Forissier const void *reg; 1829fe4c797SJerome Forissier int ncells; 1839fe4c797SJerome Forissier int len; 18434deb103SPeng Fan int parent; 18534deb103SPeng Fan 18634deb103SPeng Fan parent = fdt_parent_offset(fdt, offs); 18734deb103SPeng Fan if (parent < 0) 188c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1899fe4c797SJerome Forissier 1909fe4c797SJerome Forissier reg = fdt_getprop(fdt, offs, "reg", &len); 1919fe4c797SJerome Forissier if (!reg) 192c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1939fe4c797SJerome Forissier 19434deb103SPeng Fan ncells = fdt_address_cells(fdt, parent); 1959fe4c797SJerome Forissier if (ncells < 0) 196c0cfb36cSEtienne Carriere return DT_INFO_INVALID_REG; 1979fe4c797SJerome Forissier 198f354a5d8SGatien Chevallier return fdt_read_paddr(reg, ncells); 1999fe4c797SJerome Forissier } 2009fe4c797SJerome Forissier 201a2e8c036SGatien Chevallier static size_t fdt_read_size(const uint32_t *cell, int n) 202a2e8c036SGatien Chevallier { 203a2e8c036SGatien Chevallier uint32_t sz = 0; 204a2e8c036SGatien Chevallier 205a2e8c036SGatien Chevallier sz = fdt32_to_cpu(*cell); 206a2e8c036SGatien Chevallier if (n == 2) { 207a2e8c036SGatien Chevallier if (sz) 208a2e8c036SGatien Chevallier return DT_INFO_INVALID_REG_SIZE; 209a2e8c036SGatien Chevallier 210a2e8c036SGatien Chevallier cell++; 211a2e8c036SGatien Chevallier sz = fdt32_to_cpu(*cell); 212a2e8c036SGatien Chevallier } 213a2e8c036SGatien Chevallier 214a2e8c036SGatien Chevallier return sz; 215a2e8c036SGatien Chevallier } 216a2e8c036SGatien Chevallier 217f354a5d8SGatien Chevallier size_t fdt_reg_size(const void *fdt, int offs) 2189fe4c797SJerome Forissier { 2199fe4c797SJerome Forissier const uint32_t *reg; 2209fe4c797SJerome Forissier int n; 2219fe4c797SJerome Forissier int len; 22234deb103SPeng Fan int parent; 22334deb103SPeng Fan 22434deb103SPeng Fan parent = fdt_parent_offset(fdt, offs); 22534deb103SPeng Fan if (parent < 0) 2261527e616SMarek Vasut return DT_INFO_INVALID_REG_SIZE; 2279fe4c797SJerome Forissier 2289fe4c797SJerome Forissier reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len); 2299fe4c797SJerome Forissier if (!reg) 230df7cecc0SLionel Debieve return DT_INFO_INVALID_REG_SIZE; 2319fe4c797SJerome Forissier 23234deb103SPeng Fan n = fdt_address_cells(fdt, parent); 2339fe4c797SJerome Forissier if (n < 1 || n > 2) 234df7cecc0SLionel Debieve return DT_INFO_INVALID_REG_SIZE; 2359fe4c797SJerome Forissier 2369fe4c797SJerome Forissier reg += n; 2379fe4c797SJerome Forissier 23834deb103SPeng Fan n = fdt_size_cells(fdt, parent); 2399fe4c797SJerome Forissier if (n < 1 || n > 2) 240df7cecc0SLionel Debieve return DT_INFO_INVALID_REG_SIZE; 2419fe4c797SJerome Forissier 242a2e8c036SGatien Chevallier return fdt_read_size(reg, n); 2439fe4c797SJerome Forissier } 2449fe4c797SJerome Forissier 2459fe4c797SJerome Forissier static bool is_okay(const char *st, int len) 2469fe4c797SJerome Forissier { 2479fe4c797SJerome Forissier return !strncmp(st, "ok", len) || !strncmp(st, "okay", len); 2489fe4c797SJerome Forissier } 2499fe4c797SJerome Forissier 250f354a5d8SGatien Chevallier int fdt_get_status(const void *fdt, int offs) 2519fe4c797SJerome Forissier { 2529fe4c797SJerome Forissier const char *prop; 2539fe4c797SJerome Forissier int st = 0; 2549fe4c797SJerome Forissier int len; 2559fe4c797SJerome Forissier 2569fe4c797SJerome Forissier prop = fdt_getprop(fdt, offs, "status", &len); 2579fe4c797SJerome Forissier if (!prop || is_okay(prop, len)) { 2589fe4c797SJerome Forissier /* If status is not specified, it defaults to "okay" */ 2599fe4c797SJerome Forissier st |= DT_STATUS_OK_NSEC; 2609fe4c797SJerome Forissier } 2619fe4c797SJerome Forissier 2629fe4c797SJerome Forissier prop = fdt_getprop(fdt, offs, "secure-status", &len); 2639fe4c797SJerome Forissier if (!prop) { 2649fe4c797SJerome Forissier /* 2659fe4c797SJerome Forissier * When secure-status is not specified it defaults to the same 2669fe4c797SJerome Forissier * value as status 2679fe4c797SJerome Forissier */ 2689fe4c797SJerome Forissier if (st & DT_STATUS_OK_NSEC) 2699fe4c797SJerome Forissier st |= DT_STATUS_OK_SEC; 2709fe4c797SJerome Forissier } else { 2719fe4c797SJerome Forissier if (is_okay(prop, len)) 2729fe4c797SJerome Forissier st |= DT_STATUS_OK_SEC; 2739fe4c797SJerome Forissier } 2749fe4c797SJerome Forissier 2759fe4c797SJerome Forissier return st; 2769fe4c797SJerome Forissier } 277c0cfb36cSEtienne Carriere 278f354a5d8SGatien Chevallier void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, int offs) 279c0cfb36cSEtienne Carriere { 280c0cfb36cSEtienne Carriere struct dt_node_info dinfo = { 281c0cfb36cSEtienne Carriere .reg = DT_INFO_INVALID_REG, 28206fd21ddSLionel Debieve .reg_size = DT_INFO_INVALID_REG_SIZE, 283c0cfb36cSEtienne Carriere .clock = DT_INFO_INVALID_CLOCK, 284c0cfb36cSEtienne Carriere .reset = DT_INFO_INVALID_RESET, 2857acb3a47SLudovic Barre .interrupt = DT_INFO_INVALID_INTERRUPT, 286c0cfb36cSEtienne Carriere }; 287c0cfb36cSEtienne Carriere const fdt32_t *cuint; 288c0cfb36cSEtienne Carriere 289f354a5d8SGatien Chevallier dinfo.reg = fdt_reg_base_address(fdt, offs); 290f354a5d8SGatien Chevallier dinfo.reg_size = fdt_reg_size(fdt, offs); 291c0cfb36cSEtienne Carriere 292c0cfb36cSEtienne Carriere cuint = fdt_getprop(fdt, offs, "clocks", NULL); 293c0cfb36cSEtienne Carriere if (cuint) { 294c0cfb36cSEtienne Carriere cuint++; 295c0cfb36cSEtienne Carriere dinfo.clock = (int)fdt32_to_cpu(*cuint); 296c0cfb36cSEtienne Carriere } 297c0cfb36cSEtienne Carriere 298c0cfb36cSEtienne Carriere cuint = fdt_getprop(fdt, offs, "resets", NULL); 299c0cfb36cSEtienne Carriere if (cuint) { 300c0cfb36cSEtienne Carriere cuint++; 301c0cfb36cSEtienne Carriere dinfo.reset = (int)fdt32_to_cpu(*cuint); 302c0cfb36cSEtienne Carriere } 303c0cfb36cSEtienne Carriere 304702fe5a7SClément Léger dinfo.interrupt = dt_get_irq_type_prio(fdt, offs, &dinfo.type, 305702fe5a7SClément Léger &dinfo.prio); 3067acb3a47SLudovic Barre 307f354a5d8SGatien Chevallier dinfo.status = fdt_get_status(fdt, offs); 308c0cfb36cSEtienne Carriere 309c0cfb36cSEtienne Carriere *info = dinfo; 310c0cfb36cSEtienne Carriere } 311876826f3SGabriel Fernandez 312f354a5d8SGatien Chevallier int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, 313876826f3SGabriel Fernandez uint32_t *array, size_t count) 314876826f3SGabriel Fernandez { 315876826f3SGabriel Fernandez const fdt32_t *cuint = NULL; 316876826f3SGabriel Fernandez int len = 0; 317876826f3SGabriel Fernandez uint32_t i = 0; 318876826f3SGabriel Fernandez 319876826f3SGabriel Fernandez cuint = fdt_getprop(fdt, node, prop_name, &len); 320876826f3SGabriel Fernandez if (!cuint) 32173e27bfaSGatien Chevallier return len; 322876826f3SGabriel Fernandez 323876826f3SGabriel Fernandez if ((uint32_t)len != (count * sizeof(uint32_t))) 324876826f3SGabriel Fernandez return -FDT_ERR_BADLAYOUT; 325876826f3SGabriel Fernandez 326876826f3SGabriel Fernandez for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 327876826f3SGabriel Fernandez *array = fdt32_to_cpu(*cuint); 328876826f3SGabriel Fernandez array++; 329876826f3SGabriel Fernandez cuint++; 330876826f3SGabriel Fernandez } 331876826f3SGabriel Fernandez 332876826f3SGabriel Fernandez return 0; 333876826f3SGabriel Fernandez } 334876826f3SGabriel Fernandez 3357c3a6b7bSGatien Chevallier int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, 3367c3a6b7bSGatien Chevallier int index, uint32_t *value) 3377c3a6b7bSGatien Chevallier { 3387c3a6b7bSGatien Chevallier const fdt32_t *cuint = NULL; 3397c3a6b7bSGatien Chevallier int len = 0; 3407c3a6b7bSGatien Chevallier 3417c3a6b7bSGatien Chevallier cuint = fdt_getprop(fdt, node, prop_name, &len); 3427c3a6b7bSGatien Chevallier if (!cuint) 3437c3a6b7bSGatien Chevallier return len; 3447c3a6b7bSGatien Chevallier 3457c3a6b7bSGatien Chevallier if ((uint32_t)len < (sizeof(uint32_t) * (index + 1))) 3467c3a6b7bSGatien Chevallier return -FDT_ERR_BADLAYOUT; 3477c3a6b7bSGatien Chevallier 3487c3a6b7bSGatien Chevallier *value = fdt32_to_cpu(cuint[index]); 3497c3a6b7bSGatien Chevallier 3507c3a6b7bSGatien Chevallier return 0; 3517c3a6b7bSGatien Chevallier } 3527c3a6b7bSGatien Chevallier 353f354a5d8SGatien Chevallier int fdt_read_uint32(const void *fdt, int node, const char *prop_name, 354876826f3SGabriel Fernandez uint32_t *value) 355876826f3SGabriel Fernandez { 356f354a5d8SGatien Chevallier return fdt_read_uint32_array(fdt, node, prop_name, value, 1); 357876826f3SGabriel Fernandez } 358876826f3SGabriel Fernandez 359f354a5d8SGatien Chevallier uint32_t fdt_read_uint32_default(const void *fdt, int node, 360876826f3SGabriel Fernandez const char *prop_name, uint32_t dflt_value) 361876826f3SGabriel Fernandez { 3627c3a6b7bSGatien Chevallier uint32_t ret = dflt_value; 363876826f3SGabriel Fernandez 3647c3a6b7bSGatien Chevallier fdt_read_uint32_index(fdt, node, prop_name, 0, &ret); 365876826f3SGabriel Fernandez 3667c3a6b7bSGatien Chevallier return ret; 367876826f3SGabriel Fernandez } 36807ced948SGatien Chevallier 36907ced948SGatien Chevallier int fdt_get_reg_props_by_index(const void *fdt, int node, int index, 37007ced948SGatien Chevallier paddr_t *base, size_t *size) 37107ced948SGatien Chevallier { 37207ced948SGatien Chevallier const fdt32_t *prop = NULL; 37307ced948SGatien Chevallier int parent = 0; 37407ced948SGatien Chevallier int len = 0; 37507ced948SGatien Chevallier int address_cells = 0; 37607ced948SGatien Chevallier int size_cells = 0; 37707ced948SGatien Chevallier int cell = 0; 37807ced948SGatien Chevallier 37907ced948SGatien Chevallier parent = fdt_parent_offset(fdt, node); 38007ced948SGatien Chevallier if (parent < 0) 38107ced948SGatien Chevallier return parent; 38207ced948SGatien Chevallier 38307ced948SGatien Chevallier address_cells = fdt_address_cells(fdt, parent); 38407ced948SGatien Chevallier if (address_cells < 0) 38507ced948SGatien Chevallier return address_cells; 38607ced948SGatien Chevallier 38707ced948SGatien Chevallier size_cells = fdt_size_cells(fdt, parent); 38807ced948SGatien Chevallier if (size_cells < 0) 38907ced948SGatien Chevallier return size_cells; 39007ced948SGatien Chevallier 39107ced948SGatien Chevallier cell = index * (address_cells + size_cells); 39207ced948SGatien Chevallier 39307ced948SGatien Chevallier prop = fdt_getprop(fdt, node, "reg", &len); 39407ced948SGatien Chevallier if (!prop) 39507ced948SGatien Chevallier return len; 39607ced948SGatien Chevallier 39707ced948SGatien Chevallier if (((cell + address_cells + size_cells) * (int)sizeof(uint32_t)) > len) 39807ced948SGatien Chevallier return -FDT_ERR_BADVALUE; 39907ced948SGatien Chevallier 40007ced948SGatien Chevallier if (base) { 40107ced948SGatien Chevallier *base = fdt_read_paddr(&prop[cell], address_cells); 40207ced948SGatien Chevallier if (*base == DT_INFO_INVALID_REG) 40307ced948SGatien Chevallier return -FDT_ERR_BADVALUE; 40407ced948SGatien Chevallier } 40507ced948SGatien Chevallier 40607ced948SGatien Chevallier if (size) { 40707ced948SGatien Chevallier *size = fdt_read_size(&prop[cell + address_cells], size_cells); 40807ced948SGatien Chevallier if (*size == DT_INFO_INVALID_REG_SIZE) 40907ced948SGatien Chevallier return -FDT_ERR_BADVALUE; 41007ced948SGatien Chevallier } 41107ced948SGatien Chevallier 41207ced948SGatien Chevallier return 0; 41307ced948SGatien Chevallier } 41407ced948SGatien Chevallier 41507ced948SGatien Chevallier int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, 41607ced948SGatien Chevallier paddr_t *base, size_t *size) 41707ced948SGatien Chevallier { 41807ced948SGatien Chevallier int index = 0; 41907ced948SGatien Chevallier 42007ced948SGatien Chevallier index = fdt_stringlist_search(fdt, node, "reg-names", name); 42107ced948SGatien Chevallier if (index < 0) 42207ced948SGatien Chevallier return index; 42307ced948SGatien Chevallier 42407ced948SGatien Chevallier return fdt_get_reg_props_by_index(fdt, node, index, base, size); 42507ced948SGatien Chevallier } 4264e45454aSJens Wiklander 4274e45454aSJens Wiklander int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, 4284e45454aSJens Wiklander uint64_t *num) 4294e45454aSJens Wiklander { 4304e45454aSJens Wiklander const void *prop = NULL; 4314e45454aSJens Wiklander int len = 0; 4324e45454aSJens Wiklander 4334e45454aSJens Wiklander prop = fdt_getprop(fdt, nodeoffset, name, &len); 4344e45454aSJens Wiklander if (!prop) 4354e45454aSJens Wiklander return len; 4364e45454aSJens Wiklander 4374e45454aSJens Wiklander switch (len) { 4384e45454aSJens Wiklander case sizeof(uint32_t): 4394e45454aSJens Wiklander *num = fdt32_ld(prop); 4404e45454aSJens Wiklander return 0; 4414e45454aSJens Wiklander case sizeof(uint64_t): 4424e45454aSJens Wiklander *num = fdt64_ld(prop); 4434e45454aSJens Wiklander return 0; 4444e45454aSJens Wiklander default: 4454e45454aSJens Wiklander return -FDT_ERR_BADVALUE; 4464e45454aSJens Wiklander } 4474e45454aSJens Wiklander } 448e6027f48SAlvin Chang 449e6027f48SAlvin Chang void *get_dt(void) 450e6027f48SAlvin Chang { 451e6027f48SAlvin Chang void *fdt = get_embedded_dt(); 452e6027f48SAlvin Chang 453e6027f48SAlvin Chang if (!fdt) 454e6027f48SAlvin Chang fdt = get_external_dt(); 455e6027f48SAlvin Chang 456*c5e3e79fSSungbae Yoo if (!fdt) 457*c5e3e79fSSungbae Yoo fdt = get_manifest_dt(); 458*c5e3e79fSSungbae Yoo 459e6027f48SAlvin Chang return fdt; 460e6027f48SAlvin Chang } 461e6027f48SAlvin Chang 462e6027f48SAlvin Chang void *get_secure_dt(void) 463e6027f48SAlvin Chang { 464e6027f48SAlvin Chang void *fdt = get_embedded_dt(); 465e6027f48SAlvin Chang 466e6027f48SAlvin Chang if (!fdt && IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) 467e6027f48SAlvin Chang fdt = get_external_dt(); 468e6027f48SAlvin Chang 469*c5e3e79fSSungbae Yoo if (!fdt) 470*c5e3e79fSSungbae Yoo fdt = get_manifest_dt(); 471*c5e3e79fSSungbae Yoo 472e6027f48SAlvin Chang return fdt; 473e6027f48SAlvin Chang } 474e6027f48SAlvin Chang 475e6027f48SAlvin Chang #if defined(CFG_EMBED_DTB) 476e6027f48SAlvin Chang void *get_embedded_dt(void) 477e6027f48SAlvin Chang { 478e6027f48SAlvin Chang static bool checked; 479e6027f48SAlvin Chang 480e6027f48SAlvin Chang assert(cpu_mmu_enabled()); 481e6027f48SAlvin Chang 482e6027f48SAlvin Chang if (!checked) { 483e6027f48SAlvin Chang IMSG("Embedded DTB found"); 484e6027f48SAlvin Chang 485e6027f48SAlvin Chang if (fdt_check_header(embedded_secure_dtb)) 486e6027f48SAlvin Chang panic("Invalid embedded DTB"); 487e6027f48SAlvin Chang 488e6027f48SAlvin Chang checked = true; 489e6027f48SAlvin Chang } 490e6027f48SAlvin Chang 491e6027f48SAlvin Chang return embedded_secure_dtb; 492e6027f48SAlvin Chang } 493e6027f48SAlvin Chang #else 494e6027f48SAlvin Chang void *get_embedded_dt(void) 495e6027f48SAlvin Chang { 496e6027f48SAlvin Chang return NULL; 497e6027f48SAlvin Chang } 498e6027f48SAlvin Chang #endif /*CFG_EMBED_DTB*/ 499e6027f48SAlvin Chang 500e6027f48SAlvin Chang #ifdef _CFG_USE_DTB_OVERLAY 501e6027f48SAlvin Chang static int add_dt_overlay_fragment(struct dt_descriptor *dt, int ioffs) 502e6027f48SAlvin Chang { 5030c49b6d6SAlvin Chang char frag[32] = { }; 5040c49b6d6SAlvin Chang int offs = 0; 5050c49b6d6SAlvin Chang int ret = 0; 506e6027f48SAlvin Chang 507a039ffc6SClement Faure ret = snprintf(frag, sizeof(frag), "fragment@%d", dt->frag_id); 508a039ffc6SClement Faure if (ret < 0 || (size_t)ret >= sizeof(frag)) 509a039ffc6SClement Faure return -1; 510a039ffc6SClement Faure 511e6027f48SAlvin Chang offs = fdt_add_subnode(dt->blob, ioffs, frag); 512e6027f48SAlvin Chang if (offs < 0) 513e6027f48SAlvin Chang return offs; 514e6027f48SAlvin Chang 515e6027f48SAlvin Chang dt->frag_id += 1; 516e6027f48SAlvin Chang 517e6027f48SAlvin Chang ret = fdt_setprop_string(dt->blob, offs, "target-path", "/"); 518e6027f48SAlvin Chang if (ret < 0) 5190c49b6d6SAlvin Chang return ret; 520e6027f48SAlvin Chang 521e6027f48SAlvin Chang return fdt_add_subnode(dt->blob, offs, "__overlay__"); 522e6027f48SAlvin Chang } 523e6027f48SAlvin Chang 524e6027f48SAlvin Chang static int init_dt_overlay(struct dt_descriptor *dt, int __maybe_unused dt_size) 525e6027f48SAlvin Chang { 5260c49b6d6SAlvin Chang int fragment = 0; 527e6027f48SAlvin Chang 528e6027f48SAlvin Chang if (IS_ENABLED(CFG_EXTERNAL_DTB_OVERLAY)) { 529e6027f48SAlvin Chang if (!fdt_check_header(dt->blob)) { 530e6027f48SAlvin Chang fdt_for_each_subnode(fragment, dt->blob, 0) 531e6027f48SAlvin Chang dt->frag_id += 1; 532e6027f48SAlvin Chang return 0; 533e6027f48SAlvin Chang } 534e6027f48SAlvin Chang } 535e6027f48SAlvin Chang 536e6027f48SAlvin Chang return fdt_create_empty_tree(dt->blob, dt_size); 537e6027f48SAlvin Chang } 538e6027f48SAlvin Chang #else 539e6027f48SAlvin Chang static int add_dt_overlay_fragment(struct dt_descriptor *dt __unused, int offs) 540e6027f48SAlvin Chang { 541e6027f48SAlvin Chang return offs; 542e6027f48SAlvin Chang } 543e6027f48SAlvin Chang 544e6027f48SAlvin Chang static int init_dt_overlay(struct dt_descriptor *dt __unused, 545e6027f48SAlvin Chang int dt_size __unused) 546e6027f48SAlvin Chang { 547e6027f48SAlvin Chang return 0; 548e6027f48SAlvin Chang } 549e6027f48SAlvin Chang #endif /* _CFG_USE_DTB_OVERLAY */ 550e6027f48SAlvin Chang 551e6027f48SAlvin Chang struct dt_descriptor *get_external_dt_desc(void) 552e6027f48SAlvin Chang { 553e6027f48SAlvin Chang if (!IS_ENABLED(CFG_EXTERNAL_DT)) 554e6027f48SAlvin Chang return NULL; 555e6027f48SAlvin Chang 556e6027f48SAlvin Chang return &external_dt; 557e6027f48SAlvin Chang } 558e6027f48SAlvin Chang 559dcff802bSRaymond Mao void init_external_dt(unsigned long phys_dt, size_t dt_sz) 560e6027f48SAlvin Chang { 561e6027f48SAlvin Chang struct dt_descriptor *dt = &external_dt; 5620c49b6d6SAlvin Chang int ret = 0; 56366763721SRaymond Mao enum teecore_memtypes mtype = MEM_AREA_MAXTYPE; 564e6027f48SAlvin Chang 565e6027f48SAlvin Chang if (!IS_ENABLED(CFG_EXTERNAL_DT)) 566e6027f48SAlvin Chang return; 567e6027f48SAlvin Chang 568dcff802bSRaymond Mao if (!phys_dt || !dt_sz) { 569e6027f48SAlvin Chang /* 570e6027f48SAlvin Chang * No need to panic as we're not using the DT in OP-TEE 571e6027f48SAlvin Chang * yet, we're only adding some nodes for normal world use. 572e6027f48SAlvin Chang * This makes the switch to using DT easier as we can boot 573e6027f48SAlvin Chang * a newer OP-TEE with older boot loaders. Once we start to 574e6027f48SAlvin Chang * initialize devices based on DT we'll likely panic 575e6027f48SAlvin Chang * instead of returning here. 576e6027f48SAlvin Chang */ 577e6027f48SAlvin Chang IMSG("No non-secure external DT"); 578e6027f48SAlvin Chang return; 579e6027f48SAlvin Chang } 580e6027f48SAlvin Chang 58166763721SRaymond Mao mtype = core_mmu_get_type_by_pa(phys_dt); 58266763721SRaymond Mao if (mtype == MEM_AREA_MAXTYPE) { 58366763721SRaymond Mao /* Map the DTB if it is not yet mapped */ 58466763721SRaymond Mao dt->blob = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, 585dcff802bSRaymond Mao dt_sz); 58666763721SRaymond Mao if (!dt->blob) 587e6027f48SAlvin Chang panic("Failed to map external DTB"); 58866763721SRaymond Mao } else { 58966763721SRaymond Mao /* Get the DTB address if already mapped in a memory area */ 590dcff802bSRaymond Mao dt->blob = phys_to_virt(phys_dt, mtype, dt_sz); 59166763721SRaymond Mao if (!dt->blob) { 59266763721SRaymond Mao EMSG("Failed to get a mapped external DTB for PA %#lx", 59366763721SRaymond Mao phys_dt); 59466763721SRaymond Mao panic(); 59566763721SRaymond Mao } 59666763721SRaymond Mao } 597e6027f48SAlvin Chang 598dcff802bSRaymond Mao ret = init_dt_overlay(dt, dt_sz); 599e6027f48SAlvin Chang if (ret < 0) { 600e6027f48SAlvin Chang EMSG("Device Tree Overlay init fail @ %#lx: error %d", phys_dt, 601e6027f48SAlvin Chang ret); 602e6027f48SAlvin Chang panic(); 603e6027f48SAlvin Chang } 604e6027f48SAlvin Chang 605dcff802bSRaymond Mao ret = fdt_open_into(dt->blob, dt->blob, dt_sz); 606e6027f48SAlvin Chang if (ret < 0) { 607e6027f48SAlvin Chang EMSG("Invalid Device Tree at %#lx: error %d", phys_dt, ret); 608e6027f48SAlvin Chang panic(); 609e6027f48SAlvin Chang } 610e6027f48SAlvin Chang 611e6027f48SAlvin Chang IMSG("Non-secure external DT found"); 612e6027f48SAlvin Chang } 613e6027f48SAlvin Chang 614e6027f48SAlvin Chang void *get_external_dt(void) 615e6027f48SAlvin Chang { 616e6027f48SAlvin Chang if (!IS_ENABLED(CFG_EXTERNAL_DT)) 617e6027f48SAlvin Chang return NULL; 618e6027f48SAlvin Chang 619e6027f48SAlvin Chang assert(cpu_mmu_enabled()); 620e6027f48SAlvin Chang return external_dt.blob; 621e6027f48SAlvin Chang } 622e6027f48SAlvin Chang 623e6027f48SAlvin Chang static TEE_Result release_external_dt(void) 624e6027f48SAlvin Chang { 625e6027f48SAlvin Chang int ret = 0; 62666763721SRaymond Mao paddr_t pa_dt = 0; 627e6027f48SAlvin Chang 628e6027f48SAlvin Chang if (!IS_ENABLED(CFG_EXTERNAL_DT)) 629e6027f48SAlvin Chang return TEE_SUCCESS; 630e6027f48SAlvin Chang 631e6027f48SAlvin Chang if (!external_dt.blob) 632e6027f48SAlvin Chang return TEE_SUCCESS; 633e6027f48SAlvin Chang 63466763721SRaymond Mao pa_dt = virt_to_phys(external_dt.blob); 63566763721SRaymond Mao /* 63666763721SRaymond Mao * Skip packing and un-mapping operations if the external DTB is mapped 63766763721SRaymond Mao * in a different memory area 63866763721SRaymond Mao */ 63966763721SRaymond Mao if (core_mmu_get_type_by_pa(pa_dt) != MEM_AREA_EXT_DT) 64066763721SRaymond Mao return TEE_SUCCESS; 64166763721SRaymond Mao 642e6027f48SAlvin Chang ret = fdt_pack(external_dt.blob); 643e6027f48SAlvin Chang if (ret < 0) { 644e6027f48SAlvin Chang EMSG("Failed to pack Device Tree at 0x%" PRIxPA ": error %d", 645e6027f48SAlvin Chang virt_to_phys(external_dt.blob), ret); 646e6027f48SAlvin Chang panic(); 647e6027f48SAlvin Chang } 648e6027f48SAlvin Chang 649e6027f48SAlvin Chang if (core_mmu_remove_mapping(MEM_AREA_EXT_DT, external_dt.blob, 650e6027f48SAlvin Chang CFG_DTB_MAX_SIZE)) 651e6027f48SAlvin Chang panic("Failed to remove temporary Device Tree mapping"); 652e6027f48SAlvin Chang 653e6027f48SAlvin Chang /* External DTB no more reached, reset pointer to invalid */ 654e6027f48SAlvin Chang external_dt.blob = NULL; 655e6027f48SAlvin Chang 656e6027f48SAlvin Chang return TEE_SUCCESS; 657e6027f48SAlvin Chang } 658e6027f48SAlvin Chang 659e6027f48SAlvin Chang boot_final(release_external_dt); 660e6027f48SAlvin Chang 661e6027f48SAlvin Chang int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, 662e6027f48SAlvin Chang const char *subnode) 663e6027f48SAlvin Chang { 6640c49b6d6SAlvin Chang int offs = 0; 665e6027f48SAlvin Chang 666e6027f48SAlvin Chang offs = fdt_path_offset(dt->blob, path); 667e6027f48SAlvin Chang if (offs < 0) 6680c49b6d6SAlvin Chang return offs; 669e6027f48SAlvin Chang offs = add_dt_overlay_fragment(dt, offs); 670e6027f48SAlvin Chang if (offs < 0) 671e6027f48SAlvin Chang return offs; 6720c49b6d6SAlvin Chang return fdt_add_subnode(dt->blob, offs, subnode); 673e6027f48SAlvin Chang } 674e6027f48SAlvin Chang 675e6027f48SAlvin Chang static void set_dt_val(void *data, uint32_t cell_size, uint64_t val) 676e6027f48SAlvin Chang { 677e6027f48SAlvin Chang if (cell_size == 1) { 678e6027f48SAlvin Chang fdt32_t v = cpu_to_fdt32((uint32_t)val); 679e6027f48SAlvin Chang 680e6027f48SAlvin Chang memcpy(data, &v, sizeof(v)); 681e6027f48SAlvin Chang } else { 682e6027f48SAlvin Chang fdt64_t v = cpu_to_fdt64(val); 683e6027f48SAlvin Chang 684e6027f48SAlvin Chang memcpy(data, &v, sizeof(v)); 685e6027f48SAlvin Chang } 686e6027f48SAlvin Chang } 687e6027f48SAlvin Chang 688e6027f48SAlvin Chang int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name, 689e6027f48SAlvin Chang paddr_t pa, size_t size) 690e6027f48SAlvin Chang { 691e6027f48SAlvin Chang int offs = 0; 692e6027f48SAlvin Chang int ret = 0; 693e6027f48SAlvin Chang int addr_size = -1; 694e6027f48SAlvin Chang int len_size = -1; 695e6027f48SAlvin Chang bool found = true; 6960c49b6d6SAlvin Chang char subnode_name[80] = { }; 697e6027f48SAlvin Chang 698e6027f48SAlvin Chang offs = fdt_path_offset(dt->blob, "/reserved-memory"); 699e6027f48SAlvin Chang 700e6027f48SAlvin Chang if (offs < 0) { 701e6027f48SAlvin Chang found = false; 702e6027f48SAlvin Chang offs = 0; 703e6027f48SAlvin Chang } 704e6027f48SAlvin Chang 705e6027f48SAlvin Chang if (IS_ENABLED2(_CFG_USE_DTB_OVERLAY)) { 706e6027f48SAlvin Chang len_size = sizeof(paddr_t) / sizeof(uint32_t); 707e6027f48SAlvin Chang addr_size = sizeof(paddr_t) / sizeof(uint32_t); 708e6027f48SAlvin Chang } else { 709e6027f48SAlvin Chang len_size = fdt_size_cells(dt->blob, offs); 710e6027f48SAlvin Chang if (len_size < 0) 7110c49b6d6SAlvin Chang return len_size; 712e6027f48SAlvin Chang addr_size = fdt_address_cells(dt->blob, offs); 713e6027f48SAlvin Chang if (addr_size < 0) 7140c49b6d6SAlvin Chang return addr_size; 715e6027f48SAlvin Chang } 716e6027f48SAlvin Chang 717e6027f48SAlvin Chang if (!found) { 718e6027f48SAlvin Chang offs = add_dt_path_subnode(dt, "/", "reserved-memory"); 719e6027f48SAlvin Chang if (offs < 0) 7200c49b6d6SAlvin Chang return offs; 721e6027f48SAlvin Chang ret = fdt_setprop_cell(dt->blob, offs, "#address-cells", 722e6027f48SAlvin Chang addr_size); 723e6027f48SAlvin Chang if (ret < 0) 7240c49b6d6SAlvin Chang return ret; 725e6027f48SAlvin Chang ret = fdt_setprop_cell(dt->blob, offs, "#size-cells", len_size); 726e6027f48SAlvin Chang if (ret < 0) 7270c49b6d6SAlvin Chang return ret; 728e6027f48SAlvin Chang ret = fdt_setprop(dt->blob, offs, "ranges", NULL, 0); 729e6027f48SAlvin Chang if (ret < 0) 7300c49b6d6SAlvin Chang return ret; 731e6027f48SAlvin Chang } 732e6027f48SAlvin Chang 733e6027f48SAlvin Chang ret = snprintf(subnode_name, sizeof(subnode_name), 734e6027f48SAlvin Chang "%s@%" PRIxPA, name, pa); 735e6027f48SAlvin Chang if (ret < 0 || ret >= (int)sizeof(subnode_name)) 736e6027f48SAlvin Chang DMSG("truncated node \"%s@%" PRIxPA"\"", name, pa); 737e6027f48SAlvin Chang offs = fdt_add_subnode(dt->blob, offs, subnode_name); 738e6027f48SAlvin Chang if (offs >= 0) { 7390c49b6d6SAlvin Chang uint32_t data[FDT_MAX_NCELLS * 2] = { }; 740e6027f48SAlvin Chang 741e6027f48SAlvin Chang set_dt_val(data, addr_size, pa); 742e6027f48SAlvin Chang set_dt_val(data + addr_size, len_size, size); 743e6027f48SAlvin Chang ret = fdt_setprop(dt->blob, offs, "reg", data, 744e6027f48SAlvin Chang sizeof(uint32_t) * (addr_size + len_size)); 745e6027f48SAlvin Chang if (ret < 0) 7460c49b6d6SAlvin Chang return ret; 747e6027f48SAlvin Chang ret = fdt_setprop(dt->blob, offs, "no-map", NULL, 0); 748e6027f48SAlvin Chang if (ret < 0) 7490c49b6d6SAlvin Chang return ret; 750e6027f48SAlvin Chang } else { 7510c49b6d6SAlvin Chang return offs; 752e6027f48SAlvin Chang } 753e6027f48SAlvin Chang return 0; 754e6027f48SAlvin Chang } 7554bc2c5f0SSungbae Yoo 7564bc2c5f0SSungbae Yoo #if defined(CFG_CORE_FFA) 7574bc2c5f0SSungbae Yoo void init_manifest_dt(void *fdt) 7584bc2c5f0SSungbae Yoo { 7594bc2c5f0SSungbae Yoo manifest_dt = fdt; 7604bc2c5f0SSungbae Yoo } 7614bc2c5f0SSungbae Yoo 7624bc2c5f0SSungbae Yoo void reinit_manifest_dt(void) 7634bc2c5f0SSungbae Yoo { 7644bc2c5f0SSungbae Yoo paddr_t pa = (unsigned long)manifest_dt; 7654bc2c5f0SSungbae Yoo void *fdt = NULL; 7664bc2c5f0SSungbae Yoo int ret = 0; 7674bc2c5f0SSungbae Yoo 7684bc2c5f0SSungbae Yoo if (!pa) { 7694bc2c5f0SSungbae Yoo EMSG("No manifest DT found"); 7704bc2c5f0SSungbae Yoo return; 7714bc2c5f0SSungbae Yoo } 7724bc2c5f0SSungbae Yoo 7734bc2c5f0SSungbae Yoo fdt = core_mmu_add_mapping(MEM_AREA_MANIFEST_DT, pa, CFG_DTB_MAX_SIZE); 7744bc2c5f0SSungbae Yoo if (!fdt) 7754bc2c5f0SSungbae Yoo panic("Failed to map manifest DT"); 7764bc2c5f0SSungbae Yoo 7774bc2c5f0SSungbae Yoo manifest_dt = fdt; 7784bc2c5f0SSungbae Yoo 7794bc2c5f0SSungbae Yoo ret = fdt_check_full(fdt, CFG_DTB_MAX_SIZE); 7804bc2c5f0SSungbae Yoo if (ret < 0) { 7814bc2c5f0SSungbae Yoo EMSG("Invalid manifest Device Tree at %#lx: error %d", pa, ret); 7824bc2c5f0SSungbae Yoo panic(); 7834bc2c5f0SSungbae Yoo } 7844bc2c5f0SSungbae Yoo 7854bc2c5f0SSungbae Yoo IMSG("manifest DT found"); 7864bc2c5f0SSungbae Yoo } 7874bc2c5f0SSungbae Yoo 7884bc2c5f0SSungbae Yoo void *get_manifest_dt(void) 7894bc2c5f0SSungbae Yoo { 7904bc2c5f0SSungbae Yoo return manifest_dt; 7914bc2c5f0SSungbae Yoo } 7924bc2c5f0SSungbae Yoo 7934bc2c5f0SSungbae Yoo static TEE_Result release_manifest_dt(void) 7944bc2c5f0SSungbae Yoo { 7954bc2c5f0SSungbae Yoo if (!manifest_dt) 7964bc2c5f0SSungbae Yoo return TEE_SUCCESS; 7974bc2c5f0SSungbae Yoo 7984bc2c5f0SSungbae Yoo if (core_mmu_remove_mapping(MEM_AREA_MANIFEST_DT, manifest_dt, 7994bc2c5f0SSungbae Yoo CFG_DTB_MAX_SIZE)) 8004bc2c5f0SSungbae Yoo panic("Failed to remove temporary manifest DT mapping"); 8014bc2c5f0SSungbae Yoo manifest_dt = NULL; 8024bc2c5f0SSungbae Yoo 8034bc2c5f0SSungbae Yoo return TEE_SUCCESS; 8044bc2c5f0SSungbae Yoo } 8054bc2c5f0SSungbae Yoo 8064bc2c5f0SSungbae Yoo boot_final(release_manifest_dt); 8074bc2c5f0SSungbae Yoo #else 8084bc2c5f0SSungbae Yoo void init_manifest_dt(void *fdt __unused) 8094bc2c5f0SSungbae Yoo { 8104bc2c5f0SSungbae Yoo } 8114bc2c5f0SSungbae Yoo 8124bc2c5f0SSungbae Yoo void reinit_manifest_dt(void) 8134bc2c5f0SSungbae Yoo { 8144bc2c5f0SSungbae Yoo } 8154bc2c5f0SSungbae Yoo 8164bc2c5f0SSungbae Yoo void *get_manifest_dt(void) 8174bc2c5f0SSungbae Yoo { 8184bc2c5f0SSungbae Yoo return NULL; 8194bc2c5f0SSungbae Yoo } 8204bc2c5f0SSungbae Yoo #endif /*CFG_CORE_FFA*/ 821