xref: /optee_os/core/drivers/imx_snvs.c (revision ea4f7ad67de4e1d03729d5a2d393185086cb4aa3)
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_BAD    BIT(14)
27 #define SNVS_HPSR_SYS_SECURITY_CLOSED BIT(13)
28 #define SNVS_HPSR_SYS_SECURITY_OPEN   BIT(12)
29 #define SNVS_HPSR_OTPMK_SYND	      GENMASK_32(24, 16)
30 #define SNVS_HPSR_OTPMK_ZERO	      BIT(27)
31 
32 #define SNVS_HPLR_MKS_SL BIT32(9)
33 
34 #define SNVS_LPLR_MKS_HL BIT32(9)
35 
36 #define SNVS_HPCOMR_MKS_EN   BIT32(13)
37 #define SNVS_HPCOMR_NPSWA_EN BIT32(31)
38 
39 #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0)
40 
41 enum snvs_ssm_mode {
42 	SNVS_SSM_MODE_INIT,
43 	SNVS_SSM_MODE_HARD_FAIL,
44 	SNVS_SSM_MODE_SOFT_FAIL = 3,
45 	SNVS_SSM_MODE_INIT_INTERMEDIATE = 8,
46 	SNVS_SSM_MODE_CHECK,
47 	SNVS_SSM_MODE_NON_SECURE = 11,
48 	SNVS_SSM_MODE_TRUSTED = 13,
49 	SNVS_SSM_MODE_SECURE,
50 };
51 
52 enum snvs_security_cfg {
53 	SNVS_SECURITY_CFG_FAB,
54 	SNVS_SECURITY_CFG_OPEN,
55 	SNVS_SECURITY_CFG_CLOSED,
56 	SNVS_SECURITY_CFG_FIELD_RETURN,
57 };
58 
59 /*
60  * Return true if the master key is OTPMK, false otherwise.
61  */
62 static bool is_otpmk_selected(void)
63 {
64 	uint32_t hp_mks = 0;
65 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
66 
67 	hp_mks = io_read32(base + SNVS_HPCOMR);
68 
69 	/*
70 	 * The master key selection might be done by the MASTER_KEY_SEL field
71 	 * of LPMKCR instead.
72 	 */
73 	if (hp_mks & SNVS_HPCOMR_MKS_EN) {
74 		uint32_t lp_mks = io_read32(base + SNVS_LPMKCR);
75 
76 		if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL)
77 			return false;
78 	}
79 
80 	return true;
81 }
82 
83 /*
84  * Return true if the master key selection is locked, false otherwise.
85  */
86 static bool is_mks_locked(void)
87 {
88 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
89 
90 	return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL ||
91 	       io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL;
92 }
93 
94 /* Set the Master key to use OTPMK and lock it. */
95 static void set_mks_otpmk(void)
96 {
97 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
98 
99 	io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN);
100 	io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL);
101 	io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL);
102 	io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL);
103 }
104 
105 /*
106  * Return true if OTPMK is valid, false otherwise.
107  */
108 static bool is_otpmk_valid(void)
109 {
110 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
111 	uint32_t status = io_read32(base + SNVS_HPSR);
112 
113 	return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND));
114 }
115 
116 static enum snvs_security_cfg snvs_get_security_cfg(void)
117 {
118 	vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
119 				       SNVS_HPSR + sizeof(uint32_t));
120 	uint32_t val = 0;
121 
122 	val = io_read32(snvs + SNVS_HPSR);
123 	DMSG("HPSR: 0x%"PRIx32, val);
124 	if (val & SNVS_HPSR_SYS_SECURITY_BAD)
125 		return SNVS_SECURITY_CFG_FIELD_RETURN;
126 	else if (val & SNVS_HPSR_SYS_SECURITY_CLOSED)
127 		return SNVS_SECURITY_CFG_CLOSED;
128 	else if (val & SNVS_HPSR_SYS_SECURITY_OPEN)
129 		return SNVS_SECURITY_CFG_OPEN;
130 	else if (val > 4 && val < 8)
131 		return SNVS_SECURITY_CFG_OPEN;
132 
133 	return SNVS_SECURITY_CFG_FAB;
134 }
135 
136 bool snvs_is_device_closed(void)
137 {
138 	return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED);
139 }
140 
141 #ifdef CFG_RPMB_FS
142 static enum snvs_ssm_mode snvs_get_ssm_mode(void)
143 {
144 	vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
145 				       SNVS_HPSR + sizeof(uint32_t));
146 	uint32_t val = 0;
147 
148 	val = io_read32(snvs + SNVS_HPSR);
149 	val &= HPSR_SSM_ST_MASK;
150 	val = val >> HPSR_SSM_ST_SHIFT;
151 	DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val);
152 	return val;
153 }
154 
155 bool plat_rpmb_key_is_ready(void)
156 {
157 	enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT;
158 	enum snvs_security_cfg security = SNVS_SECURITY_CFG_OPEN;
159 	bool ssm_secure = false;
160 
161 	mode = snvs_get_ssm_mode();
162 	security = snvs_get_security_cfg();
163 	ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED ||
164 		      mode == SNVS_SSM_MODE_SECURE);
165 
166 	/*
167 	 * On i.MX6SDL and i.MX6DQ, the security cfg always returns
168 	 * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security
169 	 * configuration for this SoC.
170 	 */
171 	if (soc_is_imx6sdl() || soc_is_imx6dq())
172 		return ssm_secure;
173 
174 	return ssm_secure && (security == SNVS_SECURITY_CFG_CLOSED);
175 }
176 #endif /* CFG_RPMB_FS */
177 
178 TEE_Result imx_snvs_set_master_otpmk(void)
179 {
180 	if (is_otpmk_valid())
181 		return TEE_ERROR_BAD_STATE;
182 
183 	if (is_mks_locked()) {
184 		if (is_otpmk_selected())
185 			return TEE_SUCCESS;
186 
187 		return TEE_ERROR_BAD_STATE;
188 	}
189 
190 	set_mks_otpmk();
191 
192 	return TEE_SUCCESS;
193 }
194