xref: /optee_os/core/drivers/imx_snvs.c (revision ad0ae8003583f7270d62568c85a32a5f25a601c6)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2020 Pengutronix
4  * Rouven Czerwinski <entwicklung@pengutronix.de>
5  * Copyright 2022 NXP
6  */
7 
8 #include <drivers/imx_snvs.h>
9 #include <io.h>
10 #include <mm/core_memprot.h>
11 #include <mm/core_mmu.h>
12 #include <stdint.h>
13 #include <tee/tee_fs.h>
14 #include <types_ext.h>
15 #include <trace.h>
16 
17 #define SNVS_HPLR   0x00
18 #define SNVS_HPCOMR 0x04
19 #define SNVS_HPSR   0x14
20 #define SNVS_LPLR   0x34
21 #define SNVS_LPMKCR 0x3C
22 
23 #define HPSR_SSM_ST_MASK  GENMASK_32(11, 8)
24 #define HPSR_SSM_ST_SHIFT 8
25 
26 #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12
27 
28 #define SNVS_HPSR_OTPMK_SYND	      GENMASK_32(24, 16)
29 #define SNVS_HPSR_OTPMK_ZERO	      BIT(27)
30 
31 #define SNVS_HPLR_MKS_SL BIT32(9)
32 
33 #define SNVS_LPLR_MKS_HL BIT32(9)
34 
35 #define SNVS_HPCOMR_MKS_EN   BIT32(13)
36 #define SNVS_HPCOMR_NPSWA_EN BIT32(31)
37 
38 #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0)
39 
40 enum snvs_ssm_mode {
41 	SNVS_SSM_MODE_INIT,
42 	SNVS_SSM_MODE_HARD_FAIL,
43 	SNVS_SSM_MODE_SOFT_FAIL = 3,
44 	SNVS_SSM_MODE_INIT_INTERMEDIATE = 8,
45 	SNVS_SSM_MODE_CHECK,
46 	SNVS_SSM_MODE_NON_SECURE = 11,
47 	SNVS_SSM_MODE_TRUSTED = 13,
48 	SNVS_SSM_MODE_SECURE = 15,
49 };
50 
51 enum snvs_security_cfg {
52 	SNVS_SECURITY_CFG_FAB,
53 	SNVS_SECURITY_CFG_OPEN,
54 	SNVS_SECURITY_CFG_CLOSED,
55 	SNVS_SECURITY_CFG_FIELD_RETURN,
56 };
57 
58 /*
59  * Return true if the master key is OTPMK, false otherwise.
60  */
61 static bool is_otpmk_selected(void)
62 {
63 	uint32_t hp_mks = 0;
64 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
65 
66 	hp_mks = io_read32(base + SNVS_HPCOMR);
67 
68 	/*
69 	 * The master key selection might be done by the MASTER_KEY_SEL field
70 	 * of LPMKCR instead.
71 	 */
72 	if (hp_mks & SNVS_HPCOMR_MKS_EN) {
73 		uint32_t lp_mks = io_read32(base + SNVS_LPMKCR);
74 
75 		if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL)
76 			return false;
77 	}
78 
79 	return true;
80 }
81 
82 /*
83  * Return true if the master key selection is locked, false otherwise.
84  */
85 static bool is_mks_locked(void)
86 {
87 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
88 
89 	return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL ||
90 	       io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL;
91 }
92 
93 /* Set the Master key to use OTPMK and lock it. */
94 static void set_mks_otpmk(void)
95 {
96 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
97 
98 	io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN);
99 	io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL);
100 	io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL);
101 	io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL);
102 }
103 
104 /*
105  * Return true if OTPMK is valid, false otherwise.
106  */
107 static bool is_otpmk_valid(void)
108 {
109 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
110 	uint32_t status = io_read32(base + SNVS_HPSR);
111 
112 	return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND));
113 }
114 
115 #ifdef CFG_MX8M
116 #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(15, 12)
117 
118 static enum snvs_security_cfg snvs_get_security_cfg(void)
119 {
120 	uint32_t val = 0;
121 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
122 				       SNVS_SIZE);
123 
124 	val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >>
125 	      SNVS_HPSR_SYS_SECURITY_CFG_OFFSET;
126 
127 	switch (val) {
128 	case 0b0000:
129 	case 0b1000:
130 		return SNVS_SECURITY_CFG_FAB;
131 	case 0b0001:
132 	case 0b0010:
133 	case 0b0011:
134 		return SNVS_SECURITY_CFG_OPEN;
135 	case 0b1010:
136 	case 0b1001:
137 	case 0b1011:
138 		return SNVS_SECURITY_CFG_CLOSED;
139 	default:
140 		return SNVS_SECURITY_CFG_FIELD_RETURN;
141 	}
142 }
143 #else
144 #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12)
145 
146 static enum snvs_security_cfg snvs_get_security_cfg(void)
147 {
148 	uint32_t val = 0;
149 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
150 				       SNVS_SIZE);
151 
152 	val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >>
153 	      SNVS_HPSR_SYS_SECURITY_CFG_OFFSET;
154 
155 	switch (val) {
156 	case 0b000:
157 		return SNVS_SECURITY_CFG_FAB;
158 	case 0b001:
159 		return SNVS_SECURITY_CFG_OPEN;
160 	case 0b011:
161 		return SNVS_SECURITY_CFG_CLOSED;
162 	default:
163 		return SNVS_SECURITY_CFG_FIELD_RETURN;
164 	}
165 }
166 #endif
167 
168 bool snvs_is_device_closed(void)
169 {
170 	return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED);
171 }
172 
173 #ifdef CFG_RPMB_FS
174 static enum snvs_ssm_mode snvs_get_ssm_mode(void)
175 {
176 	vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
177 				       SNVS_HPSR + sizeof(uint32_t));
178 	uint32_t val = 0;
179 
180 	val = io_read32(snvs + SNVS_HPSR);
181 	val &= HPSR_SSM_ST_MASK;
182 	val = val >> HPSR_SSM_ST_SHIFT;
183 	DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val);
184 	return val;
185 }
186 
187 bool plat_rpmb_key_is_ready(void)
188 {
189 	enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT;
190 	bool ssm_secure = false;
191 
192 	mode = snvs_get_ssm_mode();
193 	ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED ||
194 		      mode == SNVS_SSM_MODE_SECURE);
195 
196 	/*
197 	 * On i.MX6SDL and i.MX6DQ, the security cfg always returns
198 	 * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security
199 	 * configuration for this SoC.
200 	 */
201 	if (soc_is_imx6sdl() || soc_is_imx6dq())
202 		return ssm_secure;
203 
204 	return ssm_secure && snvs_is_device_closed();
205 }
206 #endif /* CFG_RPMB_FS */
207 
208 TEE_Result imx_snvs_set_master_otpmk(void)
209 {
210 	if (!is_otpmk_valid())
211 		return TEE_ERROR_BAD_STATE;
212 
213 	if (is_mks_locked()) {
214 		if (is_otpmk_selected())
215 			return TEE_SUCCESS;
216 
217 		return TEE_ERROR_BAD_STATE;
218 	}
219 
220 	set_mks_otpmk();
221 
222 	return TEE_SUCCESS;
223 }
224