xref: /linux/drivers/firmware/coreboot/coreboot-cfr.c (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * coreboot CFR firmware attributes driver.
4  *
5  * Parses LB_TAG_CFR_ROOT records from the coreboot table and exposes
6  * runtime EFI variable-backed options through the firmware-attributes class.
7  */
8 
9 #include <linux/array_size.h>
10 #include <linux/bitops.h>
11 #include <linux/cleanup.h>
12 #include <linux/compiler_attributes.h>
13 #include <linux/container_of.h>
14 #include <linux/crc32.h>
15 #include <linux/ctype.h>
16 #include <linux/device.h>
17 #include <linux/device-id/coreboot.h>
18 #include <linux/efi.h>
19 #include <linux/err.h>
20 #include <linux/firmware_attributes.h>
21 #include <linux/io.h>
22 #include <linux/kdev_t.h>
23 #include <linux/kobject.h>
24 #include <linux/kstrtox.h>
25 #include <linux/limits.h>
26 #include <linux/list.h>
27 #include <linux/module.h>
28 #include <linux/mutex.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <linux/sysfs.h>
32 #include <linux/types.h>
33 
34 #include "coreboot_table.h"
35 
36 #define DRIVER_NAME "coreboot-cfr"
37 
38 #define LB_TAG_CFR_ROOT		0x47
39 #define CFR_VERSION		0
40 
41 enum cfr_tags {
42 	CFR_TAG_OPTION_FORM		= 1,
43 	CFR_TAG_ENUM_VALUE		= 2,
44 	CFR_TAG_OPTION_ENUM		= 3,
45 	CFR_TAG_OPTION_NUMBER		= 4,
46 	CFR_TAG_OPTION_BOOL		= 5,
47 	CFR_TAG_VARCHAR_OPT_NAME	= 7,
48 	CFR_TAG_VARCHAR_UI_NAME		= 8,
49 	CFR_TAG_RUNTIME_APPLY		= 13,
50 };
51 
52 enum cfr_option_flags {
53 	CFR_OPTFLAG_READONLY	= BIT(0),
54 	CFR_OPTFLAG_INACTIVE	= BIT(1),
55 	CFR_OPTFLAG_SUPPRESS	= BIT(2),
56 	CFR_OPTFLAG_VOLATILE	= BIT(3),
57 	CFR_OPTFLAG_RUNTIME	= BIT(4),
58 };
59 
60 enum cfr_runtime_apply_method {
61 	CFR_RUNTIME_APPLY_NONE		= 0,
62 	CFR_RUNTIME_APPLY_APM_CNT	= 1,
63 };
64 
65 struct lb_cfr {
66 	u32 tag;
67 	u32 size;
68 	u32 version;
69 	u32 checksum;
70 } __packed;
71 
72 struct lb_cfr_varbinary {
73 	u32 tag;
74 	u32 size;
75 	u32 data_length;
76 } __packed;
77 
78 struct lb_cfr_enum_value {
79 	u32 tag;
80 	u32 size;
81 	u32 value;
82 } __packed;
83 
84 struct lb_cfr_runtime_apply {
85 	u32 tag;
86 	u32 size;
87 	u32 method;
88 	u32 id;
89 } __packed;
90 
91 struct lb_cfr_numeric_option {
92 	u32 tag;
93 	u32 size;
94 	cb_u64 object_id;
95 	cb_u64 dependency_id;
96 	u32 flags;
97 	u32 default_value;
98 	u32 min;
99 	u32 max;
100 	u32 step;
101 	u32 display_flags;
102 } __packed;
103 
104 struct lb_cfr_option_form {
105 	u32 tag;
106 	u32 size;
107 	cb_u64 object_id;
108 	cb_u64 dependency_id;
109 	u32 flags;
110 } __packed;
111 
112 #define COREBOOT_CFR_OPT_SKIP_FLAGS \
113 	(CFR_OPTFLAG_SUPPRESS | CFR_OPTFLAG_VOLATILE)
114 
115 #define COREBOOT_CFR_OPT_READ_ONLY_FLAGS \
116 	(CFR_OPTFLAG_READONLY | CFR_OPTFLAG_INACTIVE)
117 
118 #define COREBOOT_CFR_EFI_ATTRS \
119 	(EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | \
120 	 EFI_VARIABLE_RUNTIME_ACCESS)
121 
122 #define COREBOOT_CFR_APM_CNT_PORT	0xb2
123 #define COREBOOT_CFR_APM_STS_PORT	0xb3
124 #define COREBOOT_CFR_APM_APPLY_CMD	0xe3
125 #define COREBOOT_CFR_MAX_FORM_DEPTH	16
126 
127 static efi_guid_t coreboot_cfr_guid = EFI_GUID(0xceae4c1d, 0x335b, 0x4685,
128 					       0xa4, 0xa0, 0xfc, 0x4a,
129 					       0x94, 0xee, 0xa0, 0x85);
130 
131 enum coreboot_cfr_setting_type {
132 	COREBOOT_CFR_SETTING_ENUM,
133 	COREBOOT_CFR_SETTING_NUMBER,
134 	COREBOOT_CFR_SETTING_BOOL,
135 };
136 
137 struct coreboot_cfr_enum {
138 	char *label;
139 	u32 value;
140 };
141 
142 struct coreboot_cfr_setting {
143 	struct kobject kobj;
144 	struct list_head node;
145 	struct coreboot_cfr_drvdata *drvdata;
146 	enum coreboot_cfr_setting_type type;
147 	char *name;
148 	char *display_name;
149 	struct coreboot_cfr_enum *values;
150 	unsigned int n_values;
151 	u32 default_value;
152 	u32 min;
153 	u32 max;
154 	u32 step;
155 	u32 runtime_apply_method;
156 	u32 runtime_apply_id;
157 	bool read_only;
158 };
159 
160 struct coreboot_cfr_drvdata {
161 	struct device *class_dev;
162 	struct kset *attrs_kset;
163 	struct list_head settings;
164 	/* Serializes EFI variable writes and the matching runtime apply hook. */
165 	struct mutex lock;
166 	bool efi_writes_supported;
167 	bool pending_reboot;
168 };
169 
170 struct coreboot_cfr_iterator {
171 	const u8 *cursor;
172 	size_t remaining;
173 };
174 
175 static struct coreboot_cfr_setting *to_coreboot_cfr_setting(struct kobject *kobj)
176 {
177 	return container_of(kobj, struct coreboot_cfr_setting, kobj);
178 }
179 
180 static bool coreboot_cfr_string_is_valid_name(const char *name)
181 {
182 	return name && name[0] && !strchr(name, '/') &&
183 		strcmp(name, "pending_reboot") != 0;
184 }
185 
186 static bool coreboot_cfr_string_is_valid_label(const char *label)
187 {
188 	return label && !strchr(label, ';') && !strchr(label, '\n');
189 }
190 
191 static char *coreboot_cfr_string_dup(const struct lb_cfr_varbinary *str)
192 {
193 	const char *data = (const char *)(str + 1);
194 	size_t len = str->data_length;
195 
196 	if (len && !data[len - 1])
197 		len--;
198 
199 	return kmemdup_nul(data, len, GFP_KERNEL);
200 }
201 
202 static const struct coreboot_table_entry *
203 coreboot_cfr_next_entry(struct coreboot_cfr_iterator *iterator)
204 {
205 	const struct coreboot_table_entry *entry;
206 
207 	if (!iterator->remaining)
208 		return NULL;
209 
210 	if (iterator->remaining < sizeof(*entry))
211 		return ERR_PTR(-EINVAL);
212 
213 	entry = (const struct coreboot_table_entry *)iterator->cursor;
214 	if (entry->size < sizeof(*entry) || entry->size > iterator->remaining)
215 		return ERR_PTR(-EINVAL);
216 
217 	iterator->cursor += entry->size;
218 	iterator->remaining -= entry->size;
219 
220 	return entry;
221 }
222 
223 static const struct coreboot_table_entry *
224 coreboot_cfr_child_entry(const void *base, size_t len, u32 tag)
225 {
226 	struct coreboot_cfr_iterator iterator = {
227 		.cursor = base,
228 		.remaining = len,
229 	};
230 	const struct coreboot_table_entry *entry;
231 
232 	for (;;) {
233 		entry = coreboot_cfr_next_entry(&iterator);
234 		if (IS_ERR_OR_NULL(entry))
235 			return entry;
236 
237 		if (entry->tag == tag)
238 			return entry;
239 	}
240 }
241 
242 static const struct lb_cfr_varbinary *
243 coreboot_cfr_child_string(const void *base, size_t len, u32 tag)
244 {
245 	const struct lb_cfr_varbinary *str;
246 	const struct coreboot_table_entry *entry;
247 
248 	entry = coreboot_cfr_child_entry(base, len, tag);
249 	if (IS_ERR(entry))
250 		return ERR_CAST(entry);
251 	if (!entry)
252 		return NULL;
253 
254 	if (entry->size < sizeof(*str))
255 		return ERR_PTR(-EINVAL);
256 
257 	str = (const struct lb_cfr_varbinary *)entry;
258 	if (str->data_length > entry->size - sizeof(*str))
259 		return ERR_PTR(-EINVAL);
260 
261 	return str;
262 }
263 
264 static const struct lb_cfr_runtime_apply *
265 coreboot_cfr_child_runtime_apply(const void *base, size_t len)
266 {
267 	const struct lb_cfr_runtime_apply *runtime_apply;
268 	const struct coreboot_table_entry *entry;
269 
270 	entry = coreboot_cfr_child_entry(base, len, CFR_TAG_RUNTIME_APPLY);
271 	if (IS_ERR(entry))
272 		return ERR_CAST(entry);
273 	if (!entry)
274 		return NULL;
275 
276 	if (entry->size < sizeof(*runtime_apply))
277 		return ERR_PTR(-EINVAL);
278 
279 	runtime_apply = (const struct lb_cfr_runtime_apply *)entry;
280 	if (runtime_apply->method == CFR_RUNTIME_APPLY_APM_CNT &&
281 	    runtime_apply->id > U8_MAX)
282 		return ERR_PTR(-EINVAL);
283 
284 	return runtime_apply;
285 }
286 
287 static efi_char16_t *coreboot_cfr_efi_name(const char *name)
288 {
289 	size_t len, i;
290 
291 	len = strlen(name);
292 	if (len >= EFI_VAR_NAME_LEN)
293 		return ERR_PTR(-ENAMETOOLONG);
294 
295 	efi_char16_t *efi_name __free(kfree) =
296 		kcalloc(len + 1, sizeof(*efi_name), GFP_KERNEL);
297 	if (!efi_name)
298 		return ERR_PTR(-ENOMEM);
299 
300 	for (i = 0; i < len; i++) {
301 		if (!isascii(name[i]))
302 			return ERR_PTR(-EINVAL);
303 		efi_name[i] = name[i];
304 	}
305 
306 	return no_free_ptr(efi_name);
307 }
308 
309 /* Caller must hold the efivar lock. */
310 static int coreboot_cfr_read_efi_value(efi_char16_t *efi_name, u32 *value,
311 				       u32 *attrs)
312 {
313 	unsigned long size = sizeof(__le32);
314 	efi_status_t status;
315 	__le32 data;
316 	u32 attr;
317 
318 	status = efivar_get_variable(efi_name, &coreboot_cfr_guid, &attr,
319 				     &size, &data);
320 	if (status != EFI_SUCCESS)
321 		return efi_status_to_err(status);
322 
323 	if (size != sizeof(data))
324 		return -EINVAL;
325 
326 	if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS))
327 		return -EOPNOTSUPP;
328 
329 	*value = le32_to_cpu(data);
330 	if (attrs)
331 		*attrs = attr;
332 
333 	return 0;
334 }
335 
336 static int coreboot_cfr_read_value(const struct coreboot_cfr_setting *setting,
337 				   u32 *value, u32 *attrs)
338 {
339 	efi_char16_t *efi_name __free(kfree) =
340 		coreboot_cfr_efi_name(setting->name);
341 	int ret;
342 
343 	if (IS_ERR(efi_name))
344 		return PTR_ERR(no_free_ptr(efi_name));
345 
346 	ret = efivar_lock();
347 	if (ret)
348 		return ret;
349 
350 	ret = coreboot_cfr_read_efi_value(efi_name, value, attrs);
351 	efivar_unlock();
352 
353 	return ret;
354 }
355 
356 /* Caller must hold the efivar lock. */
357 static int coreboot_cfr_write_efi_value(efi_char16_t *efi_name, u32 value,
358 					u32 attrs)
359 {
360 	efi_status_t status;
361 	__le32 data;
362 
363 	if (!efivar_supports_writes())
364 		return -EROFS;
365 
366 	data = cpu_to_le32(value);
367 	status = efivar_set_variable_locked(efi_name, &coreboot_cfr_guid, attrs,
368 					    sizeof(data), &data, false);
369 	if (status != EFI_SUCCESS)
370 		return efi_status_to_err(status);
371 
372 	return 0;
373 }
374 
375 static int coreboot_cfr_apply_runtime(struct coreboot_cfr_setting *setting)
376 {
377 	u8 status;
378 
379 	if (setting->runtime_apply_method != CFR_RUNTIME_APPLY_APM_CNT)
380 		return -EOPNOTSUPP;
381 
382 	outb((u8)setting->runtime_apply_id, COREBOOT_CFR_APM_STS_PORT);
383 	outb(COREBOOT_CFR_APM_APPLY_CMD, COREBOOT_CFR_APM_CNT_PORT);
384 	status = inb(COREBOOT_CFR_APM_STS_PORT);
385 	if (status)
386 		return -EIO;
387 
388 	return 0;
389 }
390 
391 static int coreboot_cfr_write_value(struct coreboot_cfr_setting *setting,
392 				    u32 value)
393 {
394 	efi_char16_t *efi_name;
395 	u32 attrs;
396 	u32 old;
397 	int restore_ret;
398 	int ret;
399 
400 	if (setting->read_only)
401 		return -EACCES;
402 
403 	efi_name = coreboot_cfr_efi_name(setting->name);
404 	if (IS_ERR(efi_name))
405 		return PTR_ERR(efi_name);
406 
407 	mutex_lock(&setting->drvdata->lock);
408 
409 	ret = efivar_lock();
410 	if (ret)
411 		goto out_unlock_mutex;
412 
413 	ret = coreboot_cfr_read_efi_value(efi_name, &old, &attrs);
414 	if (ret)
415 		goto out_unlock_efi;
416 
417 	if ((attrs & COREBOOT_CFR_EFI_ATTRS) != COREBOOT_CFR_EFI_ATTRS) {
418 		ret = -EOPNOTSUPP;
419 		goto out_unlock_efi;
420 	}
421 
422 	if (old == value)
423 		goto out_unlock_efi;
424 
425 	ret = coreboot_cfr_write_efi_value(efi_name, value, attrs);
426 	if (ret)
427 		goto out_unlock_efi;
428 
429 	ret = coreboot_cfr_apply_runtime(setting);
430 	if (ret == -EOPNOTSUPP) {
431 		/* EFI changed; firmware will consume it after reboot. */
432 		setting->drvdata->pending_reboot = true;
433 		ret = 0;
434 	} else if (ret) {
435 		restore_ret = coreboot_cfr_write_efi_value(efi_name, old, attrs);
436 		if (restore_ret) {
437 			setting->drvdata->pending_reboot = true;
438 			ret = restore_ret;
439 		} else {
440 			goto out_unlock_efi;
441 		}
442 	}
443 
444 	efivar_unlock();
445 	kobject_uevent(&setting->drvdata->class_dev->kobj, KOBJ_CHANGE);
446 	mutex_unlock(&setting->drvdata->lock);
447 	kfree(efi_name);
448 	return ret;
449 
450 out_unlock_efi:
451 	efivar_unlock();
452 out_unlock_mutex:
453 	mutex_unlock(&setting->drvdata->lock);
454 	kfree(efi_name);
455 	return ret;
456 }
457 
458 static const char *
459 coreboot_cfr_label_from_value(const struct coreboot_cfr_setting *setting,
460 			      u32 value)
461 {
462 	unsigned int i;
463 
464 	for (i = 0; i < setting->n_values; i++) {
465 		if (setting->values[i].value == value)
466 			return setting->values[i].label;
467 	}
468 
469 	return NULL;
470 }
471 
472 static int coreboot_cfr_parse_value(struct coreboot_cfr_setting *setting,
473 				    const char *label, u32 *value_out)
474 {
475 	unsigned int i;
476 
477 	for (i = 0; i < setting->n_values; i++) {
478 		if (!sysfs_streq(label, setting->values[i].label))
479 			continue;
480 
481 		*value_out = setting->values[i].value;
482 		return 0;
483 	}
484 
485 	return kstrtou32(label, 0, value_out);
486 }
487 
488 static bool coreboot_cfr_value_is_valid(struct coreboot_cfr_setting *setting,
489 					u32 value)
490 {
491 	u32 delta;
492 
493 	if (setting->type != COREBOOT_CFR_SETTING_NUMBER) {
494 		/* Enum and bool values are valid only if they have a label. */
495 		return coreboot_cfr_label_from_value(setting, value);
496 	}
497 
498 	if (value < setting->min || value > setting->max)
499 		return false;
500 
501 	if (!setting->step)
502 		return true;
503 
504 	delta = value - setting->min;
505 	return delta % setting->step == 0;
506 }
507 
508 static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
509 			 char *buf)
510 {
511 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
512 
513 	if (setting->type == COREBOOT_CFR_SETTING_NUMBER)
514 		return sysfs_emit(buf, "integer\n");
515 
516 	return sysfs_emit(buf, "enumeration\n");
517 }
518 
519 static ssize_t display_name_language_code_show(struct kobject *kobj,
520 					       struct kobj_attribute *attr,
521 					       char *buf)
522 {
523 	return sysfs_emit(buf, "en_US.UTF-8\n");
524 }
525 
526 static ssize_t display_name_show(struct kobject *kobj,
527 				 struct kobj_attribute *attr, char *buf)
528 {
529 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
530 
531 	return sysfs_emit(buf, "%s\n", setting->display_name);
532 }
533 
534 static ssize_t possible_values_show(struct kobject *kobj,
535 				    struct kobj_attribute *attr, char *buf)
536 {
537 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
538 	ssize_t len = 0;
539 	unsigned int i;
540 
541 	for (i = 0; i < setting->n_values; i++) {
542 		len += sysfs_emit_at(buf, len, "%s%s", i ? ";" : "",
543 				     setting->values[i].label);
544 	}
545 
546 	len += sysfs_emit_at(buf, len, "\n");
547 	return len;
548 }
549 
550 static ssize_t min_value_show(struct kobject *kobj, struct kobj_attribute *attr,
551 			      char *buf)
552 {
553 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
554 
555 	return sysfs_emit(buf, "%u\n", setting->min);
556 }
557 
558 static ssize_t max_value_show(struct kobject *kobj, struct kobj_attribute *attr,
559 			      char *buf)
560 {
561 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
562 
563 	return sysfs_emit(buf, "%u\n", setting->max);
564 }
565 
566 static ssize_t scalar_increment_show(struct kobject *kobj,
567 				     struct kobj_attribute *attr, char *buf)
568 {
569 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
570 
571 	return sysfs_emit(buf, "%u\n", setting->step);
572 }
573 
574 static ssize_t default_value_show(struct kobject *kobj,
575 				  struct kobj_attribute *attr, char *buf)
576 {
577 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
578 	const char *label;
579 
580 	if (setting->type == COREBOOT_CFR_SETTING_NUMBER)
581 		return sysfs_emit(buf, "%u\n", setting->default_value);
582 
583 	label = coreboot_cfr_label_from_value(setting, setting->default_value);
584 	if (!label)
585 		return sysfs_emit(buf, "%u\n", setting->default_value);
586 
587 	return sysfs_emit(buf, "%s\n", label);
588 }
589 
590 static ssize_t current_value_show(struct kobject *kobj,
591 				  struct kobj_attribute *attr, char *buf)
592 {
593 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
594 	const char *label;
595 	u32 value;
596 	int ret;
597 
598 	ret = coreboot_cfr_read_value(setting, &value, NULL);
599 	if (ret)
600 		return ret;
601 
602 	if (setting->type == COREBOOT_CFR_SETTING_NUMBER)
603 		return sysfs_emit(buf, "%u\n", value);
604 
605 	label = coreboot_cfr_label_from_value(setting, value);
606 	if (!label)
607 		return -EINVAL;
608 
609 	return sysfs_emit(buf, "%s\n", label);
610 }
611 
612 static ssize_t current_value_store(struct kobject *kobj,
613 				   struct kobj_attribute *attr,
614 				   const char *buf, size_t count)
615 {
616 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
617 	u32 value;
618 	int ret;
619 
620 	ret = coreboot_cfr_parse_value(setting, buf, &value);
621 	if (ret)
622 		return ret;
623 
624 	if (!coreboot_cfr_value_is_valid(setting, value))
625 		return -EINVAL;
626 
627 	ret = coreboot_cfr_write_value(setting, value);
628 	if (ret)
629 		return ret;
630 
631 	return count;
632 }
633 
634 static struct kobj_attribute type_attr = __ATTR_RO(type);
635 static struct kobj_attribute display_name_language_code_attr =
636 	__ATTR_RO(display_name_language_code);
637 static struct kobj_attribute display_name_attr = __ATTR_RO(display_name);
638 static struct kobj_attribute possible_values_attr = __ATTR_RO(possible_values);
639 static struct kobj_attribute min_value_attr = __ATTR_RO(min_value);
640 static struct kobj_attribute max_value_attr = __ATTR_RO(max_value);
641 static struct kobj_attribute scalar_increment_attr = __ATTR_RO(scalar_increment);
642 static struct kobj_attribute default_value_attr = __ATTR_RO(default_value);
643 static struct kobj_attribute current_value_attr = __ATTR_RW(current_value);
644 
645 static struct attribute *coreboot_cfr_setting_attrs[] = {
646 	&type_attr.attr,
647 	&display_name_language_code_attr.attr,
648 	&display_name_attr.attr,
649 	&possible_values_attr.attr,
650 	&min_value_attr.attr,
651 	&max_value_attr.attr,
652 	&scalar_increment_attr.attr,
653 	&default_value_attr.attr,
654 	&current_value_attr.attr,
655 	NULL,
656 };
657 
658 static umode_t coreboot_cfr_attr_is_visible(struct kobject *kobj,
659 					    struct attribute *attr, int n)
660 {
661 	struct coreboot_cfr_setting *setting = to_coreboot_cfr_setting(kobj);
662 
663 	if (setting->type == COREBOOT_CFR_SETTING_NUMBER &&
664 	    attr == &possible_values_attr.attr)
665 		return 0;
666 
667 	if (setting->type != COREBOOT_CFR_SETTING_NUMBER &&
668 	    (attr == &min_value_attr.attr || attr == &max_value_attr.attr ||
669 	     attr == &scalar_increment_attr.attr))
670 		return 0;
671 
672 	if (setting->read_only && attr == &current_value_attr.attr)
673 		return 0444;
674 
675 	return attr->mode;
676 }
677 
678 static const struct attribute_group coreboot_cfr_setting_group = {
679 	.attrs = coreboot_cfr_setting_attrs,
680 	.is_visible = coreboot_cfr_attr_is_visible,
681 };
682 
683 static void coreboot_cfr_free_setting(struct coreboot_cfr_setting *setting)
684 {
685 	unsigned int i;
686 
687 	for (i = 0; i < setting->n_values; i++)
688 		kfree(setting->values[i].label);
689 
690 	kfree(setting->values);
691 	kfree(setting->display_name);
692 	kfree(setting->name);
693 	kfree(setting);
694 }
695 
696 static void coreboot_cfr_setting_release(struct kobject *kobj)
697 {
698 	coreboot_cfr_free_setting(to_coreboot_cfr_setting(kobj));
699 }
700 
701 static const struct kobj_type coreboot_cfr_setting_ktype = {
702 	.release = coreboot_cfr_setting_release,
703 	.sysfs_ops = &kobj_sysfs_ops,
704 };
705 
706 static ssize_t pending_reboot_show(struct kobject *kobj,
707 				   struct kobj_attribute *attr, char *buf)
708 {
709 	struct device *dev = kobj_to_dev(kobj->parent);
710 	struct coreboot_cfr_drvdata *data;
711 
712 	data = dev_get_drvdata(dev);
713 
714 	return sysfs_emit(buf, "%d\n", data->pending_reboot);
715 }
716 
717 static struct kobj_attribute pending_reboot_attr = __ATTR_RO(pending_reboot);
718 
719 static int coreboot_cfr_copy_bool_values(struct coreboot_cfr_setting *setting)
720 {
721 	static const struct coreboot_cfr_enum bool_values[] = {
722 		{ .label = "Disabled", .value = 0 },
723 		{ .label = "Enabled", .value = 1 },
724 	};
725 	unsigned int i;
726 
727 	setting->values = kcalloc(ARRAY_SIZE(bool_values), sizeof(*setting->values),
728 				  GFP_KERNEL);
729 	if (!setting->values)
730 		return -ENOMEM;
731 
732 	for (i = 0; i < ARRAY_SIZE(bool_values); i++) {
733 		setting->values[i].label = kstrdup(bool_values[i].label,
734 						   GFP_KERNEL);
735 		if (!setting->values[i].label)
736 			return -ENOMEM;
737 		setting->values[i].value = bool_values[i].value;
738 		setting->n_values++;
739 	}
740 
741 	return 0;
742 }
743 
744 static int coreboot_cfr_count_enum_values(const void *base, size_t len)
745 {
746 	struct coreboot_cfr_iterator iterator = {
747 		.cursor = base,
748 		.remaining = len,
749 	};
750 	const struct coreboot_table_entry *entry;
751 	int count = 0;
752 
753 	for (;;) {
754 		entry = coreboot_cfr_next_entry(&iterator);
755 		if (IS_ERR(entry))
756 			return PTR_ERR(entry);
757 		if (!entry)
758 			return count;
759 
760 		if (entry->tag == CFR_TAG_ENUM_VALUE)
761 			count++;
762 	}
763 }
764 
765 static int coreboot_cfr_copy_enum_values(struct coreboot_cfr_setting *setting,
766 					 const void *base, size_t len)
767 {
768 	struct coreboot_cfr_iterator iterator = {
769 		.cursor = base,
770 		.remaining = len,
771 	};
772 	const struct lb_cfr_enum_value *enum_value;
773 	const struct lb_cfr_varbinary *label;
774 	const struct coreboot_table_entry *entry;
775 	struct coreboot_cfr_enum *value;
776 	int count;
777 
778 	count = coreboot_cfr_count_enum_values(base, len);
779 	if (count <= 0)
780 		return count ?: -EINVAL;
781 
782 	setting->values = kcalloc(count, sizeof(*setting->values), GFP_KERNEL);
783 	if (!setting->values)
784 		return -ENOMEM;
785 
786 	for (;;) {
787 		entry = coreboot_cfr_next_entry(&iterator);
788 		if (IS_ERR(entry))
789 			return PTR_ERR(entry);
790 		if (!entry)
791 			return 0;
792 
793 		if (entry->tag != CFR_TAG_ENUM_VALUE)
794 			continue;
795 
796 		if (entry->size < sizeof(*enum_value))
797 			return -EINVAL;
798 
799 		enum_value = (const struct lb_cfr_enum_value *)entry;
800 		label = coreboot_cfr_child_string(enum_value + 1,
801 						  enum_value->size - sizeof(*enum_value),
802 						  CFR_TAG_VARCHAR_UI_NAME);
803 		if (IS_ERR(label))
804 			return PTR_ERR(label);
805 		if (!label)
806 			return -EINVAL;
807 
808 		value = &setting->values[setting->n_values];
809 		value->label = coreboot_cfr_string_dup(label);
810 		if (!value->label)
811 			return -ENOMEM;
812 		if (!coreboot_cfr_string_is_valid_label(value->label)) {
813 			kfree(value->label);
814 			value->label = NULL;
815 			return -EINVAL;
816 		}
817 
818 		value->value = enum_value->value;
819 		setting->n_values++;
820 	}
821 }
822 
823 static bool
824 coreboot_cfr_possible_values_fit(const struct coreboot_cfr_setting *setting)
825 {
826 	size_t len = 1;		/* Trailing newline. */
827 	size_t label_len;
828 	unsigned int i;
829 
830 	for (i = 0; i < setting->n_values; i++) {
831 		if (len >= PAGE_SIZE)
832 			return false;
833 
834 		if (i)
835 			len++;
836 
837 		label_len = strlen(setting->values[i].label);
838 		if (label_len >= PAGE_SIZE - len)
839 			return false;
840 
841 		len += label_len;
842 	}
843 
844 	return true;
845 }
846 
847 static int coreboot_cfr_setting_is_usable(struct coreboot_cfr_setting *setting)
848 {
849 	u32 value;
850 	int ret;
851 
852 	ret = coreboot_cfr_read_value(setting, &value, NULL);
853 	if (ret)
854 		return ret;
855 
856 	if (!coreboot_cfr_value_is_valid(setting, value))
857 		return -EINVAL;
858 
859 	return 0;
860 }
861 
862 static int coreboot_cfr_register_setting(struct coreboot_cfr_drvdata *data,
863 					 struct coreboot_cfr_setting *setting)
864 {
865 	int ret;
866 
867 	ret = kobject_init_and_add(&setting->kobj, &coreboot_cfr_setting_ktype,
868 				   &data->attrs_kset->kobj, "%s", setting->name);
869 	if (ret)
870 		goto err_put_kobj;
871 
872 	ret = sysfs_create_group(&setting->kobj, &coreboot_cfr_setting_group);
873 	if (ret)
874 		goto err_put_kobj;
875 
876 	list_add_tail(&setting->node, &data->settings);
877 	return 0;
878 
879 err_put_kobj:
880 	kobject_put(&setting->kobj);
881 	return ret;
882 }
883 
884 static int coreboot_cfr_add_numeric_option(struct coreboot_cfr_drvdata *data,
885 					   const struct lb_cfr_numeric_option *option,
886 					   bool parent_read_only)
887 {
888 	const struct lb_cfr_varbinary *name;
889 	const struct lb_cfr_varbinary *display_name;
890 	const struct lb_cfr_runtime_apply *runtime_apply;
891 	const void *child_base = option + 1;
892 	struct coreboot_cfr_setting *setting;
893 	size_t child_len = option->size - sizeof(*option);
894 	int ret;
895 
896 	if (!(option->flags & CFR_OPTFLAG_RUNTIME))
897 		return 0;
898 
899 	if (option->flags & COREBOOT_CFR_OPT_SKIP_FLAGS)
900 		return 0;
901 
902 	if (option->dependency_id)
903 		return 0;
904 
905 	setting = kzalloc_obj(*setting, GFP_KERNEL);
906 	if (!setting)
907 		return -ENOMEM;
908 
909 	INIT_LIST_HEAD(&setting->node);
910 	setting->drvdata = data;
911 	setting->default_value = option->default_value;
912 	setting->min = option->min;
913 	setting->max = option->max;
914 	setting->step = option->step ?: 1;
915 	setting->read_only =
916 		(option->flags & COREBOOT_CFR_OPT_READ_ONLY_FLAGS) ||
917 		!data->efi_writes_supported || parent_read_only;
918 
919 	runtime_apply = coreboot_cfr_child_runtime_apply(child_base, child_len);
920 	if (IS_ERR(runtime_apply)) {
921 		ret = PTR_ERR(runtime_apply);
922 		goto err_put_setting;
923 	}
924 
925 	if (runtime_apply && runtime_apply->method == CFR_RUNTIME_APPLY_APM_CNT) {
926 		setting->runtime_apply_method = runtime_apply->method;
927 		setting->runtime_apply_id = runtime_apply->id;
928 	}
929 
930 	name = coreboot_cfr_child_string(child_base, child_len,
931 					 CFR_TAG_VARCHAR_OPT_NAME);
932 	if (IS_ERR(name)) {
933 		ret = PTR_ERR(name);
934 		goto err_put_setting;
935 	}
936 	if (!name) {
937 		ret = -EINVAL;
938 		goto err_put_setting;
939 	}
940 
941 	setting->name = coreboot_cfr_string_dup(name);
942 	if (!setting->name) {
943 		ret = -ENOMEM;
944 		goto err_put_setting;
945 	}
946 
947 	if (!coreboot_cfr_string_is_valid_name(setting->name)) {
948 		ret = -EINVAL;
949 		goto err_put_setting;
950 	}
951 
952 	display_name = coreboot_cfr_child_string(child_base, child_len,
953 						 CFR_TAG_VARCHAR_UI_NAME);
954 	if (IS_ERR(display_name)) {
955 		ret = PTR_ERR(display_name);
956 		goto err_put_setting;
957 	}
958 	if (display_name)
959 		setting->display_name = coreboot_cfr_string_dup(display_name);
960 	else
961 		setting->display_name = kstrdup(setting->name, GFP_KERNEL);
962 	if (!setting->display_name) {
963 		ret = -ENOMEM;
964 		goto err_put_setting;
965 	}
966 
967 	switch (option->tag) {
968 	case CFR_TAG_OPTION_BOOL:
969 		setting->type = COREBOOT_CFR_SETTING_BOOL;
970 		setting->min = 0;
971 		setting->max = 1;
972 		setting->step = 1;
973 		ret = coreboot_cfr_copy_bool_values(setting);
974 		break;
975 	case CFR_TAG_OPTION_ENUM:
976 		setting->type = COREBOOT_CFR_SETTING_ENUM;
977 		ret = coreboot_cfr_copy_enum_values(setting, child_base,
978 						    child_len);
979 		break;
980 	case CFR_TAG_OPTION_NUMBER:
981 		setting->type = COREBOOT_CFR_SETTING_NUMBER;
982 		if (setting->max < setting->min)
983 			ret = -EINVAL;
984 		else
985 			ret = 0;
986 		break;
987 	default:
988 		ret = -EINVAL;
989 		break;
990 	}
991 
992 	if (ret)
993 		goto err_put_setting;
994 	/* possible_values must be returned completely in one sysfs read. */
995 	if (setting->type != COREBOOT_CFR_SETTING_NUMBER &&
996 	    !coreboot_cfr_possible_values_fit(setting)) {
997 		ret = 0;
998 		goto err_put_setting;
999 	}
1000 
1001 	ret = coreboot_cfr_setting_is_usable(setting);
1002 	if (ret) {
1003 		/*
1004 		 * CFR may describe options without a matching, readable runtime
1005 		 * EFI variable. Skip those, but propagate transient EFI failures.
1006 		 */
1007 		if (ret == -ENOENT || ret == -EINVAL || ret == -EOPNOTSUPP ||
1008 		    ret == -ENAMETOOLONG)
1009 			ret = 0;
1010 		goto err_put_setting;
1011 	}
1012 
1013 	/* The kobject release callback owns setting after this call. */
1014 	return coreboot_cfr_register_setting(data, setting);
1015 
1016 err_put_setting:
1017 	coreboot_cfr_free_setting(setting);
1018 	return ret;
1019 }
1020 
1021 static int coreboot_cfr_parse_records(struct coreboot_cfr_drvdata *data,
1022 				      const void *base, size_t len,
1023 				      unsigned int depth,
1024 				      bool parent_read_only)
1025 {
1026 	struct coreboot_cfr_iterator iterator = {
1027 		.cursor = base,
1028 		.remaining = len,
1029 	};
1030 	const struct lb_cfr_option_form *form;
1031 	const struct lb_cfr_numeric_option *option;
1032 	const struct coreboot_table_entry *entry;
1033 	const void *child_base;
1034 	size_t child_len;
1035 	int ret;
1036 
1037 	for (;;) {
1038 		entry = coreboot_cfr_next_entry(&iterator);
1039 		if (IS_ERR(entry))
1040 			return PTR_ERR(entry);
1041 		if (!entry)
1042 			return 0;
1043 
1044 		switch (entry->tag) {
1045 		case CFR_TAG_OPTION_FORM:
1046 			if (entry->size < sizeof(struct lb_cfr_option_form))
1047 				return -EINVAL;
1048 
1049 			form = (const struct lb_cfr_option_form *)entry;
1050 			if (form->dependency_id ||
1051 			    form->flags & CFR_OPTFLAG_SUPPRESS)
1052 				break;
1053 
1054 			if (depth >= COREBOOT_CFR_MAX_FORM_DEPTH)
1055 				return -E2BIG;
1056 
1057 			child_base = form + 1;
1058 			child_len = entry->size - sizeof(struct lb_cfr_option_form);
1059 			ret = coreboot_cfr_parse_records(data, child_base,
1060 							 child_len, depth + 1,
1061 							 parent_read_only ||
1062 							 (form->flags &
1063 							  COREBOOT_CFR_OPT_READ_ONLY_FLAGS));
1064 			if (ret)
1065 				return ret;
1066 			break;
1067 		case CFR_TAG_OPTION_ENUM:
1068 		case CFR_TAG_OPTION_NUMBER:
1069 		case CFR_TAG_OPTION_BOOL:
1070 			option = (const struct lb_cfr_numeric_option *)entry;
1071 			if (entry->size < sizeof(*option))
1072 				return -EINVAL;
1073 			ret = coreboot_cfr_add_numeric_option(data, option,
1074 							      parent_read_only);
1075 			if (ret)
1076 				return ret;
1077 			break;
1078 		default:
1079 			/* Ignore unsupported, child-only and future record types. */
1080 			break;
1081 		}
1082 	}
1083 }
1084 
1085 static void coreboot_cfr_unregister_settings(struct coreboot_cfr_drvdata *data)
1086 {
1087 	struct coreboot_cfr_setting *setting, *tmp;
1088 
1089 	list_for_each_entry_safe(setting, tmp, &data->settings, node) {
1090 		sysfs_remove_group(&setting->kobj, &coreboot_cfr_setting_group);
1091 		list_del(&setting->node);
1092 		kobject_put(&setting->kobj);
1093 	}
1094 }
1095 
1096 static int coreboot_cfr_probe(struct coreboot_device *dev)
1097 {
1098 	const struct lb_cfr *root = (const struct lb_cfr *)dev->raw;
1099 	struct coreboot_cfr_drvdata *data;
1100 	size_t payload_len;
1101 	int ret;
1102 
1103 	if (dev->entry.size < sizeof(*root))
1104 		return -EINVAL;
1105 
1106 	if (root->tag != LB_TAG_CFR_ROOT || root->version != CFR_VERSION)
1107 		return -EINVAL;
1108 
1109 	if (root->size < sizeof(*root) || root->size > dev->entry.size)
1110 		return -EINVAL;
1111 
1112 	payload_len = root->size - sizeof(*root);
1113 	if (crc32_be(0, root + 1, payload_len) != root->checksum)
1114 		return -EBADMSG;
1115 
1116 	if (!efivar_is_available())
1117 		return -EPROBE_DEFER;
1118 
1119 	data = devm_kzalloc(&dev->dev, sizeof(*data), GFP_KERNEL);
1120 	if (!data)
1121 		return -ENOMEM;
1122 
1123 	ret = efivar_lock();
1124 	if (ret)
1125 		return ret;
1126 	data->efi_writes_supported = efivar_supports_writes();
1127 	efivar_unlock();
1128 
1129 	INIT_LIST_HEAD(&data->settings);
1130 	ret = devm_mutex_init(&dev->dev, &data->lock);
1131 	if (ret)
1132 		return ret;
1133 
1134 	dev_set_drvdata(&dev->dev, data);
1135 
1136 	data->class_dev = device_create(&firmware_attributes_class, NULL,
1137 					MKDEV(0, 0), NULL, DRIVER_NAME);
1138 	if (IS_ERR(data->class_dev))
1139 		return PTR_ERR(data->class_dev);
1140 	dev_set_drvdata(data->class_dev, data);
1141 
1142 	data->attrs_kset = kset_create_and_add("attributes", NULL,
1143 					       &data->class_dev->kobj);
1144 	if (!data->attrs_kset) {
1145 		ret = -ENOMEM;
1146 		goto err_unregister_dev;
1147 	}
1148 
1149 	ret = sysfs_create_file(&data->attrs_kset->kobj,
1150 				&pending_reboot_attr.attr);
1151 	if (ret)
1152 		goto err_unregister_attrs;
1153 
1154 	ret = coreboot_cfr_parse_records(data, root + 1, payload_len, 0, false);
1155 	if (ret)
1156 		goto err_unregister_settings;
1157 
1158 	if (list_empty(&data->settings)) {
1159 		ret = -ENODEV;
1160 		goto err_unregister_settings;
1161 	}
1162 
1163 	return 0;
1164 
1165 err_unregister_settings:
1166 	coreboot_cfr_unregister_settings(data);
1167 	sysfs_remove_file(&data->attrs_kset->kobj, &pending_reboot_attr.attr);
1168 err_unregister_attrs:
1169 	kset_unregister(data->attrs_kset);
1170 err_unregister_dev:
1171 	device_unregister(data->class_dev);
1172 	return ret;
1173 }
1174 
1175 static void coreboot_cfr_remove(struct coreboot_device *dev)
1176 {
1177 	struct coreboot_cfr_drvdata *data = dev_get_drvdata(&dev->dev);
1178 
1179 	coreboot_cfr_unregister_settings(data);
1180 	sysfs_remove_file(&data->attrs_kset->kobj, &pending_reboot_attr.attr);
1181 	kset_unregister(data->attrs_kset);
1182 	device_unregister(data->class_dev);
1183 }
1184 
1185 static const struct coreboot_device_id coreboot_cfr_ids[] = {
1186 	{ .tag = LB_TAG_CFR_ROOT },
1187 	{ }
1188 };
1189 MODULE_DEVICE_TABLE(coreboot, coreboot_cfr_ids);
1190 
1191 static struct coreboot_driver coreboot_cfr_driver = {
1192 	.probe = coreboot_cfr_probe,
1193 	.remove = coreboot_cfr_remove,
1194 	.drv = {
1195 		.name = DRIVER_NAME,
1196 	},
1197 	.id_table = coreboot_cfr_ids,
1198 };
1199 module_coreboot_driver(coreboot_cfr_driver);
1200 
1201 MODULE_AUTHOR("Sean Rhodes <sean@starlabs.systems>");
1202 MODULE_DESCRIPTION("coreboot CFR firmware attributes driver");
1203 MODULE_LICENSE("GPL");
1204 MODULE_IMPORT_NS("EFIVAR");
1205