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