Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi: vars: Switch to new wrapper layer

Switch the caching linked-list efivars layer implementation to the newly
introduced efivar get/set variable wrappers, instead of accessing the
lock and the ops pointer directly. This will permit us to move this code
out of the public efivars API, and into efivarfs once the obsolete sysfs
access method is finally removed.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

+52 -81
+52 -81
drivers/firmware/efi/vars.c
··· 408 408 int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *), 409 409 void *data, bool duplicates, struct list_head *head) 410 410 { 411 - const struct efivar_operations *ops; 412 411 unsigned long variable_name_size = 1024; 413 412 efi_char16_t *variable_name; 414 413 efi_status_t status; 415 414 efi_guid_t vendor_guid; 416 415 int err = 0; 417 - 418 - if (!__efivars) 419 - return -EFAULT; 420 - 421 - ops = __efivars->ops; 422 416 423 417 variable_name = kzalloc(variable_name_size, GFP_KERNEL); 424 418 if (!variable_name) { ··· 420 426 return -ENOMEM; 421 427 } 422 428 423 - if (down_interruptible(&efivars_lock)) { 424 - err = -EINTR; 429 + err = efivar_lock(); 430 + if (err) 425 431 goto free; 426 - } 427 432 428 433 /* 429 434 * Per EFI spec, the maximum storage allocated for both ··· 432 439 do { 433 440 variable_name_size = 1024; 434 441 435 - status = ops->get_next_variable(&variable_name_size, 436 - variable_name, 437 - &vendor_guid); 442 + status = efivar_get_next_variable(&variable_name_size, 443 + variable_name, 444 + &vendor_guid); 438 445 switch (status) { 439 446 case EFI_SUCCESS: 440 447 variable_name_size = var_name_strnsize(variable_name, ··· 476 483 477 484 } while (status != EFI_NOT_FOUND); 478 485 479 - up(&efivars_lock); 486 + efivar_unlock(); 480 487 free: 481 488 kfree(variable_name); 482 489 ··· 493 500 */ 494 501 int efivar_entry_add(struct efivar_entry *entry, struct list_head *head) 495 502 { 496 - if (down_interruptible(&efivars_lock)) 497 - return -EINTR; 503 + int err; 504 + 505 + err = efivar_lock(); 506 + if (err) 507 + return err; 498 508 list_add(&entry->list, head); 499 - up(&efivars_lock); 509 + efivar_unlock(); 500 510 501 511 return 0; 502 512 } ··· 540 544 static void efivar_entry_list_del_unlock(struct efivar_entry *entry) 541 545 { 542 546 list_del(&entry->list); 543 - up(&efivars_lock); 547 + efivar_unlock(); 544 548 } 545 549 546 550 /** ··· 556 560 */ 557 561 int efivar_entry_delete(struct efivar_entry *entry) 558 562 { 559 - const struct efivar_operations *ops; 560 563 efi_status_t status; 564 + int err; 561 565 562 - if (down_interruptible(&efivars_lock)) 563 - return -EINTR; 566 + err = efivar_lock(); 567 + if (err) 568 + return err; 564 569 565 - if (!__efivars) { 566 - up(&efivars_lock); 567 - return -EINVAL; 568 - } 569 - ops = __efivars->ops; 570 - status = ops->set_variable(entry->var.VariableName, 571 - &entry->var.VendorGuid, 572 - 0, 0, NULL); 570 + status = efivar_set_variable_locked(entry->var.VariableName, 571 + &entry->var.VendorGuid, 572 + 0, 0, NULL, false); 573 573 if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND)) { 574 - up(&efivars_lock); 574 + efivar_unlock(); 575 575 return efi_status_to_err(status); 576 576 } 577 577 ··· 583 591 */ 584 592 int efivar_entry_size(struct efivar_entry *entry, unsigned long *size) 585 593 { 586 - const struct efivar_operations *ops; 587 594 efi_status_t status; 595 + int err; 588 596 589 597 *size = 0; 590 598 591 - if (down_interruptible(&efivars_lock)) 592 - return -EINTR; 593 - if (!__efivars) { 594 - up(&efivars_lock); 595 - return -EINVAL; 596 - } 597 - ops = __efivars->ops; 598 - status = ops->get_variable(entry->var.VariableName, 599 - &entry->var.VendorGuid, NULL, size, NULL); 600 - up(&efivars_lock); 599 + err = efivar_lock(); 600 + if (err) 601 + return err; 602 + 603 + status = efivar_get_variable(entry->var.VariableName, 604 + &entry->var.VendorGuid, NULL, size, NULL); 605 + efivar_unlock(); 601 606 602 607 if (status != EFI_BUFFER_TOO_SMALL) 603 608 return efi_status_to_err(status); ··· 610 621 * @size: size of @data buffer 611 622 * @data: buffer to store variable data 612 623 * 613 - * The caller MUST call efivar_entry_iter_begin() and 614 - * efivar_entry_iter_end() before and after the invocation of this 615 - * function, respectively. 624 + * The caller MUST hold the efivar lock when calling this function. 616 625 */ 617 626 int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes, 618 627 unsigned long *size, void *data) 619 628 { 620 629 efi_status_t status; 621 630 622 - if (!__efivars) 623 - return -EINVAL; 624 - 625 - status = __efivars->ops->get_variable(entry->var.VariableName, 626 - &entry->var.VendorGuid, 627 - attributes, size, data); 631 + status = efivar_get_variable(entry->var.VariableName, 632 + &entry->var.VendorGuid, 633 + attributes, size, data); 628 634 629 635 return efi_status_to_err(status); 630 636 } ··· 635 651 int efivar_entry_get(struct efivar_entry *entry, u32 *attributes, 636 652 unsigned long *size, void *data) 637 653 { 638 - efi_status_t status; 654 + int err; 639 655 640 - if (down_interruptible(&efivars_lock)) 641 - return -EINTR; 656 + err = efivar_lock(); 657 + if (err) 658 + return err; 659 + err = __efivar_entry_get(entry, attributes, size, data); 660 + efivar_unlock(); 642 661 643 - if (!__efivars) { 644 - up(&efivars_lock); 645 - return -EINVAL; 646 - } 647 - 648 - status = __efivars->ops->get_variable(entry->var.VariableName, 649 - &entry->var.VendorGuid, 650 - attributes, size, data); 651 - up(&efivars_lock); 652 - 653 - return efi_status_to_err(status); 662 + return err; 654 663 } 655 664 EXPORT_SYMBOL_GPL(efivar_entry_get); 656 665 ··· 672 695 int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes, 673 696 unsigned long *size, void *data, bool *set) 674 697 { 675 - const struct efivar_operations *ops; 676 698 efi_char16_t *name = entry->var.VariableName; 677 699 efi_guid_t *vendor = &entry->var.VendorGuid; 678 700 efi_status_t status; ··· 687 711 * set_variable call, and removal of the variable from the efivars 688 712 * list (in the case of an authenticated delete). 689 713 */ 690 - if (down_interruptible(&efivars_lock)) 691 - return -EINTR; 692 - 693 - if (!__efivars) { 694 - err = -EINVAL; 695 - goto out; 696 - } 714 + err = efivar_lock(); 715 + if (err) 716 + return err; 697 717 698 718 /* 699 719 * Ensure that the available space hasn't shrunk below the safe level ··· 707 735 } 708 736 } 709 737 710 - ops = __efivars->ops; 711 - 712 - status = ops->set_variable(name, vendor, attributes, *size, data); 738 + status = efivar_set_variable_locked(name, vendor, attributes, *size, 739 + data, false); 713 740 if (status != EFI_SUCCESS) { 714 741 err = efi_status_to_err(status); 715 742 goto out; ··· 723 752 * happened. 724 753 */ 725 754 *size = 0; 726 - status = ops->get_variable(entry->var.VariableName, 727 - &entry->var.VendorGuid, 728 - NULL, size, NULL); 755 + status = efivar_get_variable(entry->var.VariableName, 756 + &entry->var.VendorGuid, 757 + NULL, size, NULL); 729 758 730 759 if (status == EFI_NOT_FOUND) 731 760 efivar_entry_list_del_unlock(entry); 732 761 else 733 - up(&efivars_lock); 762 + efivar_unlock(); 734 763 735 764 if (status && status != EFI_BUFFER_TOO_SMALL) 736 765 return efi_status_to_err(status); ··· 738 767 return 0; 739 768 740 769 out: 741 - up(&efivars_lock); 770 + efivar_unlock(); 742 771 return err; 743 772 744 773 } ··· 764 793 struct efivar_entry *entry, *n; 765 794 int err = 0; 766 795 767 - err = down_interruptible(&efivars_lock); 796 + err = efivar_lock(); 768 797 if (err) 769 798 return err; 770 799 ··· 773 802 if (err) 774 803 break; 775 804 } 776 - up(&efivars_lock); 805 + efivar_unlock(); 777 806 778 807 return err; 779 808 }