1 /* 2 * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <stdint.h> 10 11 #include <libfdt.h> 12 13 #include <platform_def.h> 14 15 #include <arch_helpers.h> 16 #include <common/debug.h> 17 #include <drivers/clk.h> 18 #include <drivers/delay_timer.h> 19 #include <drivers/st/stm32_hash.h> 20 #include <drivers/st/stm32mp_reset.h> 21 #include <lib/mmio.h> 22 #include <lib/utils.h> 23 #include <plat/common/platform.h> 24 25 #define DT_HASH_COMPAT "st,stm32f756-hash" 26 27 #define HASH_CR 0x00U 28 #define HASH_DIN 0x04U 29 #define HASH_STR 0x08U 30 #define HASH_SR 0x24U 31 #define HASH_HREG(x) (0x310U + ((x) * 0x04U)) 32 33 /* Control Register */ 34 #define HASH_CR_INIT BIT(2) 35 #define HASH_CR_DATATYPE_SHIFT U(4) 36 37 #define HASH_CR_ALGO_SHA1 0x0U 38 #define HASH_CR_ALGO_MD5 BIT(7) 39 #define HASH_CR_ALGO_SHA224 BIT(18) 40 #define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) 41 42 /* Status Flags */ 43 #define HASH_SR_DCIS BIT(1) 44 #define HASH_SR_BUSY BIT(3) 45 46 /* STR Register */ 47 #define HASH_STR_NBLW_MASK GENMASK(4, 0) 48 #define HASH_STR_DCAL BIT(8) 49 50 #define MD5_DIGEST_SIZE 16U 51 #define SHA1_DIGEST_SIZE 20U 52 #define SHA224_DIGEST_SIZE 28U 53 #define SHA256_DIGEST_SIZE 32U 54 55 #define RESET_TIMEOUT_US_1MS 1000U 56 #define HASH_TIMEOUT_US 10000U 57 58 enum stm32_hash_data_format { 59 HASH_DATA_32_BITS, 60 HASH_DATA_16_BITS, 61 HASH_DATA_8_BITS, 62 HASH_DATA_1_BIT 63 }; 64 65 struct stm32_hash_instance { 66 uintptr_t base; 67 unsigned int clock; 68 size_t digest_size; 69 }; 70 71 struct stm32_hash_remain { 72 uint32_t buffer; 73 size_t length; 74 }; 75 76 /* Expect a single HASH peripheral */ 77 static struct stm32_hash_instance stm32_hash; 78 static struct stm32_hash_remain stm32_remain; 79 80 static uintptr_t hash_base(void) 81 { 82 return stm32_hash.base; 83 } 84 85 static int hash_wait_busy(void) 86 { 87 uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); 88 89 while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) { 90 if (timeout_elapsed(timeout)) { 91 ERROR("%s: busy timeout\n", __func__); 92 return -ETIMEDOUT; 93 } 94 } 95 96 return 0; 97 } 98 99 static int hash_wait_computation(void) 100 { 101 uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); 102 103 while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) { 104 if (timeout_elapsed(timeout)) { 105 ERROR("%s: busy timeout\n", __func__); 106 return -ETIMEDOUT; 107 } 108 } 109 110 return 0; 111 } 112 113 static int hash_write_data(uint32_t data) 114 { 115 int ret; 116 117 ret = hash_wait_busy(); 118 if (ret != 0) { 119 return ret; 120 } 121 122 mmio_write_32(hash_base() + HASH_DIN, data); 123 124 return 0; 125 } 126 127 static void hash_hw_init(enum stm32_hash_algo_mode mode) 128 { 129 uint32_t reg; 130 131 reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); 132 133 switch (mode) { 134 case HASH_MD5SUM: 135 reg |= HASH_CR_ALGO_MD5; 136 stm32_hash.digest_size = MD5_DIGEST_SIZE; 137 break; 138 case HASH_SHA1: 139 reg |= HASH_CR_ALGO_SHA1; 140 stm32_hash.digest_size = SHA1_DIGEST_SIZE; 141 break; 142 case HASH_SHA224: 143 reg |= HASH_CR_ALGO_SHA224; 144 stm32_hash.digest_size = SHA224_DIGEST_SIZE; 145 break; 146 /* Default selected algo is SHA256 */ 147 case HASH_SHA256: 148 default: 149 reg |= HASH_CR_ALGO_SHA256; 150 stm32_hash.digest_size = SHA256_DIGEST_SIZE; 151 break; 152 } 153 154 mmio_write_32(hash_base() + HASH_CR, reg); 155 } 156 157 static int hash_get_digest(uint8_t *digest) 158 { 159 int ret; 160 uint32_t i; 161 uint32_t dsg; 162 163 ret = hash_wait_computation(); 164 if (ret != 0) { 165 return ret; 166 } 167 168 for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) { 169 dsg = __builtin_bswap32(mmio_read_32(hash_base() + 170 HASH_HREG(i))); 171 memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t)); 172 } 173 174 #if defined(IMAGE_BL2) 175 /* 176 * Clean hardware context as HASH could be used later 177 * by non-secure software 178 */ 179 hash_hw_init(HASH_SHA256); 180 #endif 181 return 0; 182 } 183 184 int stm32_hash_update(const uint8_t *buffer, size_t length) 185 { 186 size_t remain_length = length; 187 int ret = 0; 188 189 if ((length == 0U) || (buffer == NULL)) { 190 return 0; 191 } 192 193 clk_enable(stm32_hash.clock); 194 195 if (stm32_remain.length != 0U) { 196 uint32_t copysize; 197 198 copysize = MIN((sizeof(uint32_t) - stm32_remain.length), 199 length); 200 memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length, 201 buffer, copysize); 202 remain_length -= copysize; 203 buffer += copysize; 204 if (stm32_remain.length == sizeof(uint32_t)) { 205 ret = hash_write_data(stm32_remain.buffer); 206 if (ret != 0) { 207 goto exit; 208 } 209 210 zeromem(&stm32_remain, sizeof(stm32_remain)); 211 } 212 } 213 214 while (remain_length / sizeof(uint32_t) != 0U) { 215 uint32_t tmp_buf; 216 217 memcpy(&tmp_buf, buffer, sizeof(uint32_t)); 218 ret = hash_write_data(tmp_buf); 219 if (ret != 0) { 220 goto exit; 221 } 222 223 buffer += sizeof(uint32_t); 224 remain_length -= sizeof(uint32_t); 225 } 226 227 if (remain_length != 0U) { 228 assert(stm32_remain.length == 0U); 229 230 memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length); 231 stm32_remain.length = remain_length; 232 } 233 234 exit: 235 clk_disable(stm32_hash.clock); 236 237 return ret; 238 } 239 240 int stm32_hash_final(uint8_t *digest) 241 { 242 int ret; 243 244 clk_enable(stm32_hash.clock); 245 246 if (stm32_remain.length != 0U) { 247 ret = hash_write_data(stm32_remain.buffer); 248 if (ret != 0) { 249 clk_disable(stm32_hash.clock); 250 return ret; 251 } 252 253 mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, 254 8U * stm32_remain.length); 255 zeromem(&stm32_remain, sizeof(stm32_remain)); 256 } else { 257 mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK); 258 } 259 260 mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); 261 262 ret = hash_get_digest(digest); 263 264 clk_disable(stm32_hash.clock); 265 266 return ret; 267 } 268 269 int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, 270 uint8_t *digest) 271 { 272 int ret; 273 274 ret = stm32_hash_update(buffer, length); 275 if (ret != 0) { 276 return ret; 277 } 278 279 return stm32_hash_final(digest); 280 } 281 282 void stm32_hash_init(enum stm32_hash_algo_mode mode) 283 { 284 clk_enable(stm32_hash.clock); 285 286 hash_hw_init(mode); 287 288 clk_disable(stm32_hash.clock); 289 290 zeromem(&stm32_remain, sizeof(stm32_remain)); 291 } 292 293 int stm32_hash_register(void) 294 { 295 struct dt_node_info hash_info; 296 int node; 297 298 for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT); 299 node != -FDT_ERR_NOTFOUND; 300 node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) { 301 #if defined(IMAGE_BL2) 302 if (hash_info.status != DT_DISABLED) { 303 break; 304 } 305 #else 306 /* BL32 uses hash if it is assigned only to secure world */ 307 if (hash_info.status == DT_SECURE) { 308 stm32mp_register_secure_periph_iomem(hash_info.base); 309 break; 310 } 311 #endif 312 } 313 314 if (node == -FDT_ERR_NOTFOUND) { 315 return -ENODEV; 316 } 317 318 if (hash_info.clock < 0) { 319 return -EINVAL; 320 } 321 322 stm32_hash.base = hash_info.base; 323 stm32_hash.clock = hash_info.clock; 324 325 clk_enable(stm32_hash.clock); 326 327 if (hash_info.reset >= 0) { 328 uint32_t id = (uint32_t)hash_info.reset; 329 330 if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) { 331 panic(); 332 } 333 udelay(20); 334 if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) { 335 panic(); 336 } 337 } 338 339 clk_disable(stm32_hash.clock); 340 341 return 0; 342 } 343