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