Lionel Debieve | 1dc5e2e | 2020-09-27 21:13:53 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2021, STMicroelectronics - All Rights Reserved |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <assert.h> |
| 8 | |
| 9 | #include <common/debug.h> |
| 10 | #include <common/fdt_wrappers.h> |
| 11 | #include <drivers/arm/tzc400.h> |
Yann Gautier | a205a5c | 2021-08-30 15:06:54 +0200 | [diff] [blame] | 12 | #include <drivers/clk.h> |
Lionel Debieve | 1dc5e2e | 2020-09-27 21:13:53 +0200 | [diff] [blame] | 13 | #include <dt-bindings/clock/stm32mp1-clks.h> |
| 14 | #include <lib/fconf/fconf.h> |
| 15 | #include <lib/object_pool.h> |
| 16 | #include <libfdt.h> |
| 17 | #include <tools_share/firmware_image_package.h> |
| 18 | |
| 19 | #include <platform_def.h> |
| 20 | #include <stm32mp_fconf_getter.h> |
| 21 | |
| 22 | #define STM32MP_REGION_PARAMS 4 |
| 23 | #define STM32MP_MAX_REGIONS 8 |
| 24 | #define FORCE_SEC_REGION BIT(31) |
| 25 | |
| 26 | static uint32_t nb_regions; |
| 27 | |
| 28 | struct dt_id_attr { |
| 29 | fdt32_t id_attr[STM32MP_MAX_REGIONS]; |
| 30 | }; |
| 31 | |
| 32 | void stm32mp1_arch_security_setup(void) |
| 33 | { |
Yann Gautier | a205a5c | 2021-08-30 15:06:54 +0200 | [diff] [blame] | 34 | clk_enable(TZC1); |
| 35 | clk_enable(TZC2); |
Lionel Debieve | 1dc5e2e | 2020-09-27 21:13:53 +0200 | [diff] [blame] | 36 | |
| 37 | tzc400_init(STM32MP1_TZC_BASE); |
| 38 | tzc400_disable_filters(); |
| 39 | |
| 40 | /* |
| 41 | * Region 0 set to cover all DRAM at 0xC000_0000 |
| 42 | * Only secure access is granted in read/write. |
| 43 | */ |
| 44 | tzc400_configure_region0(TZC_REGION_S_RDWR, 0); |
| 45 | |
| 46 | tzc400_set_action(TZC_ACTION_ERR); |
| 47 | tzc400_enable_filters(); |
| 48 | } |
| 49 | |
| 50 | void stm32mp1_security_setup(void) |
| 51 | { |
| 52 | uint8_t i; |
| 53 | |
| 54 | assert(nb_regions > 0U); |
| 55 | |
| 56 | tzc400_init(STM32MP1_TZC_BASE); |
| 57 | tzc400_disable_filters(); |
| 58 | |
| 59 | /* |
| 60 | * Region 0 set to cover all DRAM at 0xC000_0000 |
| 61 | * No access is allowed. |
| 62 | */ |
| 63 | tzc400_configure_region0(TZC_REGION_S_NONE, 0); |
| 64 | |
| 65 | for (i = 1U; i <= nb_regions; i++) { |
| 66 | tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL); |
| 67 | } |
| 68 | |
| 69 | tzc400_set_action(TZC_ACTION_INT); |
| 70 | tzc400_enable_filters(); |
| 71 | } |
| 72 | |
| 73 | static int fconf_populate_stm32mp1_firewall(uintptr_t config) |
| 74 | { |
| 75 | int node, len; |
| 76 | unsigned int i; |
| 77 | const struct dt_id_attr *conf_list; |
| 78 | const void *dtb = (const void *)config; |
| 79 | |
| 80 | /* Assert the node offset point to "st,mem-firewall" compatible property */ |
| 81 | const char *compatible_str = "st,mem-firewall"; |
| 82 | |
| 83 | node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); |
| 84 | if (node < 0) { |
| 85 | ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str); |
| 86 | return node; |
| 87 | } |
| 88 | |
| 89 | conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len); |
| 90 | if (conf_list == NULL) { |
| 91 | WARN("FCONF: Read cell failed for %s\n", "memory-ranges"); |
| 92 | return -1; |
| 93 | } |
| 94 | |
| 95 | /* Locate the memory cells and read all values */ |
| 96 | for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) { |
| 97 | uint32_t base; |
| 98 | uint32_t size; |
| 99 | uint32_t sec_attr; |
| 100 | uint32_t nsaid; |
| 101 | |
| 102 | base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]); |
| 103 | size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]); |
| 104 | sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]); |
| 105 | nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]); |
| 106 | |
| 107 | VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n", |
| 108 | base, size, sec_attr, nsaid); |
| 109 | |
| 110 | nb_regions++; |
| 111 | |
| 112 | /* Configure region but keep disabled for secure access for BL2 load */ |
| 113 | tzc400_configure_region(0U, nb_regions, (unsigned long long)base, |
| 114 | (unsigned long long)base + size - 1ULL, sec_attr, nsaid); |
| 115 | } |
| 116 | |
| 117 | /* Force flush as the value will be used cache off */ |
| 118 | flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t)); |
| 119 | |
| 120 | return 0; |
| 121 | } |
| 122 | |
| 123 | FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall); |