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 ¤t_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 == ¤t_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