diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efivars.c | 512 |
1 files changed, 504 insertions, 8 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 6e51c1e81f14..52c5d8956d7d 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -80,6 +80,10 @@ | |||
80 | #include <linux/slab.h> | 80 | #include <linux/slab.h> |
81 | #include <linux/pstore.h> | 81 | #include <linux/pstore.h> |
82 | 82 | ||
83 | #include <linux/fs.h> | ||
84 | #include <linux/ramfs.h> | ||
85 | #include <linux/pagemap.h> | ||
86 | |||
83 | #include <asm/uaccess.h> | 87 | #include <asm/uaccess.h> |
84 | 88 | ||
85 | #define EFIVARS_VERSION "0.08" | 89 | #define EFIVARS_VERSION "0.08" |
@@ -93,6 +97,12 @@ MODULE_VERSION(EFIVARS_VERSION); | |||
93 | #define DUMP_NAME_LEN 52 | 97 | #define DUMP_NAME_LEN 52 |
94 | 98 | ||
95 | /* | 99 | /* |
100 | * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) | ||
101 | * not including trailing NUL | ||
102 | */ | ||
103 | #define GUID_LEN 36 | ||
104 | |||
105 | /* | ||
96 | * The maximum size of VariableName + Data = 1024 | 106 | * The maximum size of VariableName + Data = 1024 |
97 | * Therefore, it's reasonable to save that much | 107 | * Therefore, it's reasonable to save that much |
98 | * space in each part of the structure, | 108 | * space in each part of the structure, |
@@ -108,7 +118,6 @@ struct efi_variable { | |||
108 | __u32 Attributes; | 118 | __u32 Attributes; |
109 | } __attribute__((packed)); | 119 | } __attribute__((packed)); |
110 | 120 | ||
111 | |||
112 | struct efivar_entry { | 121 | struct efivar_entry { |
113 | struct efivars *efivars; | 122 | struct efivars *efivars; |
114 | struct efi_variable var; | 123 | struct efi_variable var; |
@@ -122,6 +131,9 @@ struct efivar_attribute { | |||
122 | ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); | 131 | ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); |
123 | }; | 132 | }; |
124 | 133 | ||
134 | static struct efivars __efivars; | ||
135 | static struct efivar_operations ops; | ||
136 | |||
125 | #define PSTORE_EFI_ATTRIBUTES \ | 137 | #define PSTORE_EFI_ATTRIBUTES \ |
126 | (EFI_VARIABLE_NON_VOLATILE | \ | 138 | (EFI_VARIABLE_NON_VOLATILE | \ |
127 | EFI_VARIABLE_BOOTSERVICE_ACCESS | \ | 139 | EFI_VARIABLE_BOOTSERVICE_ACCESS | \ |
@@ -629,14 +641,482 @@ static struct kobj_type efivar_ktype = { | |||
629 | .default_attrs = def_attrs, | 641 | .default_attrs = def_attrs, |
630 | }; | 642 | }; |
631 | 643 | ||
632 | static struct pstore_info efi_pstore_info; | ||
633 | |||
634 | static inline void | 644 | static inline void |
635 | efivar_unregister(struct efivar_entry *var) | 645 | efivar_unregister(struct efivar_entry *var) |
636 | { | 646 | { |
637 | kobject_put(&var->kobj); | 647 | kobject_put(&var->kobj); |
638 | } | 648 | } |
639 | 649 | ||
650 | static int efivarfs_file_open(struct inode *inode, struct file *file) | ||
651 | { | ||
652 | file->private_data = inode->i_private; | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static int efi_status_to_err(efi_status_t status) | ||
657 | { | ||
658 | int err; | ||
659 | |||
660 | switch (status) { | ||
661 | case EFI_INVALID_PARAMETER: | ||
662 | err = -EINVAL; | ||
663 | break; | ||
664 | case EFI_OUT_OF_RESOURCES: | ||
665 | err = -ENOSPC; | ||
666 | break; | ||
667 | case EFI_DEVICE_ERROR: | ||
668 | err = -EIO; | ||
669 | break; | ||
670 | case EFI_WRITE_PROTECTED: | ||
671 | err = -EROFS; | ||
672 | break; | ||
673 | case EFI_SECURITY_VIOLATION: | ||
674 | err = -EACCES; | ||
675 | break; | ||
676 | case EFI_NOT_FOUND: | ||
677 | err = -ENOENT; | ||
678 | break; | ||
679 | default: | ||
680 | err = -EINVAL; | ||
681 | } | ||
682 | |||
683 | return err; | ||
684 | } | ||
685 | |||
686 | static ssize_t efivarfs_file_write(struct file *file, | ||
687 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
688 | { | ||
689 | struct efivar_entry *var = file->private_data; | ||
690 | struct efivars *efivars; | ||
691 | efi_status_t status; | ||
692 | void *data; | ||
693 | u32 attributes; | ||
694 | struct inode *inode = file->f_mapping->host; | ||
695 | unsigned long datasize = count - sizeof(attributes); | ||
696 | unsigned long newdatasize; | ||
697 | u64 storage_size, remaining_size, max_size; | ||
698 | ssize_t bytes = 0; | ||
699 | |||
700 | if (count < sizeof(attributes)) | ||
701 | return -EINVAL; | ||
702 | |||
703 | if (copy_from_user(&attributes, userbuf, sizeof(attributes))) | ||
704 | return -EFAULT; | ||
705 | |||
706 | if (attributes & ~(EFI_VARIABLE_MASK)) | ||
707 | return -EINVAL; | ||
708 | |||
709 | efivars = var->efivars; | ||
710 | |||
711 | /* | ||
712 | * Ensure that the user can't allocate arbitrarily large | ||
713 | * amounts of memory. Pick a default size of 64K if | ||
714 | * QueryVariableInfo() isn't supported by the firmware. | ||
715 | */ | ||
716 | spin_lock(&efivars->lock); | ||
717 | |||
718 | if (!efivars->ops->query_variable_info) | ||
719 | status = EFI_UNSUPPORTED; | ||
720 | else { | ||
721 | const struct efivar_operations *fops = efivars->ops; | ||
722 | status = fops->query_variable_info(attributes, &storage_size, | ||
723 | &remaining_size, &max_size); | ||
724 | } | ||
725 | |||
726 | spin_unlock(&efivars->lock); | ||
727 | |||
728 | if (status != EFI_SUCCESS) { | ||
729 | if (status != EFI_UNSUPPORTED) | ||
730 | return efi_status_to_err(status); | ||
731 | |||
732 | remaining_size = 65536; | ||
733 | } | ||
734 | |||
735 | if (datasize > remaining_size) | ||
736 | return -ENOSPC; | ||
737 | |||
738 | data = kmalloc(datasize, GFP_KERNEL); | ||
739 | if (!data) | ||
740 | return -ENOMEM; | ||
741 | |||
742 | if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { | ||
743 | bytes = -EFAULT; | ||
744 | goto out; | ||
745 | } | ||
746 | |||
747 | if (validate_var(&var->var, data, datasize) == false) { | ||
748 | bytes = -EINVAL; | ||
749 | goto out; | ||
750 | } | ||
751 | |||
752 | /* | ||
753 | * The lock here protects the get_variable call, the conditional | ||
754 | * set_variable call, and removal of the variable from the efivars | ||
755 | * list (in the case of an authenticated delete). | ||
756 | */ | ||
757 | spin_lock(&efivars->lock); | ||
758 | |||
759 | status = efivars->ops->set_variable(var->var.VariableName, | ||
760 | &var->var.VendorGuid, | ||
761 | attributes, datasize, | ||
762 | data); | ||
763 | |||
764 | if (status != EFI_SUCCESS) { | ||
765 | spin_unlock(&efivars->lock); | ||
766 | kfree(data); | ||
767 | |||
768 | return efi_status_to_err(status); | ||
769 | } | ||
770 | |||
771 | bytes = count; | ||
772 | |||
773 | /* | ||
774 | * Writing to the variable may have caused a change in size (which | ||
775 | * could either be an append or an overwrite), or the variable to be | ||
776 | * deleted. Perform a GetVariable() so we can tell what actually | ||
777 | * happened. | ||
778 | */ | ||
779 | newdatasize = 0; | ||
780 | status = efivars->ops->get_variable(var->var.VariableName, | ||
781 | &var->var.VendorGuid, | ||
782 | NULL, &newdatasize, | ||
783 | NULL); | ||
784 | |||
785 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
786 | spin_unlock(&efivars->lock); | ||
787 | mutex_lock(&inode->i_mutex); | ||
788 | i_size_write(inode, newdatasize + sizeof(attributes)); | ||
789 | mutex_unlock(&inode->i_mutex); | ||
790 | |||
791 | } else if (status == EFI_NOT_FOUND) { | ||
792 | list_del(&var->list); | ||
793 | spin_unlock(&efivars->lock); | ||
794 | efivar_unregister(var); | ||
795 | drop_nlink(inode); | ||
796 | dput(file->f_dentry); | ||
797 | |||
798 | } else { | ||
799 | spin_unlock(&efivars->lock); | ||
800 | pr_warn("efivarfs: inconsistent EFI variable implementation? " | ||
801 | "status = %lx\n", status); | ||
802 | } | ||
803 | |||
804 | out: | ||
805 | kfree(data); | ||
806 | |||
807 | return bytes; | ||
808 | } | ||
809 | |||
810 | static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, | ||
811 | size_t count, loff_t *ppos) | ||
812 | { | ||
813 | struct efivar_entry *var = file->private_data; | ||
814 | struct efivars *efivars = var->efivars; | ||
815 | efi_status_t status; | ||
816 | unsigned long datasize = 0; | ||
817 | u32 attributes; | ||
818 | void *data; | ||
819 | ssize_t size = 0; | ||
820 | |||
821 | spin_lock(&efivars->lock); | ||
822 | status = efivars->ops->get_variable(var->var.VariableName, | ||
823 | &var->var.VendorGuid, | ||
824 | &attributes, &datasize, NULL); | ||
825 | spin_unlock(&efivars->lock); | ||
826 | |||
827 | if (status != EFI_BUFFER_TOO_SMALL) | ||
828 | return efi_status_to_err(status); | ||
829 | |||
830 | data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); | ||
831 | |||
832 | if (!data) | ||
833 | return -ENOMEM; | ||
834 | |||
835 | spin_lock(&efivars->lock); | ||
836 | status = efivars->ops->get_variable(var->var.VariableName, | ||
837 | &var->var.VendorGuid, | ||
838 | &attributes, &datasize, | ||
839 | (data + sizeof(attributes))); | ||
840 | spin_unlock(&efivars->lock); | ||
841 | |||
842 | if (status != EFI_SUCCESS) { | ||
843 | size = efi_status_to_err(status); | ||
844 | goto out_free; | ||
845 | } | ||
846 | |||
847 | memcpy(data, &attributes, sizeof(attributes)); | ||
848 | size = simple_read_from_buffer(userbuf, count, ppos, | ||
849 | data, datasize + sizeof(attributes)); | ||
850 | out_free: | ||
851 | kfree(data); | ||
852 | |||
853 | return size; | ||
854 | } | ||
855 | |||
856 | static void efivarfs_evict_inode(struct inode *inode) | ||
857 | { | ||
858 | clear_inode(inode); | ||
859 | } | ||
860 | |||
861 | static const struct super_operations efivarfs_ops = { | ||
862 | .statfs = simple_statfs, | ||
863 | .drop_inode = generic_delete_inode, | ||
864 | .evict_inode = efivarfs_evict_inode, | ||
865 | .show_options = generic_show_options, | ||
866 | }; | ||
867 | |||
868 | static struct super_block *efivarfs_sb; | ||
869 | |||
870 | static const struct inode_operations efivarfs_dir_inode_operations; | ||
871 | |||
872 | static const struct file_operations efivarfs_file_operations = { | ||
873 | .open = efivarfs_file_open, | ||
874 | .read = efivarfs_file_read, | ||
875 | .write = efivarfs_file_write, | ||
876 | .llseek = no_llseek, | ||
877 | }; | ||
878 | |||
879 | static struct inode *efivarfs_get_inode(struct super_block *sb, | ||
880 | const struct inode *dir, int mode, dev_t dev) | ||
881 | { | ||
882 | struct inode *inode = new_inode(sb); | ||
883 | |||
884 | if (inode) { | ||
885 | inode->i_ino = get_next_ino(); | ||
886 | inode->i_uid = inode->i_gid = 0; | ||
887 | inode->i_mode = mode; | ||
888 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
889 | switch (mode & S_IFMT) { | ||
890 | case S_IFREG: | ||
891 | inode->i_fop = &efivarfs_file_operations; | ||
892 | break; | ||
893 | case S_IFDIR: | ||
894 | inode->i_op = &efivarfs_dir_inode_operations; | ||
895 | inode->i_fop = &simple_dir_operations; | ||
896 | inc_nlink(inode); | ||
897 | break; | ||
898 | } | ||
899 | } | ||
900 | return inode; | ||
901 | } | ||
902 | |||
903 | static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) | ||
904 | { | ||
905 | guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); | ||
906 | guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]); | ||
907 | guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]); | ||
908 | guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]); | ||
909 | guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]); | ||
910 | guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]); | ||
911 | guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]); | ||
912 | guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]); | ||
913 | guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]); | ||
914 | guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]); | ||
915 | guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]); | ||
916 | guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]); | ||
917 | guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]); | ||
918 | guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]); | ||
919 | guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]); | ||
920 | guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]); | ||
921 | } | ||
922 | |||
923 | static int efivarfs_create(struct inode *dir, struct dentry *dentry, | ||
924 | umode_t mode, bool excl) | ||
925 | { | ||
926 | struct inode *inode; | ||
927 | struct efivars *efivars = &__efivars; | ||
928 | struct efivar_entry *var; | ||
929 | int namelen, i = 0, err = 0; | ||
930 | |||
931 | /* | ||
932 | * We need a GUID, plus at least one letter for the variable name, | ||
933 | * plus the '-' separator | ||
934 | */ | ||
935 | if (dentry->d_name.len < GUID_LEN + 2) | ||
936 | return -EINVAL; | ||
937 | |||
938 | inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); | ||
939 | if (!inode) | ||
940 | return -ENOMEM; | ||
941 | |||
942 | var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); | ||
943 | if (!var) { | ||
944 | err = -ENOMEM; | ||
945 | goto out; | ||
946 | } | ||
947 | |||
948 | /* length of the variable name itself: remove GUID and separator */ | ||
949 | namelen = dentry->d_name.len - GUID_LEN - 1; | ||
950 | |||
951 | efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1, | ||
952 | &var->var.VendorGuid); | ||
953 | |||
954 | for (i = 0; i < namelen; i++) | ||
955 | var->var.VariableName[i] = dentry->d_name.name[i]; | ||
956 | |||
957 | var->var.VariableName[i] = '\0'; | ||
958 | |||
959 | inode->i_private = var; | ||
960 | var->efivars = efivars; | ||
961 | var->kobj.kset = efivars->kset; | ||
962 | |||
963 | err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s", | ||
964 | dentry->d_name.name); | ||
965 | if (err) | ||
966 | goto out; | ||
967 | |||
968 | kobject_uevent(&var->kobj, KOBJ_ADD); | ||
969 | spin_lock(&efivars->lock); | ||
970 | list_add(&var->list, &efivars->list); | ||
971 | spin_unlock(&efivars->lock); | ||
972 | d_instantiate(dentry, inode); | ||
973 | dget(dentry); | ||
974 | out: | ||
975 | if (err) { | ||
976 | kfree(var); | ||
977 | iput(inode); | ||
978 | } | ||
979 | return err; | ||
980 | } | ||
981 | |||
982 | static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) | ||
983 | { | ||
984 | struct efivar_entry *var = dentry->d_inode->i_private; | ||
985 | struct efivars *efivars = var->efivars; | ||
986 | efi_status_t status; | ||
987 | |||
988 | spin_lock(&efivars->lock); | ||
989 | |||
990 | status = efivars->ops->set_variable(var->var.VariableName, | ||
991 | &var->var.VendorGuid, | ||
992 | 0, 0, NULL); | ||
993 | |||
994 | if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) { | ||
995 | list_del(&var->list); | ||
996 | spin_unlock(&efivars->lock); | ||
997 | efivar_unregister(var); | ||
998 | drop_nlink(dir); | ||
999 | dput(dentry); | ||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | spin_unlock(&efivars->lock); | ||
1004 | return -EINVAL; | ||
1005 | }; | ||
1006 | |||
1007 | static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | ||
1008 | { | ||
1009 | struct inode *inode = NULL; | ||
1010 | struct dentry *root; | ||
1011 | struct efivar_entry *entry, *n; | ||
1012 | struct efivars *efivars = &__efivars; | ||
1013 | char *name; | ||
1014 | |||
1015 | efivarfs_sb = sb; | ||
1016 | |||
1017 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
1018 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
1019 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
1020 | sb->s_magic = EFIVARFS_MAGIC; | ||
1021 | sb->s_op = &efivarfs_ops; | ||
1022 | sb->s_time_gran = 1; | ||
1023 | |||
1024 | inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0); | ||
1025 | if (!inode) | ||
1026 | return -ENOMEM; | ||
1027 | inode->i_op = &efivarfs_dir_inode_operations; | ||
1028 | |||
1029 | root = d_make_root(inode); | ||
1030 | sb->s_root = root; | ||
1031 | if (!root) | ||
1032 | return -ENOMEM; | ||
1033 | |||
1034 | list_for_each_entry_safe(entry, n, &efivars->list, list) { | ||
1035 | struct dentry *dentry, *root = efivarfs_sb->s_root; | ||
1036 | unsigned long size = 0; | ||
1037 | int len, i; | ||
1038 | |||
1039 | inode = NULL; | ||
1040 | |||
1041 | len = utf16_strlen(entry->var.VariableName); | ||
1042 | |||
1043 | /* name, plus '-', plus GUID, plus NUL*/ | ||
1044 | name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); | ||
1045 | if (!name) | ||
1046 | goto fail; | ||
1047 | |||
1048 | for (i = 0; i < len; i++) | ||
1049 | name[i] = entry->var.VariableName[i] & 0xFF; | ||
1050 | |||
1051 | name[len] = '-'; | ||
1052 | |||
1053 | efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); | ||
1054 | |||
1055 | name[len+GUID_LEN+1] = '\0'; | ||
1056 | |||
1057 | inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, | ||
1058 | S_IFREG | 0644, 0); | ||
1059 | if (!inode) | ||
1060 | goto fail_name; | ||
1061 | |||
1062 | dentry = d_alloc_name(root, name); | ||
1063 | if (!dentry) | ||
1064 | goto fail_inode; | ||
1065 | |||
1066 | /* copied by the above to local storage in the dentry. */ | ||
1067 | kfree(name); | ||
1068 | |||
1069 | spin_lock(&efivars->lock); | ||
1070 | efivars->ops->get_variable(entry->var.VariableName, | ||
1071 | &entry->var.VendorGuid, | ||
1072 | &entry->var.Attributes, | ||
1073 | &size, | ||
1074 | NULL); | ||
1075 | spin_unlock(&efivars->lock); | ||
1076 | |||
1077 | mutex_lock(&inode->i_mutex); | ||
1078 | inode->i_private = entry; | ||
1079 | i_size_write(inode, size+4); | ||
1080 | mutex_unlock(&inode->i_mutex); | ||
1081 | d_add(dentry, inode); | ||
1082 | } | ||
1083 | |||
1084 | return 0; | ||
1085 | |||
1086 | fail_inode: | ||
1087 | iput(inode); | ||
1088 | fail_name: | ||
1089 | kfree(name); | ||
1090 | fail: | ||
1091 | return -ENOMEM; | ||
1092 | } | ||
1093 | |||
1094 | static struct dentry *efivarfs_mount(struct file_system_type *fs_type, | ||
1095 | int flags, const char *dev_name, void *data) | ||
1096 | { | ||
1097 | return mount_single(fs_type, flags, data, efivarfs_fill_super); | ||
1098 | } | ||
1099 | |||
1100 | static void efivarfs_kill_sb(struct super_block *sb) | ||
1101 | { | ||
1102 | kill_litter_super(sb); | ||
1103 | efivarfs_sb = NULL; | ||
1104 | } | ||
1105 | |||
1106 | static struct file_system_type efivarfs_type = { | ||
1107 | .name = "efivarfs", | ||
1108 | .mount = efivarfs_mount, | ||
1109 | .kill_sb = efivarfs_kill_sb, | ||
1110 | }; | ||
1111 | |||
1112 | static const struct inode_operations efivarfs_dir_inode_operations = { | ||
1113 | .lookup = simple_lookup, | ||
1114 | .unlink = efivarfs_unlink, | ||
1115 | .create = efivarfs_create, | ||
1116 | }; | ||
1117 | |||
1118 | static struct pstore_info efi_pstore_info; | ||
1119 | |||
640 | #ifdef CONFIG_PSTORE | 1120 | #ifdef CONFIG_PSTORE |
641 | 1121 | ||
642 | static int efi_pstore_open(struct pstore_info *psi) | 1122 | static int efi_pstore_open(struct pstore_info *psi) |
@@ -1065,11 +1545,18 @@ efivar_create_sysfs_entry(struct efivars *efivars, | |||
1065 | efi_char16_t *variable_name, | 1545 | efi_char16_t *variable_name, |
1066 | efi_guid_t *vendor_guid) | 1546 | efi_guid_t *vendor_guid) |
1067 | { | 1547 | { |
1068 | int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; | 1548 | int i, short_name_size; |
1069 | char *short_name; | 1549 | char *short_name; |
1070 | struct efivar_entry *new_efivar; | 1550 | struct efivar_entry *new_efivar; |
1071 | 1551 | ||
1072 | short_name = kzalloc(short_name_size + 1, GFP_KERNEL); | 1552 | /* |
1553 | * Length of the variable bytes in ASCII, plus the '-' separator, | ||
1554 | * plus the GUID, plus trailing NUL | ||
1555 | */ | ||
1556 | short_name_size = variable_name_size / sizeof(efi_char16_t) | ||
1557 | + 1 + GUID_LEN + 1; | ||
1558 | |||
1559 | short_name = kzalloc(short_name_size, GFP_KERNEL); | ||
1073 | new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); | 1560 | new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); |
1074 | 1561 | ||
1075 | if (!short_name || !new_efivar) { | 1562 | if (!short_name || !new_efivar) { |
@@ -1189,6 +1676,7 @@ void unregister_efivars(struct efivars *efivars) | |||
1189 | sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); | 1676 | sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var); |
1190 | kfree(efivars->new_var); | 1677 | kfree(efivars->new_var); |
1191 | kfree(efivars->del_var); | 1678 | kfree(efivars->del_var); |
1679 | kobject_put(efivars->kobject); | ||
1192 | kset_unregister(efivars->kset); | 1680 | kset_unregister(efivars->kset); |
1193 | } | 1681 | } |
1194 | EXPORT_SYMBOL_GPL(unregister_efivars); | 1682 | EXPORT_SYMBOL_GPL(unregister_efivars); |
@@ -1220,6 +1708,14 @@ int register_efivars(struct efivars *efivars, | |||
1220 | goto out; | 1708 | goto out; |
1221 | } | 1709 | } |
1222 | 1710 | ||
1711 | efivars->kobject = kobject_create_and_add("efivars", parent_kobj); | ||
1712 | if (!efivars->kobject) { | ||
1713 | pr_err("efivars: Subsystem registration failed.\n"); | ||
1714 | error = -ENOMEM; | ||
1715 | kset_unregister(efivars->kset); | ||
1716 | goto out; | ||
1717 | } | ||
1718 | |||
1223 | /* | 1719 | /* |
1224 | * Per EFI spec, the maximum storage allocated for both | 1720 | * Per EFI spec, the maximum storage allocated for both |
1225 | * the variable name and variable data is 1024 bytes. | 1721 | * the variable name and variable data is 1024 bytes. |
@@ -1262,6 +1758,8 @@ int register_efivars(struct efivars *efivars, | |||
1262 | pstore_register(&efivars->efi_pstore_info); | 1758 | pstore_register(&efivars->efi_pstore_info); |
1263 | } | 1759 | } |
1264 | 1760 | ||
1761 | register_filesystem(&efivarfs_type); | ||
1762 | |||
1265 | out: | 1763 | out: |
1266 | kfree(variable_name); | 1764 | kfree(variable_name); |
1267 | 1765 | ||
@@ -1269,9 +1767,6 @@ out: | |||
1269 | } | 1767 | } |
1270 | EXPORT_SYMBOL_GPL(register_efivars); | 1768 | EXPORT_SYMBOL_GPL(register_efivars); |
1271 | 1769 | ||
1272 | static struct efivars __efivars; | ||
1273 | static struct efivar_operations ops; | ||
1274 | |||
1275 | /* | 1770 | /* |
1276 | * For now we register the efi subsystem with the firmware subsystem | 1771 | * For now we register the efi subsystem with the firmware subsystem |
1277 | * and the vars subsystem with the efi subsystem. In the future, it | 1772 | * and the vars subsystem with the efi subsystem. In the future, it |
@@ -1302,6 +1797,7 @@ efivars_init(void) | |||
1302 | ops.set_variable = efi.set_variable; | 1797 | ops.set_variable = efi.set_variable; |
1303 | ops.get_next_variable = efi.get_next_variable; | 1798 | ops.get_next_variable = efi.get_next_variable; |
1304 | ops.query_variable_info = efi.query_variable_info; | 1799 | ops.query_variable_info = efi.query_variable_info; |
1800 | |||
1305 | error = register_efivars(&__efivars, &ops, efi_kobj); | 1801 | error = register_efivars(&__efivars, &ops, efi_kobj); |
1306 | if (error) | 1802 | if (error) |
1307 | goto err_put; | 1803 | goto err_put; |