diff options
| author | Matt Fleming <matt.fleming@intel.com> | 2013-02-08 11:27:24 -0500 |
|---|---|---|
| committer | Matt Fleming <matt.fleming@intel.com> | 2013-04-17 08:25:09 -0400 |
| commit | d68772b7c83f4b518be15ae96f4827c8ed02f684 (patch) | |
| tree | b3408a750976edf6e0b62bfce3e26d1c9685a907 | |
| parent | 048517722cde2595a7366d0c3c72b8b1ec142a9c (diff) | |
efivarfs: Move to fs/efivarfs
Now that efivarfs uses the efivar API, move it out of efivars.c and
into fs/efivarfs where it belongs. This move will eventually allow us
to enable the efivarfs code without having to also enable
CONFIG_EFI_VARS built, and vice versa.
Furthermore, things like,
mount -t efivarfs none /sys/firmware/efi/efivars
will now work if efivarfs is built as a module without requiring the
use of MODULE_ALIAS(), which would have been necessary when the
efivarfs code was part of efivars.c.
Cc: Matthew Garrett <matthew.garrett@nebula.com>
Cc: Jeremy Kerr <jk@ozlabs.org>
Reviewed-by: Tom Gundersen <teg@jklm.no>
Tested-by: Tom Gundersen <teg@jklm.no>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
| -rw-r--r-- | MAINTAINERS | 9 | ||||
| -rw-r--r-- | drivers/firmware/efivars.c | 496 | ||||
| -rw-r--r-- | fs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/Makefile | 1 | ||||
| -rw-r--r-- | fs/efivarfs/Kconfig | 12 | ||||
| -rw-r--r-- | fs/efivarfs/Makefile | 7 | ||||
| -rw-r--r-- | fs/efivarfs/file.c | 111 | ||||
| -rw-r--r-- | fs/efivarfs/inode.c | 173 | ||||
| -rw-r--r-- | fs/efivarfs/internal.h | 22 | ||||
| -rw-r--r-- | fs/efivarfs/super.c | 267 |
10 files changed, 603 insertions, 496 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9e4862bf9961..0855f4450e91 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2990,6 +2990,15 @@ F: arch/x86/platform/efi/* | |||
| 2990 | F: drivers/firmware/efivars.c | 2990 | F: drivers/firmware/efivars.c |
| 2991 | F: include/linux/efi*.h | 2991 | F: include/linux/efi*.h |
| 2992 | 2992 | ||
| 2993 | EFI VARIABLE FILESYSTEM | ||
| 2994 | M: Matthew Garrett <matthew.garrett@nebula.com> | ||
| 2995 | M: Jeremy Kerr <jk@ozlabs.org> | ||
| 2996 | M: Matt Fleming <matt.fleming@intel.com> | ||
| 2997 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git | ||
| 2998 | L: linux-efi@vger.kernel.org | ||
| 2999 | S: Maintained | ||
| 3000 | F: fs/efivarfs/ | ||
| 3001 | |||
| 2993 | EFIFB FRAMEBUFFER DRIVER | 3002 | EFIFB FRAMEBUFFER DRIVER |
| 2994 | L: linux-fbdev@vger.kernel.org | 3003 | L: linux-fbdev@vger.kernel.org |
| 2995 | M: Peter Jones <pjones@redhat.com> | 3004 | M: Peter Jones <pjones@redhat.com> |
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 5e7c3b1acde9..af396758482f 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
| @@ -94,7 +94,6 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables"); | |||
| 94 | MODULE_LICENSE("GPL"); | 94 | MODULE_LICENSE("GPL"); |
| 95 | MODULE_VERSION(EFIVARS_VERSION); | 95 | MODULE_VERSION(EFIVARS_VERSION); |
| 96 | 96 | ||
| 97 | static LIST_HEAD(efivarfs_list); | ||
| 98 | LIST_HEAD(efivar_sysfs_list); | 97 | LIST_HEAD(efivar_sysfs_list); |
| 99 | EXPORT_SYMBOL_GPL(efivar_sysfs_list); | 98 | EXPORT_SYMBOL_GPL(efivar_sysfs_list); |
| 100 | 99 | ||
| @@ -558,12 +557,6 @@ static struct kobj_type efivar_ktype = { | |||
| 558 | .default_attrs = def_attrs, | 557 | .default_attrs = def_attrs, |
| 559 | }; | 558 | }; |
| 560 | 559 | ||
| 561 | static int efivarfs_file_open(struct inode *inode, struct file *file) | ||
| 562 | { | ||
| 563 | file->private_data = inode->i_private; | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | static int efi_status_to_err(efi_status_t status) | 560 | static int efi_status_to_err(efi_status_t status) |
| 568 | { | 561 | { |
| 569 | int err; | 562 | int err; |
| @@ -597,493 +590,6 @@ static int efi_status_to_err(efi_status_t status) | |||
| 597 | return err; | 590 | return err; |
| 598 | } | 591 | } |
| 599 | 592 | ||
| 600 | static ssize_t efivarfs_file_write(struct file *file, | ||
| 601 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
| 602 | { | ||
| 603 | struct efivar_entry *var = file->private_data; | ||
| 604 | void *data; | ||
| 605 | u32 attributes; | ||
| 606 | struct inode *inode = file->f_mapping->host; | ||
| 607 | unsigned long datasize = count - sizeof(attributes); | ||
| 608 | ssize_t bytes = 0; | ||
| 609 | bool set = false; | ||
| 610 | |||
| 611 | if (count < sizeof(attributes)) | ||
| 612 | return -EINVAL; | ||
| 613 | |||
| 614 | if (copy_from_user(&attributes, userbuf, sizeof(attributes))) | ||
| 615 | return -EFAULT; | ||
| 616 | |||
| 617 | if (attributes & ~(EFI_VARIABLE_MASK)) | ||
| 618 | return -EINVAL; | ||
| 619 | |||
| 620 | data = kmalloc(datasize, GFP_KERNEL); | ||
| 621 | if (!data) | ||
| 622 | return -ENOMEM; | ||
| 623 | |||
| 624 | if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { | ||
| 625 | bytes = -EFAULT; | ||
| 626 | goto out; | ||
| 627 | } | ||
| 628 | |||
| 629 | bytes = efivar_entry_set_get_size(var, attributes, &datasize, | ||
| 630 | data, &set); | ||
| 631 | if (!set && bytes) | ||
| 632 | goto out; | ||
| 633 | |||
| 634 | if (!bytes) { | ||
| 635 | mutex_lock(&inode->i_mutex); | ||
| 636 | i_size_write(inode, datasize + sizeof(attributes)); | ||
| 637 | mutex_unlock(&inode->i_mutex); | ||
| 638 | } else if (bytes == -ENOENT) { | ||
| 639 | drop_nlink(inode); | ||
| 640 | d_delete(file->f_dentry); | ||
| 641 | dput(file->f_dentry); | ||
| 642 | } else | ||
| 643 | pr_warn("efivarfs: inconsistent EFI variable implementation? " | ||
| 644 | "status=%zu\n", bytes); | ||
| 645 | |||
| 646 | bytes = count; | ||
| 647 | |||
| 648 | out: | ||
| 649 | kfree(data); | ||
| 650 | |||
| 651 | return bytes; | ||
| 652 | } | ||
| 653 | |||
| 654 | static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, | ||
| 655 | size_t count, loff_t *ppos) | ||
| 656 | { | ||
| 657 | struct efivar_entry *var = file->private_data; | ||
| 658 | unsigned long datasize = 0; | ||
| 659 | u32 attributes; | ||
| 660 | void *data; | ||
| 661 | ssize_t size = 0; | ||
| 662 | int err; | ||
| 663 | |||
| 664 | err = efivar_entry_size(var, &datasize); | ||
| 665 | if (err) | ||
| 666 | return err; | ||
| 667 | |||
| 668 | data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); | ||
| 669 | |||
| 670 | if (!data) | ||
| 671 | return -ENOMEM; | ||
| 672 | |||
| 673 | size = efivar_entry_get(var, &attributes, &datasize, | ||
| 674 | data + sizeof(attributes)); | ||
| 675 | if (size) | ||
| 676 | goto out_free; | ||
| 677 | |||
| 678 | memcpy(data, &attributes, sizeof(attributes)); | ||
| 679 | size = simple_read_from_buffer(userbuf, count, ppos, | ||
| 680 | data, datasize + sizeof(attributes)); | ||
| 681 | out_free: | ||
| 682 | kfree(data); | ||
| 683 | |||
| 684 | return size; | ||
| 685 | } | ||
| 686 | |||
| 687 | static void efivarfs_evict_inode(struct inode *inode) | ||
| 688 | { | ||
| 689 | clear_inode(inode); | ||
| 690 | } | ||
| 691 | |||
| 692 | static const struct super_operations efivarfs_ops = { | ||
| 693 | .statfs = simple_statfs, | ||
| 694 | .drop_inode = generic_delete_inode, | ||
| 695 | .evict_inode = efivarfs_evict_inode, | ||
| 696 | .show_options = generic_show_options, | ||
| 697 | }; | ||
| 698 | |||
| 699 | static struct super_block *efivarfs_sb; | ||
| 700 | |||
| 701 | static const struct inode_operations efivarfs_dir_inode_operations; | ||
| 702 | |||
| 703 | static const struct file_operations efivarfs_file_operations = { | ||
| 704 | .open = efivarfs_file_open, | ||
| 705 | .read = efivarfs_file_read, | ||
| 706 | .write = efivarfs_file_write, | ||
| 707 | .llseek = no_llseek, | ||
| 708 | }; | ||
| 709 | |||
| 710 | static struct inode *efivarfs_get_inode(struct super_block *sb, | ||
| 711 | const struct inode *dir, int mode, dev_t dev) | ||
| 712 | { | ||
| 713 | struct inode *inode = new_inode(sb); | ||
| 714 | |||
| 715 | if (inode) { | ||
| 716 | inode->i_ino = get_next_ino(); | ||
| 717 | inode->i_mode = mode; | ||
| 718 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 719 | switch (mode & S_IFMT) { | ||
| 720 | case S_IFREG: | ||
| 721 | inode->i_fop = &efivarfs_file_operations; | ||
| 722 | break; | ||
| 723 | case S_IFDIR: | ||
| 724 | inode->i_op = &efivarfs_dir_inode_operations; | ||
| 725 | inode->i_fop = &simple_dir_operations; | ||
| 726 | inc_nlink(inode); | ||
| 727 | break; | ||
| 728 | } | ||
| 729 | } | ||
| 730 | return inode; | ||
| 731 | } | ||
| 732 | |||
| 733 | /* | ||
