xref: /arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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