xref: /linux/drivers/platform/mellanox/mlxbf-bootctl.c (revision 04cdaf6d8f52e5a7589cb5463b27b23dd5d0de74)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Mellanox boot control driver
4  *
5  * This driver provides a sysfs interface for systems management
6  * software to manage reset-time actions.
7  *
8  * Copyright (C) 2019 Mellanox Technologies
9  */
10 
11 #include <linux/acpi.h>
12 #include <linux/arm-smccc.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 
16 #include "mlxbf-bootctl.h"
17 
18 #define MLXBF_BOOTCTL_SB_SECURE_MASK		0x03
19 #define MLXBF_BOOTCTL_SB_TEST_MASK		0x0c
20 
21 #define MLXBF_SB_KEY_NUM			4
22 
23 /* UUID used to probe ATF service. */
24 static const char *mlxbf_bootctl_svc_uuid_str =
25 	"89c036b4-e7d7-11e6-8797-001aca00bfc4";
26 
27 struct mlxbf_bootctl_name {
28 	u32 value;
29 	const char *name;
30 };
31 
32 static struct mlxbf_bootctl_name boot_names[] = {
33 	{ MLXBF_BOOTCTL_EXTERNAL, "external" },
34 	{ MLXBF_BOOTCTL_EMMC, "emmc" },
35 	{ MLNX_BOOTCTL_SWAP_EMMC, "swap_emmc" },
36 	{ MLXBF_BOOTCTL_EMMC_LEGACY, "emmc_legacy" },
37 	{ MLXBF_BOOTCTL_NONE, "none" },
38 };
39 
40 static const char * const mlxbf_bootctl_lifecycle_states[] = {
41 	[0] = "Production",
42 	[1] = "GA Secured",
43 	[2] = "GA Non-Secured",
44 	[3] = "RMA",
45 };
46 
47 /* ARM SMC call which is atomic and no need for lock. */
48 static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg)
49 {
50 	struct arm_smccc_res res;
51 
52 	arm_smccc_smc(smc_op, smc_arg, 0, 0, 0, 0, 0, 0, &res);
53 
54 	return res.a0;
55 }
56 
57 /* Return the action in integer or an error code. */
58 static int mlxbf_bootctl_reset_action_to_val(const char *action)
59 {
60 	int i;
61 
62 	for (i = 0; i < ARRAY_SIZE(boot_names); i++)
63 		if (sysfs_streq(boot_names[i].name, action))
64 			return boot_names[i].value;
65 
66 	return -EINVAL;
67 }
68 
69 /* Return the action in string. */
70 static const char *mlxbf_bootctl_action_to_string(int action)
71 {
72 	int i;
73 
74 	for (i = 0; i < ARRAY_SIZE(boot_names); i++)
75 		if (boot_names[i].value == action)
76 			return boot_names[i].name;
77 
78 	return "invalid action";
79 }
80 
81 static ssize_t post_reset_wdog_show(struct device *dev,
82 				    struct device_attribute *attr, char *buf)
83 {
84 	int ret;
85 
86 	ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_POST_RESET_WDOG, 0);
87 	if (ret < 0)
88 		return ret;
89 
90 	return sprintf(buf, "%d\n", ret);
91 }
92 
93 static ssize_t post_reset_wdog_store(struct device *dev,
94 				     struct device_attribute *attr,
95 				     const char *buf, size_t count)
96 {
97 	unsigned long value;
98 	int ret;
99 
100 	ret = kstrtoul(buf, 10, &value);
101 	if (ret)
102 		return ret;
103 
104 	ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_SET_POST_RESET_WDOG, value);
105 	if (ret < 0)
106 		return ret;
107 
108 	return count;
109 }
110 
111 static ssize_t mlxbf_bootctl_show(int smc_op, char *buf)
112 {
113 	int action;
114 
115 	action = mlxbf_bootctl_smc(smc_op, 0);
116 	if (action < 0)
117 		return action;
118 
119 	return sprintf(buf, "%s\n", mlxbf_bootctl_action_to_string(action));
120 }
121 
122 static int mlxbf_bootctl_store(int smc_op, const char *buf, size_t count)
123 {
124 	int ret, action;
125 
126 	action = mlxbf_bootctl_reset_action_to_val(buf);
127 	if (action < 0)
128 		return action;
129 
130 	ret = mlxbf_bootctl_smc(smc_op, action);
131 	if (ret < 0)
132 		return ret;
133 
134 	return count;
135 }
136 
137 static ssize_t reset_action_show(struct device *dev,
138 				 struct device_attribute *attr, char *buf)
139 {
140 	return mlxbf_bootctl_show(MLXBF_BOOTCTL_GET_RESET_ACTION, buf);
141 }
142 
143 static ssize_t reset_action_store(struct device *dev,
144 				  struct device_attribute *attr,
145 				  const char *buf, size_t count)
146 {
147 	return mlxbf_bootctl_store(MLXBF_BOOTCTL_SET_RESET_ACTION, buf, count);
148 }
149 
150 static ssize_t second_reset_action_show(struct device *dev,
151 					struct device_attribute *attr,
152 					char *buf)
153 {
154 	return mlxbf_bootctl_show(MLXBF_BOOTCTL_GET_SECOND_RESET_ACTION, buf);
155 }
156 
157 static ssize_t second_reset_action_store(struct device *dev,
158 					 struct device_attribute *attr,
159 					 const char *buf, size_t count)
160 {
161 	return mlxbf_bootctl_store(MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION, buf,
162 				   count);
163 }
164 
165 static ssize_t lifecycle_state_show(struct device *dev,
166 				    struct device_attribute *attr, char *buf)
167 {
168 	int lc_state;
169 
170 	lc_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
171 				     MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE);
172 	if (lc_state < 0)
173 		return lc_state;
174 
175 	lc_state &=
176 		MLXBF_BOOTCTL_SB_TEST_MASK | MLXBF_BOOTCTL_SB_SECURE_MASK;
177 
178 	/*
179 	 * If the test bits are set, we specify that the current state may be
180 	 * due to using the test bits.
181 	 */
182 	if (lc_state & MLXBF_BOOTCTL_SB_TEST_MASK) {
183 		lc_state &= MLXBF_BOOTCTL_SB_SECURE_MASK;
184 
185 		return sprintf(buf, "%s(test)\n",
186 			       mlxbf_bootctl_lifecycle_states[lc_state]);
187 	}
188 
189 	return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]);
190 }
191 
192 static ssize_t secure_boot_fuse_state_show(struct device *dev,
193 					   struct device_attribute *attr,
194 					   char *buf)
195 {
196 	int burnt, valid, key, key_state, buf_len = 0, upper_key_used = 0;
197 	const char *status;
198 
199 	key_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
200 				      MLXBF_BOOTCTL_FUSE_STATUS_KEYS);
201 	if (key_state < 0)
202 		return key_state;
203 
204 	/*
205 	 * key_state contains the bits for 4 Key versions, loaded from eFuses
206 	 * after a hard reset. Lower 4 bits are a thermometer code indicating
207 	 * key programming has started for key n (0000 = none, 0001 = version 0,
208 	 * 0011 = version 1, 0111 = version 2, 1111 = version 3). Upper 4 bits
209 	 * are a thermometer code indicating key programming has completed for
210 	 * key n (same encodings as the start bits). This allows for detection
211 	 * of an interruption in the programming process which has left the key
212 	 * partially programmed (and thus invalid). The process is to burn the
213 	 * eFuse for the new key start bit, burn the key eFuses, then burn the
214 	 * eFuse for the new key complete bit.
215 	 *
216 	 * For example 0000_0000: no key valid, 0001_0001: key version 0 valid,
217 	 * 0011_0011: key 1 version valid, 0011_0111: key version 2 started
218 	 * programming but did not complete, etc. The most recent key for which
219 	 * both start and complete bit is set is loaded. On soft reset, this
220 	 * register is not modified.
221 	 */
222 	for (key = MLXBF_SB_KEY_NUM - 1; key >= 0; key--) {
223 		burnt = key_state & BIT(key);
224 		valid = key_state & BIT(key + MLXBF_SB_KEY_NUM);
225 
226 		if (burnt && valid)
227 			upper_key_used = 1;
228 
229 		if (upper_key_used) {
230 			if (burnt)
231 				status = valid ? "Used" : "Wasted";
232 			else
233 				status = valid ? "Invalid" : "Skipped";
234 		} else {
235 			if (burnt)
236 				status = valid ? "InUse" : "Incomplete";
237 			else
238 				status = valid ? "Invalid" : "Free";
239 		}
240 		buf_len += sprintf(buf + buf_len, "%d:%s ", key, status);
241 	}
242 	buf_len += sprintf(buf + buf_len, "\n");
243 
244 	return buf_len;
245 }
246 
247 static DEVICE_ATTR_RW(post_reset_wdog);
248 static DEVICE_ATTR_RW(reset_action);
249 static DEVICE_ATTR_RW(second_reset_action);
250 static DEVICE_ATTR_RO(lifecycle_state);
251 static DEVICE_ATTR_RO(secure_boot_fuse_state);
252 
253 static struct attribute *mlxbf_bootctl_attrs[] = {
254 	&dev_attr_post_reset_wdog.attr,
255 	&dev_attr_reset_action.attr,
256 	&dev_attr_second_reset_action.attr,
257 	&dev_attr_lifecycle_state.attr,
258 	&dev_attr_secure_boot_fuse_state.attr,
259 	NULL
260 };
261 
262 ATTRIBUTE_GROUPS(mlxbf_bootctl);
263 
264 static const struct acpi_device_id mlxbf_bootctl_acpi_ids[] = {
265 	{"MLNXBF04", 0},
266 	{}
267 };
268 
269 MODULE_DEVICE_TABLE(acpi, mlxbf_bootctl_acpi_ids);
270 
271 static bool mlxbf_bootctl_guid_match(const guid_t *guid,
272 				     const struct arm_smccc_res *res)
273 {
274 	guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16,
275 			      res->a2, res->a2 >> 8, res->a2 >> 16,
276 			      res->a2 >> 24, res->a3, res->a3 >> 8,
277 			      res->a3 >> 16, res->a3 >> 24);
278 
279 	return guid_equal(guid, &id);
280 }
281 
282 static int mlxbf_bootctl_probe(struct platform_device *pdev)
283 {
284 	struct arm_smccc_res res = { 0 };
285 	guid_t guid;
286 	int ret;
287 
288 	/* Ensure we have the UUID we expect for this service. */
289 	arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);
290 	guid_parse(mlxbf_bootctl_svc_uuid_str, &guid);
291 	if (!mlxbf_bootctl_guid_match(&guid, &res))
292 		return -ENODEV;
293 
294 	/*
295 	 * When watchdog is used, it sets boot mode to MLXBF_BOOTCTL_SWAP_EMMC
296 	 * in case of boot failures. However it doesn't clear the state if there
297 	 * is no failure. Restore the default boot mode here to avoid any
298 	 * unnecessary boot partition swapping.
299 	 */
300 	ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_SET_RESET_ACTION,
301 				MLXBF_BOOTCTL_EMMC);
302 	if (ret < 0)
303 		dev_warn(&pdev->dev, "Unable to reset the EMMC boot mode\n");
304 
305 	return 0;
306 }
307 
308 static struct platform_driver mlxbf_bootctl_driver = {
309 	.probe = mlxbf_bootctl_probe,
310 	.driver = {
311 		.name = "mlxbf-bootctl",
312 		.dev_groups = mlxbf_bootctl_groups,
313 		.acpi_match_table = mlxbf_bootctl_acpi_ids,
314 	}
315 };
316 
317 module_platform_driver(mlxbf_bootctl_driver);
318 
319 MODULE_DESCRIPTION("Mellanox boot control driver");
320 MODULE_LICENSE("GPL v2");
321 MODULE_AUTHOR("Mellanox Technologies");
322