1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2024, STMicroelectronics 4 */ 5 6 #include <assert.h> 7 #include <config.h> 8 #include <drivers/firewall.h> 9 #include <kernel/dt_driver.h> 10 #include <kernel/panic.h> 11 #include <libfdt.h> 12 #include <malloc.h> 13 #include <trace.h> 14 15 /* The firewall framework requires device tree support */ 16 static_assert(IS_ENABLED(CFG_DT)); 17 18 static TEE_Result firewall_get(struct dt_pargs *parg, void *data, 19 struct firewall_query **out_fw) 20 { 21 struct firewall_query *fw = NULL; 22 unsigned int i = 0; 23 24 assert(parg->args_count >= 0); 25 26 fw = calloc(1, sizeof(*fw)); 27 if (!fw) 28 return TEE_ERROR_OUT_OF_MEMORY; 29 30 fw->ctrl = (struct firewall_controller *)data; 31 fw->arg_count = parg->args_count; 32 33 if (fw->arg_count) { 34 fw->args = calloc(fw->arg_count, sizeof(*fw->args)); 35 if (!fw->args) { 36 free(fw); 37 return TEE_ERROR_OUT_OF_MEMORY; 38 } 39 } 40 41 for (i = 0; i < (unsigned int)parg->args_count; i++) 42 fw->args[i] = parg->args[i]; 43 44 *out_fw = fw; 45 46 return TEE_SUCCESS; 47 } 48 49 /* Firewall device API */ 50 51 void firewall_put(struct firewall_query *fw) 52 { 53 if (fw) { 54 free(fw->args); 55 free(fw); 56 } 57 } 58 59 TEE_Result firewall_dt_get_by_index(const void *fdt, int node, uint32_t index, 60 struct firewall_query **out_fw) 61 { 62 return dt_driver_device_from_node_idx_prop("access-controllers", fdt, 63 node, index, 64 DT_DRIVER_FIREWALL, 65 out_fw); 66 } 67 68 TEE_Result firewall_dt_get_by_name(const void *fdt, int node, const char *name, 69 struct firewall_query **out_fw) 70 { 71 int index = 0; 72 73 index = fdt_stringlist_search(fdt, node, "access-controllers-names", 74 name); 75 if (index == -FDT_ERR_NOTFOUND) 76 return TEE_ERROR_ITEM_NOT_FOUND; 77 else if (index < 0) 78 return TEE_ERROR_GENERIC; 79 80 return firewall_dt_get_by_index(fdt, node, index, out_fw); 81 } 82 83 TEE_Result firewall_set_configuration(struct firewall_query *fw) 84 { 85 assert(fw && fw->ctrl && fw->ctrl->ops); 86 87 if (!fw->ctrl->ops->set_conf) 88 return TEE_ERROR_NOT_SUPPORTED; 89 90 return fw->ctrl->ops->set_conf(fw); 91 } 92 93 TEE_Result firewall_check_access(struct firewall_query *fw) 94 { 95 assert(fw && fw->ctrl && fw->ctrl->ops); 96 97 if (!fw->ctrl->ops->check_access) 98 return TEE_ERROR_NOT_SUPPORTED; 99 100 return fw->ctrl->ops->check_access(fw); 101 } 102 103 TEE_Result firewall_acquire_access(struct firewall_query *fw) 104 { 105 assert(fw && fw->ctrl && fw->ctrl->ops); 106 107 if (!fw->ctrl->ops->acquire_access) 108 return TEE_ERROR_NOT_SUPPORTED; 109 110 return fw->ctrl->ops->acquire_access(fw); 111 } 112 113 TEE_Result firewall_check_memory_access(struct firewall_query *fw, 114 paddr_t paddr, size_t size, bool read, 115 bool write) 116 { 117 assert(fw && fw->ctrl && fw->ctrl->ops); 118 119 if (!fw->ctrl->ops->check_memory_access) 120 return TEE_ERROR_NOT_SUPPORTED; 121 122 return fw->ctrl->ops->check_memory_access(fw, paddr, size, read, write); 123 } 124 125 TEE_Result firewall_acquire_memory_access(struct firewall_query *fw, 126 paddr_t paddr, size_t size, bool read, 127 bool write) 128 { 129 assert(fw && fw->ctrl && fw->ctrl->ops); 130 131 if (!fw->ctrl->ops->acquire_memory_access) 132 return TEE_ERROR_NOT_SUPPORTED; 133 134 return fw->ctrl->ops->acquire_memory_access(fw, paddr, size, read, 135 write); 136 } 137 138 void firewall_release_access(struct firewall_query *fw) 139 { 140 assert(fw && fw->ctrl && fw->ctrl->ops); 141 142 if (fw->ctrl->ops->release_access) 143 fw->ctrl->ops->release_access(fw); 144 } 145 146 void firewall_release_memory_access(struct firewall_query *fw, paddr_t paddr, 147 size_t size, bool read, bool write) 148 { 149 assert(fw && fw->ctrl && fw->ctrl->ops); 150 151 if (fw->ctrl->ops->release_memory_access) 152 fw->ctrl->ops->release_memory_access(fw, paddr, size, read, 153 write); 154 } 155 156 /* Firewall controller API */ 157 158 TEE_Result firewall_dt_controller_register(const void *fdt, int node, 159 struct firewall_controller *ctrl) 160 { 161 assert(ctrl); 162 163 DMSG("Registering %s firewall controller", ctrl->name); 164 165 return dt_driver_register_provider(fdt, node, 166 (get_of_device_func)firewall_get, 167 ctrl, DT_DRIVER_FIREWALL); 168 } 169