1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2015 - 2020 Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <inttypes.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu #include <string.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <lib/mmio.h> 14*91f16700Schasinglulu #include <plat/common/platform.h> 15*91f16700Schasinglulu #include <tools_share/tbbr_oid.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <sbl_util.h> 18*91f16700Schasinglulu #include <sotp.h> 19*91f16700Schasinglulu 20*91f16700Schasinglulu /* Weak definition may be overridden in specific platform */ 21*91f16700Schasinglulu #pragma weak plat_match_rotpk 22*91f16700Schasinglulu #pragma weak plat_get_nv_ctr 23*91f16700Schasinglulu #pragma weak plat_set_nv_ctr 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* SHA256 algorithm */ 26*91f16700Schasinglulu #define SHA256_BYTES 32 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* ROTPK locations */ 29*91f16700Schasinglulu #define ARM_ROTPK_REGS_ID 1 30*91f16700Schasinglulu #define ARM_ROTPK_DEVEL_RSA_ID 2 31*91f16700Schasinglulu #define BRCM_ROTPK_SOTP_RSA_ID 3 32*91f16700Schasinglulu 33*91f16700Schasinglulu #if !ARM_ROTPK_LOCATION_ID 34*91f16700Schasinglulu #error "ARM_ROTPK_LOCATION_ID not defined" 35*91f16700Schasinglulu #endif 36*91f16700Schasinglulu 37*91f16700Schasinglulu static const unsigned char rotpk_hash_hdr[] = 38*91f16700Schasinglulu "\x30\x31\x30\x0D\x06\x09\x60\x86\x48" 39*91f16700Schasinglulu "\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; 40*91f16700Schasinglulu static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1; 41*91f16700Schasinglulu static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES]; 42*91f16700Schasinglulu 43*91f16700Schasinglulu #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) 44*91f16700Schasinglulu static const unsigned char arm_devel_rotpk_hash[] = 45*91f16700Schasinglulu "\xB0\xF3\x82\x09\x12\x97\xD8\x3A" 46*91f16700Schasinglulu "\x37\x7A\x72\x47\x1B\xEC\x32\x73" 47*91f16700Schasinglulu "\xE9\x92\x32\xE2\x49\x59\xF6\x5E" 48*91f16700Schasinglulu "\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA"; 49*91f16700Schasinglulu #endif 50*91f16700Schasinglulu 51*91f16700Schasinglulu #pragma weak plat_rotpk_hash 52*91f16700Schasinglulu const unsigned char plat_rotpk_hash[] = 53*91f16700Schasinglulu "\xdb\x06\x67\x95\x4f\x88\x2b\x88" 54*91f16700Schasinglulu "\x49\xbf\x70\x3f\xde\x50\x4a\x96" 55*91f16700Schasinglulu "\xd8\x17\x69\xd4\xa0\x6c\xba\xee" 56*91f16700Schasinglulu "\x66\x3e\x71\x82\x2d\x95\x69\xe4"; 57*91f16700Schasinglulu 58*91f16700Schasinglulu #pragma weak rom_slice 59*91f16700Schasinglulu const unsigned char rom_slice[] = 60*91f16700Schasinglulu "\x77\x06\xbc\x98\x40\xbe\xfd\xab" 61*91f16700Schasinglulu "\x60\x4b\x74\x3c\x9a\xb3\x80\x75" 62*91f16700Schasinglulu "\x39\xb6\xda\x27\x07\x2e\x5b\xbf" 63*91f16700Schasinglulu "\x5c\x47\x91\xc9\x95\x26\x26\x0c"; 64*91f16700Schasinglulu 65*91f16700Schasinglulu #if (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID) 66*91f16700Schasinglulu static int plat_is_trusted_boot(void) 67*91f16700Schasinglulu { 68*91f16700Schasinglulu uint64_t section3_row0_data; 69*91f16700Schasinglulu 70*91f16700Schasinglulu section3_row0_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); 71*91f16700Schasinglulu 72*91f16700Schasinglulu if ((section3_row0_data & SOTP_DEVICE_SECURE_CFG0_AB_MASK) == 0) { 73*91f16700Schasinglulu INFO("NOT AB\n"); 74*91f16700Schasinglulu return 0; 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu INFO("AB\n"); 78*91f16700Schasinglulu return TRUSTED_BOARD_BOOT; 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* 82*91f16700Schasinglulu * FAST AUTH is enabled if all following conditions are met: 83*91f16700Schasinglulu * - AB part 84*91f16700Schasinglulu * - SOTP.DEV != 0 85*91f16700Schasinglulu * - SOTP.CID != 0 86*91f16700Schasinglulu * - SOTP.ENC_DEV_TYPE = ENC_AB_DEV 87*91f16700Schasinglulu * - Manuf_debug strap set high 88*91f16700Schasinglulu */ 89*91f16700Schasinglulu static int plat_fast_auth_enabled(void) 90*91f16700Schasinglulu { 91*91f16700Schasinglulu uint32_t chip_state; 92*91f16700Schasinglulu uint64_t section3_row0_data; 93*91f16700Schasinglulu uint64_t section3_row1_data; 94*91f16700Schasinglulu 95*91f16700Schasinglulu section3_row0_data = 96*91f16700Schasinglulu sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); 97*91f16700Schasinglulu section3_row1_data = 98*91f16700Schasinglulu sotp_mem_read(SOTP_DEVICE_SECURE_CFG1_ROW, 0); 99*91f16700Schasinglulu 100*91f16700Schasinglulu chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES); 101*91f16700Schasinglulu 102*91f16700Schasinglulu if (plat_is_trusted_boot() && 103*91f16700Schasinglulu (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_DEV_MASK) && 104*91f16700Schasinglulu (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_CID_MASK) && 105*91f16700Schasinglulu ((section3_row1_data & SOTP_ENC_DEV_TYPE_MASK) == 106*91f16700Schasinglulu SOTP_ENC_DEV_TYPE_AB_DEV) && 107*91f16700Schasinglulu (chip_state & SOTP_CHIP_STATES_MANU_DEBUG_MASK)) 108*91f16700Schasinglulu return 1; 109*91f16700Schasinglulu 110*91f16700Schasinglulu return 0; 111*91f16700Schasinglulu } 112*91f16700Schasinglulu #endif 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* 115*91f16700Schasinglulu * Return the ROTPK hash in the following ASN.1 structure in DER format: 116*91f16700Schasinglulu * 117*91f16700Schasinglulu * AlgorithmIdentifier ::= SEQUENCE { 118*91f16700Schasinglulu * algorithm OBJECT IDENTIFIER, 119*91f16700Schasinglulu * parameters ANY DEFINED BY algorithm OPTIONAL 120*91f16700Schasinglulu * } 121*91f16700Schasinglulu * 122*91f16700Schasinglulu * DigestInfo ::= SEQUENCE { 123*91f16700Schasinglulu * digestAlgorithm AlgorithmIdentifier, 124*91f16700Schasinglulu * digest OCTET STRING 125*91f16700Schasinglulu * } 126*91f16700Schasinglulu */ 127*91f16700Schasinglulu int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, 128*91f16700Schasinglulu unsigned int *flags) 129*91f16700Schasinglulu { 130*91f16700Schasinglulu uint8_t *dst; 131*91f16700Schasinglulu 132*91f16700Schasinglulu assert(key_ptr != NULL); 133*91f16700Schasinglulu assert(key_len != NULL); 134*91f16700Schasinglulu assert(flags != NULL); 135*91f16700Schasinglulu 136*91f16700Schasinglulu *flags = 0; 137*91f16700Schasinglulu 138*91f16700Schasinglulu /* Copy the DER header */ 139*91f16700Schasinglulu memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len); 140*91f16700Schasinglulu dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len]; 141*91f16700Schasinglulu 142*91f16700Schasinglulu #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) 143*91f16700Schasinglulu memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES); 144*91f16700Schasinglulu #elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) 145*91f16700Schasinglulu uint32_t *src, tmp; 146*91f16700Schasinglulu unsigned int words, i; 147*91f16700Schasinglulu 148*91f16700Schasinglulu /* 149*91f16700Schasinglulu * Append the hash from Trusted Root-Key Storage registers. The hash has 150*91f16700Schasinglulu * not been written linearly into the registers, so we have to do a bit 151*91f16700Schasinglulu * of byte swapping: 152*91f16700Schasinglulu * 153*91f16700Schasinglulu * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C 154*91f16700Schasinglulu * +---------------------------------------------------------------+ 155*91f16700Schasinglulu * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | 156*91f16700Schasinglulu * +---------------------------------------------------------------+ 157*91f16700Schasinglulu * | ... ... | | ... ... | 158*91f16700Schasinglulu * | +--------------------+ | +-------+ 159*91f16700Schasinglulu * | | | | 160*91f16700Schasinglulu * +----------------------------+ +----------------------------+ 161*91f16700Schasinglulu * | | | | 162*91f16700Schasinglulu * +-------+ | +--------------------+ | 163*91f16700Schasinglulu * | | | | 164*91f16700Schasinglulu * v v v v 165*91f16700Schasinglulu * +---------------------------------------------------------------+ 166*91f16700Schasinglulu * | | | 167*91f16700Schasinglulu * +---------------------------------------------------------------+ 168*91f16700Schasinglulu * 0 15 16 31 169*91f16700Schasinglulu * 170*91f16700Schasinglulu * Additionally, we have to access the registers in 32-bit words 171*91f16700Schasinglulu */ 172*91f16700Schasinglulu words = SHA256_BYTES >> 3; 173*91f16700Schasinglulu 174*91f16700Schasinglulu /* Swap bytes 0-15 (first four registers) */ 175*91f16700Schasinglulu src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; 176*91f16700Schasinglulu for (i = 0 ; i < words ; i++) { 177*91f16700Schasinglulu tmp = src[words - 1 - i]; 178*91f16700Schasinglulu /* Words are read in little endian */ 179*91f16700Schasinglulu *dst++ = (uint8_t)((tmp >> 24) & 0xFF); 180*91f16700Schasinglulu *dst++ = (uint8_t)((tmp >> 16) & 0xFF); 181*91f16700Schasinglulu *dst++ = (uint8_t)((tmp >> 8) & 0xFF); 182*91f16700Schasinglulu *dst++ = (uint8_t)(tmp & 0xFF); 183*91f16700Schasinglulu } 184*91f16700Schasinglulu 185*91f16700Schasinglulu /* Swap bytes 16-31 (last four registers) */ 186*91f16700Schasinglulu src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2); 187*91f16700Schasinglulu for (i = 0 ; i < words ; i++) { 188*91f16700Schasinglulu tmp = src[words - 1 - i]; 189*91f16700Schasinglulu *dst++ = (uint8_t)((tmp >> 24) & 0xFF); 190*91f16700Schasinglulu *dst++ = (uint8_t)((tmp >> 16) & 0xFF); 191*91f16700Schasinglulu *dst++ = (uint8_t)((tmp >> 8) & 0xFF); 192*91f16700Schasinglulu *dst++ = (uint8_t)(tmp & 0xFF); 193*91f16700Schasinglulu } 194*91f16700Schasinglulu #elif (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID) 195*91f16700Schasinglulu { 196*91f16700Schasinglulu int i; 197*91f16700Schasinglulu int ret = -1; 198*91f16700Schasinglulu 199*91f16700Schasinglulu /* 200*91f16700Schasinglulu * In non-AB mode, we do not read the key. 201*91f16700Schasinglulu * In AB mode: 202*91f16700Schasinglulu * - The Dauth is in BL11 if SBL is enabled 203*91f16700Schasinglulu * - The Dauth is in SOTP if SBL is disabled. 204*91f16700Schasinglulu */ 205*91f16700Schasinglulu if (plat_is_trusted_boot() == 0) { 206*91f16700Schasinglulu 207*91f16700Schasinglulu INFO("NON-AB: Do not read DAUTH!\n"); 208*91f16700Schasinglulu *flags = ROTPK_NOT_DEPLOYED; 209*91f16700Schasinglulu ret = 0; 210*91f16700Schasinglulu 211*91f16700Schasinglulu } else if ((sbl_status() == SBL_ENABLED) && 212*91f16700Schasinglulu (mmio_read_32(BL11_DAUTH_BASE) == BL11_DAUTH_ID)) { 213*91f16700Schasinglulu 214*91f16700Schasinglulu /* Read hash from BL11 */ 215*91f16700Schasinglulu INFO("readKeys (DAUTH) from BL11\n"); 216*91f16700Schasinglulu 217*91f16700Schasinglulu memcpy(dst, 218*91f16700Schasinglulu (void *)(BL11_DAUTH_BASE + sizeof(uint32_t)), 219*91f16700Schasinglulu SHA256_BYTES); 220*91f16700Schasinglulu 221*91f16700Schasinglulu for (i = 0; i < SHA256_BYTES; i++) 222*91f16700Schasinglulu if (dst[i] != 0) 223*91f16700Schasinglulu break; 224*91f16700Schasinglulu 225*91f16700Schasinglulu if (i >= SHA256_BYTES) 226*91f16700Schasinglulu ERROR("Hash not valid from BL11\n"); 227*91f16700Schasinglulu else 228*91f16700Schasinglulu ret = 0; 229*91f16700Schasinglulu 230*91f16700Schasinglulu } else if (sotp_key_erased()) { 231*91f16700Schasinglulu 232*91f16700Schasinglulu memcpy(dst, plat_rotpk_hash, SHA256_BYTES); 233*91f16700Schasinglulu 234*91f16700Schasinglulu INFO("SOTP erased, Use internal key hash.\n"); 235*91f16700Schasinglulu ret = 0; 236*91f16700Schasinglulu 237*91f16700Schasinglulu } else if (plat_fast_auth_enabled()) { 238*91f16700Schasinglulu 239*91f16700Schasinglulu INFO("AB DEV: FAST AUTH!\n"); 240*91f16700Schasinglulu *flags = ROTPK_NOT_DEPLOYED; 241*91f16700Schasinglulu ret = 0; 242*91f16700Schasinglulu 243*91f16700Schasinglulu } else if (!(mmio_read_32(SOTP_STATUS_1) & SOTP_DAUTH_ECC_ERROR_MASK)) { 244*91f16700Schasinglulu 245*91f16700Schasinglulu /* Read hash from SOTP */ 246*91f16700Schasinglulu ret = sotp_read_key(dst, 247*91f16700Schasinglulu SHA256_BYTES, 248*91f16700Schasinglulu SOTP_DAUTH_ROW, 249*91f16700Schasinglulu SOTP_K_HMAC_ROW-1); 250*91f16700Schasinglulu 251*91f16700Schasinglulu INFO("sotp_read_key (DAUTH): %i\n", ret); 252*91f16700Schasinglulu 253*91f16700Schasinglulu } else { 254*91f16700Schasinglulu 255*91f16700Schasinglulu uint64_t row_data; 256*91f16700Schasinglulu uint32_t k; 257*91f16700Schasinglulu 258*91f16700Schasinglulu for (k = 0; k < (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW); k++) { 259*91f16700Schasinglulu row_data = sotp_mem_read(SOTP_DAUTH_ROW + k, 260*91f16700Schasinglulu SOTP_ROW_NO_ECC); 261*91f16700Schasinglulu 262*91f16700Schasinglulu if (row_data != 0) 263*91f16700Schasinglulu break; 264*91f16700Schasinglulu } 265*91f16700Schasinglulu 266*91f16700Schasinglulu if (k == (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW)) { 267*91f16700Schasinglulu INFO("SOTP NOT PROGRAMMED: Do not use DAUTH!\n"); 268*91f16700Schasinglulu 269*91f16700Schasinglulu if (sotp_mem_read(SOTP_ATF2_CFG_ROW_ID, 270*91f16700Schasinglulu SOTP_ROW_NO_ECC) & SOTP_ROMKEY_MASK) { 271*91f16700Schasinglulu memcpy(dst, plat_rotpk_hash, SHA256_BYTES); 272*91f16700Schasinglulu 273*91f16700Schasinglulu INFO("Use internal key hash.\n"); 274*91f16700Schasinglulu ret = 0; 275*91f16700Schasinglulu } else { 276*91f16700Schasinglulu *flags = ROTPK_NOT_DEPLOYED; 277*91f16700Schasinglulu ret = 0; 278*91f16700Schasinglulu } 279*91f16700Schasinglulu } else { 280*91f16700Schasinglulu INFO("No hash found in SOTP\n"); 281*91f16700Schasinglulu } 282*91f16700Schasinglulu } 283*91f16700Schasinglulu if (ret) 284*91f16700Schasinglulu return ret; 285*91f16700Schasinglulu } 286*91f16700Schasinglulu #endif 287*91f16700Schasinglulu 288*91f16700Schasinglulu *key_ptr = (void *)rotpk_hash_der; 289*91f16700Schasinglulu *key_len = (unsigned int)sizeof(rotpk_hash_der); 290*91f16700Schasinglulu *flags |= ROTPK_IS_HASH; 291*91f16700Schasinglulu 292*91f16700Schasinglulu return 0; 293*91f16700Schasinglulu } 294*91f16700Schasinglulu 295*91f16700Schasinglulu #define SOTP_NUM_BITS_PER_ROW 41 296*91f16700Schasinglulu #define SOTP_NVCTR_ROW_ALL_ONES 0x1ffffffffff 297*91f16700Schasinglulu #define SOTP_NVCTR_TRUSTED_IN_USE \ 298*91f16700Schasinglulu ((uint64_t)0x3 << (SOTP_NUM_BITS_PER_ROW-2)) 299*91f16700Schasinglulu #define SOTP_NVCTR_NON_TRUSTED_IN_USE ((uint64_t)0x3) 300*91f16700Schasinglulu #define SOTP_NVCTR_TRUSTED_NEAR_END SOTP_NVCTR_NON_TRUSTED_IN_USE 301*91f16700Schasinglulu #define SOTP_NVCTR_NON_TRUSTED_NEAR_END SOTP_NVCTR_TRUSTED_IN_USE 302*91f16700Schasinglulu 303*91f16700Schasinglulu #define SOTP_NVCTR_ROW_START 64 304*91f16700Schasinglulu #define SOTP_NVCTR_ROW_END 75 305*91f16700Schasinglulu 306*91f16700Schasinglulu /* 307*91f16700Schasinglulu * SOTP NVCTR are stored in section 10 of SOTP (rows 64-75). 308*91f16700Schasinglulu * Each row of SOTP is 41 bits. 309*91f16700Schasinglulu * NVCTR's are stored in a bitstream format. 310*91f16700Schasinglulu * We are tolerant to consecutive bit errors. 311*91f16700Schasinglulu * Trusted NVCTR starts at the top of row 64 in bitstream format. 312*91f16700Schasinglulu * Non Trusted NVCTR starts at the bottom of row 75 in reverse bitstream. 313*91f16700Schasinglulu * Each row can only be used by 1 of the 2 counters. This is determined 314*91f16700Schasinglulu * by 2 zeros remaining at the beginning or end of the last available row. 315*91f16700Schasinglulu * If one counter has already starting using a row, the other will be 316*91f16700Schasinglulu * prevent from writing to that row. 317*91f16700Schasinglulu * 318*91f16700Schasinglulu * Example counter values for SOTP programmed below: 319*91f16700Schasinglulu * Trusted Counter (rows64-69) = 5 * 41 + 40 = 245 320*91f16700Schasinglulu * NonTrusted Counter (row75-71) = 3 * 41 + 4 = 127 321*91f16700Schasinglulu * 40 39 38 37 36 ..... 5 4 3 2 1 0 322*91f16700Schasinglulu * row 64 1 1 1 1 1 1 1 1 1 1 1 323*91f16700Schasinglulu * row 65 1 1 1 1 1 1 1 1 1 1 1 324*91f16700Schasinglulu * row 66 1 1 1 1 1 1 1 1 1 1 1 325*91f16700Schasinglulu * row 67 1 1 1 1 1 1 1 1 1 1 1 326*91f16700Schasinglulu * row 68 1 1 1 1 1 1 1 1 1 1 1 327*91f16700Schasinglulu * row 69 1 1 1 1 1 1 1 1 1 1 0 328*91f16700Schasinglulu * row 71 0 0 0 0 0 0 0 0 0 0 0 329*91f16700Schasinglulu * row 71 0 0 0 0 0 0 0 0 0 0 0 330*91f16700Schasinglulu * row 71 0 0 0 0 0 0 0 1 1 1 1 331*91f16700Schasinglulu * row 73 1 1 1 1 1 1 1 1 1 1 1 332*91f16700Schasinglulu * row 74 1 1 1 1 1 1 1 1 1 1 1 333*91f16700Schasinglulu * row 75 1 1 1 1 1 1 1 1 1 1 1 334*91f16700Schasinglulu * 335*91f16700Schasinglulu */ 336*91f16700Schasinglulu 337*91f16700Schasinglulu #if (DEBUG == 1) 338*91f16700Schasinglulu /* 339*91f16700Schasinglulu * Dump sotp rows 340*91f16700Schasinglulu */ 341*91f16700Schasinglulu void sotp_dump_rows(uint32_t start_row, uint32_t end_row) 342*91f16700Schasinglulu { 343*91f16700Schasinglulu int32_t rownum; 344*91f16700Schasinglulu uint64_t rowdata; 345*91f16700Schasinglulu 346*91f16700Schasinglulu for (rownum = start_row; rownum <= end_row; rownum++) { 347*91f16700Schasinglulu rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); 348*91f16700Schasinglulu INFO("%d 0x%" PRIx64 "\n", rownum, rowdata); 349*91f16700Schasinglulu } 350*91f16700Schasinglulu } 351*91f16700Schasinglulu #endif 352*91f16700Schasinglulu 353*91f16700Schasinglulu /* 354*91f16700Schasinglulu * Get SOTP Trusted nvctr 355*91f16700Schasinglulu */ 356*91f16700Schasinglulu unsigned int sotp_get_trusted_nvctr(void) 357*91f16700Schasinglulu { 358*91f16700Schasinglulu uint64_t rowdata; 359*91f16700Schasinglulu uint64_t nextrowdata; 360*91f16700Schasinglulu uint32_t rownum; 361*91f16700Schasinglulu unsigned int nvctr; 362*91f16700Schasinglulu 363*91f16700Schasinglulu rownum = SOTP_NVCTR_ROW_START; 364*91f16700Schasinglulu nvctr = SOTP_NUM_BITS_PER_ROW; 365*91f16700Schasinglulu 366*91f16700Schasinglulu /* 367*91f16700Schasinglulu * Determine what row has last valid data for trusted ctr 368*91f16700Schasinglulu */ 369*91f16700Schasinglulu rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); 370*91f16700Schasinglulu while ((rowdata & SOTP_NVCTR_TRUSTED_IN_USE) && 371*91f16700Schasinglulu (rowdata & SOTP_NVCTR_TRUSTED_NEAR_END) && 372*91f16700Schasinglulu (rownum < SOTP_NVCTR_ROW_END)) { 373*91f16700Schasinglulu /* 374*91f16700Schasinglulu * Current row in use and has data in last 2 bits as well. 375*91f16700Schasinglulu * Check if next row also has data for this counter 376*91f16700Schasinglulu */ 377*91f16700Schasinglulu nextrowdata = sotp_mem_read(rownum+1, SOTP_ROW_NO_ECC); 378*91f16700Schasinglulu if (nextrowdata & SOTP_NVCTR_TRUSTED_IN_USE) { 379*91f16700Schasinglulu /* Next row also has data so increment rownum */ 380*91f16700Schasinglulu rownum++; 381*91f16700Schasinglulu nvctr += SOTP_NUM_BITS_PER_ROW; 382*91f16700Schasinglulu rowdata = nextrowdata; 383*91f16700Schasinglulu } else { 384*91f16700Schasinglulu /* Next row does not have data */ 385*91f16700Schasinglulu break; 386*91f16700Schasinglulu } 387*91f16700Schasinglulu } 388*91f16700Schasinglulu 389*91f16700Schasinglulu if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) { 390*91f16700Schasinglulu while ((rowdata & 0x1) == 0) { 391*91f16700Schasinglulu nvctr--; 392*91f16700Schasinglulu rowdata >>= 1; 393*91f16700Schasinglulu } 394*91f16700Schasinglulu } else 395*91f16700Schasinglulu nvctr -= SOTP_NUM_BITS_PER_ROW; 396*91f16700Schasinglulu 397*91f16700Schasinglulu INFO("CTR %i\n", nvctr); 398*91f16700Schasinglulu return nvctr; 399*91f16700Schasinglulu } 400*91f16700Schasinglulu 401*91f16700Schasinglulu /* 402*91f16700Schasinglulu * Get SOTP NonTrusted nvctr 403*91f16700Schasinglulu */ 404*91f16700Schasinglulu unsigned int sotp_get_nontrusted_nvctr(void) 405*91f16700Schasinglulu { 406*91f16700Schasinglulu uint64_t rowdata; 407*91f16700Schasinglulu uint64_t nextrowdata; 408*91f16700Schasinglulu uint32_t rownum; 409*91f16700Schasinglulu unsigned int nvctr; 410*91f16700Schasinglulu 411*91f16700Schasinglulu nvctr = SOTP_NUM_BITS_PER_ROW; 412*91f16700Schasinglulu rownum = SOTP_NVCTR_ROW_END; 413*91f16700Schasinglulu 414*91f16700Schasinglulu /* 415*91f16700Schasinglulu * Determine what row has last valid data for nontrusted ctr 416*91f16700Schasinglulu */ 417*91f16700Schasinglulu rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); 418*91f16700Schasinglulu while ((rowdata & SOTP_NVCTR_NON_TRUSTED_NEAR_END) && 419*91f16700Schasinglulu (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) && 420*91f16700Schasinglulu (rownum > SOTP_NVCTR_ROW_START)) { 421*91f16700Schasinglulu /* 422*91f16700Schasinglulu * Current row in use and has data in last 2 bits as well. 423*91f16700Schasinglulu * Check if next row also has data for this counter 424*91f16700Schasinglulu */ 425*91f16700Schasinglulu nextrowdata = sotp_mem_read(rownum-1, SOTP_ROW_NO_ECC); 426*91f16700Schasinglulu if (nextrowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) { 427*91f16700Schasinglulu /* Next row also has data so decrement rownum */ 428*91f16700Schasinglulu rownum--; 429*91f16700Schasinglulu nvctr += SOTP_NUM_BITS_PER_ROW; 430*91f16700Schasinglulu rowdata = nextrowdata; 431*91f16700Schasinglulu } else { 432*91f16700Schasinglulu /* Next row does not have data */ 433*91f16700Schasinglulu break; 434*91f16700Schasinglulu } 435*91f16700Schasinglulu } 436*91f16700Schasinglulu 437*91f16700Schasinglulu if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) { 438*91f16700Schasinglulu while ((rowdata & ((uint64_t)0x1 << (SOTP_NUM_BITS_PER_ROW-1))) 439*91f16700Schasinglulu == 440*91f16700Schasinglulu 0) { 441*91f16700Schasinglulu nvctr--; 442*91f16700Schasinglulu rowdata <<= 1; 443*91f16700Schasinglulu } 444*91f16700Schasinglulu } else 445*91f16700Schasinglulu nvctr -= SOTP_NUM_BITS_PER_ROW; 446*91f16700Schasinglulu 447*91f16700Schasinglulu INFO("NCTR %i\n", nvctr); 448*91f16700Schasinglulu return nvctr; 449*91f16700Schasinglulu } 450*91f16700Schasinglulu 451*91f16700Schasinglulu /* 452*91f16700Schasinglulu * Set SOTP Trusted nvctr 453*91f16700Schasinglulu */ 454*91f16700Schasinglulu int sotp_set_trusted_nvctr(unsigned int nvctr) 455*91f16700Schasinglulu { 456*91f16700Schasinglulu int numrows_available; 457*91f16700Schasinglulu uint32_t nontrusted_rownum; 458*91f16700Schasinglulu uint32_t trusted_rownum; 459*91f16700Schasinglulu uint64_t rowdata; 460*91f16700Schasinglulu unsigned int maxnvctr; 461*91f16700Schasinglulu 462*91f16700Schasinglulu /* 463*91f16700Schasinglulu * Read SOTP to find out how many rows are used by the 464*91f16700Schasinglulu * NON Trusted nvctr 465*91f16700Schasinglulu */ 466*91f16700Schasinglulu nontrusted_rownum = SOTP_NVCTR_ROW_END; 467*91f16700Schasinglulu do { 468*91f16700Schasinglulu rowdata = sotp_mem_read(nontrusted_rownum, SOTP_ROW_NO_ECC); 469*91f16700Schasinglulu if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) 470*91f16700Schasinglulu nontrusted_rownum--; 471*91f16700Schasinglulu else 472*91f16700Schasinglulu break; 473*91f16700Schasinglulu } while (nontrusted_rownum >= SOTP_NVCTR_ROW_START); 474*91f16700Schasinglulu 475*91f16700Schasinglulu /* 476*91f16700Schasinglulu * Calculate maximum value we can have for nvctr based on 477*91f16700Schasinglulu * number of available rows. 478*91f16700Schasinglulu */ 479*91f16700Schasinglulu numrows_available = nontrusted_rownum - SOTP_NVCTR_ROW_START + 1; 480*91f16700Schasinglulu maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW; 481*91f16700Schasinglulu if (maxnvctr) { 482*91f16700Schasinglulu /* 483*91f16700Schasinglulu * Last 2 bits of counter can't be written or it will 484*91f16700Schasinglulu * overflow with nontrusted counter 485*91f16700Schasinglulu */ 486*91f16700Schasinglulu maxnvctr -= 2; 487*91f16700Schasinglulu } 488*91f16700Schasinglulu 489*91f16700Schasinglulu if (nvctr > maxnvctr) { 490*91f16700Schasinglulu /* Error - not enough room */ 491*91f16700Schasinglulu WARN("tctr not set\n"); 492*91f16700Schasinglulu return 1; 493*91f16700Schasinglulu } 494*91f16700Schasinglulu 495*91f16700Schasinglulu /* 496*91f16700Schasinglulu * It is safe to write the nvctr, fill all 1's up to the 497*91f16700Schasinglulu * last row and then fill the last row with partial bitstream 498*91f16700Schasinglulu */ 499*91f16700Schasinglulu trusted_rownum = SOTP_NVCTR_ROW_START; 500*91f16700Schasinglulu rowdata = SOTP_NVCTR_ROW_ALL_ONES; 501*91f16700Schasinglulu 502*91f16700Schasinglulu while (nvctr >= SOTP_NUM_BITS_PER_ROW) { 503*91f16700Schasinglulu sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata); 504*91f16700Schasinglulu nvctr -= SOTP_NUM_BITS_PER_ROW; 505*91f16700Schasinglulu trusted_rownum++; 506*91f16700Schasinglulu } 507*91f16700Schasinglulu rowdata <<= (SOTP_NUM_BITS_PER_ROW - nvctr); 508*91f16700Schasinglulu sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata); 509*91f16700Schasinglulu return 0; 510*91f16700Schasinglulu } 511*91f16700Schasinglulu 512*91f16700Schasinglulu /* 513*91f16700Schasinglulu * Set SOTP NonTrusted nvctr 514*91f16700Schasinglulu */ 515*91f16700Schasinglulu int sotp_set_nontrusted_nvctr(unsigned int nvctr) 516*91f16700Schasinglulu { 517*91f16700Schasinglulu int numrows_available; 518*91f16700Schasinglulu uint32_t nontrusted_rownum; 519*91f16700Schasinglulu uint32_t trusted_rownum; 520*91f16700Schasinglulu uint64_t rowdata; 521*91f16700Schasinglulu unsigned int maxnvctr; 522*91f16700Schasinglulu 523*91f16700Schasinglulu /* 524*91f16700Schasinglulu * Read SOTP to find out how many rows are used by the 525*91f16700Schasinglulu * Trusted nvctr 526*91f16700Schasinglulu */ 527*91f16700Schasinglulu trusted_rownum = SOTP_NVCTR_ROW_START; 528*91f16700Schasinglulu do { 529*91f16700Schasinglulu rowdata = sotp_mem_read(trusted_rownum, SOTP_ROW_NO_ECC); 530*91f16700Schasinglulu if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) 531*91f16700Schasinglulu trusted_rownum++; 532*91f16700Schasinglulu else 533*91f16700Schasinglulu break; 534*91f16700Schasinglulu } while (trusted_rownum <= SOTP_NVCTR_ROW_END); 535*91f16700Schasinglulu 536*91f16700Schasinglulu /* 537*91f16700Schasinglulu * Calculate maximum value we can have for nvctr based on 538*91f16700Schasinglulu * number of available rows. 539*91f16700Schasinglulu */ 540*91f16700Schasinglulu numrows_available = SOTP_NVCTR_ROW_END - trusted_rownum + 1; 541*91f16700Schasinglulu maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW; 542*91f16700Schasinglulu if (maxnvctr) { 543*91f16700Schasinglulu /* 544*91f16700Schasinglulu * Last 2 bits of counter can't be written or it will 545*91f16700Schasinglulu * overflow with nontrusted counter 546*91f16700Schasinglulu */ 547*91f16700Schasinglulu maxnvctr -= 2; 548*91f16700Schasinglulu } 549*91f16700Schasinglulu 550*91f16700Schasinglulu if (nvctr > maxnvctr) { 551*91f16700Schasinglulu /* Error - not enough room */ 552*91f16700Schasinglulu WARN("nctr not set\n"); 553*91f16700Schasinglulu return 1; 554*91f16700Schasinglulu } 555*91f16700Schasinglulu 556*91f16700Schasinglulu /* 557*91f16700Schasinglulu * It is safe to write the nvctr, fill all 1's up to the 558*91f16700Schasinglulu * last row and then fill the last row with partial bitstream 559*91f16700Schasinglulu */ 560*91f16700Schasinglulu nontrusted_rownum = SOTP_NVCTR_ROW_END; 561*91f16700Schasinglulu rowdata = SOTP_NVCTR_ROW_ALL_ONES; 562*91f16700Schasinglulu 563*91f16700Schasinglulu while (nvctr >= SOTP_NUM_BITS_PER_ROW) { 564*91f16700Schasinglulu sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata); 565*91f16700Schasinglulu nvctr -= SOTP_NUM_BITS_PER_ROW; 566*91f16700Schasinglulu nontrusted_rownum--; 567*91f16700Schasinglulu } 568*91f16700Schasinglulu rowdata >>= (SOTP_NUM_BITS_PER_ROW - nvctr); 569*91f16700Schasinglulu sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata); 570*91f16700Schasinglulu return 0; 571*91f16700Schasinglulu } 572*91f16700Schasinglulu 573*91f16700Schasinglulu /* 574*91f16700Schasinglulu * Return the non-volatile counter value stored in the platform. The cookie 575*91f16700Schasinglulu * will contain the OID of the counter in the certificate. 576*91f16700Schasinglulu * 577*91f16700Schasinglulu * Return: 0 = success, Otherwise = error 578*91f16700Schasinglulu */ 579*91f16700Schasinglulu int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) 580*91f16700Schasinglulu { 581*91f16700Schasinglulu const char *oid; 582*91f16700Schasinglulu 583*91f16700Schasinglulu assert(cookie != NULL); 584*91f16700Schasinglulu assert(nv_ctr != NULL); 585*91f16700Schasinglulu 586*91f16700Schasinglulu *nv_ctr = 0; 587*91f16700Schasinglulu if ((sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & 588*91f16700Schasinglulu SOTP_ATF_NVCOUNTER_ENABLE_MASK)) { 589*91f16700Schasinglulu oid = (const char *)cookie; 590*91f16700Schasinglulu if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) 591*91f16700Schasinglulu *nv_ctr = sotp_get_trusted_nvctr(); 592*91f16700Schasinglulu else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) 593*91f16700Schasinglulu *nv_ctr = sotp_get_nontrusted_nvctr(); 594*91f16700Schasinglulu else 595*91f16700Schasinglulu return 1; 596*91f16700Schasinglulu } 597*91f16700Schasinglulu return 0; 598*91f16700Schasinglulu } 599*91f16700Schasinglulu 600*91f16700Schasinglulu /* 601*91f16700Schasinglulu * Store a new non-volatile counter value. 602*91f16700Schasinglulu * 603*91f16700Schasinglulu * Return: 0 = success, Otherwise = error 604*91f16700Schasinglulu */ 605*91f16700Schasinglulu int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) 606*91f16700Schasinglulu { 607*91f16700Schasinglulu const char *oid; 608*91f16700Schasinglulu 609*91f16700Schasinglulu if (sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & 610*91f16700Schasinglulu SOTP_ATF_NVCOUNTER_ENABLE_MASK) { 611*91f16700Schasinglulu INFO("set CTR %i\n", nv_ctr); 612*91f16700Schasinglulu oid = (const char *)cookie; 613*91f16700Schasinglulu if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) 614*91f16700Schasinglulu return sotp_set_trusted_nvctr(nv_ctr); 615*91f16700Schasinglulu else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) 616*91f16700Schasinglulu return sotp_set_nontrusted_nvctr(nv_ctr); 617*91f16700Schasinglulu return 1; 618*91f16700Schasinglulu } 619*91f16700Schasinglulu return 0; 620*91f16700Schasinglulu } 621*91f16700Schasinglulu 622*91f16700Schasinglulu int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) 623*91f16700Schasinglulu { 624*91f16700Schasinglulu return get_mbedtls_heap_helper(heap_addr, heap_size); 625*91f16700Schasinglulu } 626