aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efivars.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2012-10-05 01:54:56 -0400
committerMatt Fleming <matt.fleming@intel.com>2012-10-30 06:39:16 -0400
commit5d9db883761ad1bc2245fd3018715549b974203d (patch)
treef014ebfff596b735ad9b7628035cf830be632ff0 /drivers/firmware/efivars.c
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
efi: Add support for a UEFI variable filesystem
The existing EFI variables code only supports variables of up to 1024 bytes. This limitation existed in version 0.99 of the EFI specification, but was removed before any full releases. Since variables can now be larger than a single page, sysfs isn't the best interface for this. So, instead, let's add a filesystem. Variables can be read, written and created, with the first 4 bytes of each variable representing its UEFI attributes. The create() method doesn't actually commit to flash since zero-length variables can't exist per-spec. Updates from Jeremy Kerr <jeremy.kerr@canonical.com>. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'drivers/firmware/efivars.c')
-rw-r--r--drivers/firmware/efivars.c384
1 files changed, 378 insertions, 6 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index d10c9873dd9a..b605c4849772 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"
@@ -91,6 +95,7 @@ MODULE_LICENSE("GPL");
91MODULE_VERSION(EFIVARS_VERSION); 95MODULE_VERSION(EFIVARS_VERSION);
92 96
93#define DUMP_NAME_LEN 52 97#define DUMP_NAME_LEN 52
98#define GUID_LEN 37
94 99
95/* 100/*
96 * The maximum size of VariableName + Data = 1024 101 * The maximum size of VariableName + Data = 1024
@@ -108,7 +113,6 @@ struct efi_variable {
108 __u32 Attributes; 113 __u32 Attributes;
109} __attribute__((packed)); 114} __attribute__((packed));
110 115
111
112struct efivar_entry { 116struct efivar_entry {
113 struct efivars *efivars; 117 struct efivars *efivars;
114 struct efi_variable var; 118 struct efi_variable var;
@@ -122,6 +126,9 @@ struct efivar_attribute {
122 ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); 126 ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
123}; 127};
124 128
129static struct efivars __efivars;
130static struct efivar_operations ops;
131
125#define PSTORE_EFI_ATTRIBUTES \ 132#define PSTORE_EFI_ATTRIBUTES \
126 (EFI_VARIABLE_NON_VOLATILE | \ 133 (EFI_VARIABLE_NON_VOLATILE | \
127 EFI_VARIABLE_BOOTSERVICE_ACCESS | \ 134 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
@@ -629,14 +636,380 @@ static struct kobj_type efivar_ktype = {
629 .default_attrs = def_attrs, 636 .default_attrs = def_attrs,
630}; 637};
631 638
632static struct pstore_info efi_pstore_info;
633
634static inline void 639static inline void
635efivar_unregister(struct efivar_entry *var) 640efivar_unregister(struct efivar_entry *var)
636{ 641{
637 kobject_put(&var->kobj); 642 kobject_put(&var->kobj);
638} 643}
639 644
645static int efivarfs_file_open(struct inode *inode, struct file *file)
646{
647 file->private_data = inode->i_private;
648 return 0;
649}
650
651static ssize_t efivarfs_file_write(struct file *file,
652 const char __user *userbuf, size_t count, loff_t *ppos)
653{
654 struct efivar_entry *var = file->private_data;
655 struct efivars *efivars;
656 efi_status_t status;
657 void *data;
658 u32 attributes;
659 struct inode *inode = file->f_mapping->host;
660 int datasize = count - sizeof(attributes);
661
662 if (count < sizeof(attributes))
663 return -EINVAL;
664
665 data = kmalloc(datasize, GFP_KERNEL);
666
667 if (!data)
668 return -ENOMEM;
669
670 efivars = var->efivars;
671
672 if (copy_from_user(&attributes, userbuf, sizeof(attributes))) {
673 count = -EFAULT;
674 goto out;
675 }
676
677 if (attributes & ~(EFI_VARIABLE_MASK)) {
678 count = -EINVAL;
679 goto out;
680 }
681
682 if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
683 count = -EFAULT;
684 goto out;
685 }
686
687 if (validate_var(&var->var, data, datasize) == false) {
688 count = -EINVAL;
689 goto out;
690 }
691
692 status = efivars->ops->set_variable(var->var.VariableName,
693 &var->var.VendorGuid,
694 attributes, datasize,
695 data);
696
697 switch (status) {
698 case EFI_SUCCESS:
699 mutex_lock(&inode->i_mutex);
700 i_size_write(inode, count);
701 mutex_unlock(&inode->i_mutex);
702 break;
703 case EFI_INVALID_PARAMETER:
704 count = -EINVAL;
705 break;
706 case EFI_OUT_OF_RESOURCES:
707 count = -ENOSPC;
708 break;
709 case EFI_DEVICE_ERROR:
710 count = -EIO;
711 break;
712 case EFI_WRITE_PROTECTED:
713 count = -EROFS;
714 break;
715 case EFI_SECURITY_VIOLATION:
716 count = -EACCES;
717 break;
718 case EFI_NOT_FOUND:
719 count = -ENOENT;
720 break;
721 default:
722 count = -EINVAL;
723 break;
724 }
725out:
726 kfree(data);
727
728 return count;
729}
730
731static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
732 size_t count, loff_t *ppos)
733{
734 struct efivar_entry *var = file->private_data;
735 struct efivars *efivars = var->efivars;
736 efi_status_t status;
737 unsigned long datasize = 0;
738 u32 attributes;
739 void *data;
740 ssize_t size;
741
742 status = efivars->ops->get_variable(var->var.VariableName,
743 &var->var.VendorGuid,
744 &attributes, &datasize, NULL);
745
746 if (status != EFI_BUFFER_TOO_SMALL)
747 return 0;
748
749 data = kmalloc(datasize + 4, GFP_KERNEL);
750
751 if (!data)
752 return 0;
753
754 status = efivars->ops->get_variable(var->var.VariableName,
755 &var->var.VendorGuid,
756 &attributes, &datasize,
757 (data + 4));
758
759 if (status != EFI_SUCCESS)
760 return 0;
761
762 memcpy(data, &attributes, 4);
763 size = simple_read_from_buffer(userbuf, count, ppos,
764 data, datasize + 4);
765 kfree(data);
766
767 return size;
768}
769
770static void efivarfs_evict_inode(struct inode *inode)
771{
772 clear_inode(inode);
773}
774
775static const struct super_operations efivarfs_ops = {
776 .statfs = simple_statfs,
777 .drop_inode = generic_delete_inode,
778 .evict_inode = efivarfs_evict_inode,
779 .show_options = generic_show_options,
780};
781
782static struct super_block *efivarfs_sb;
783
784static const struct inode_operations efivarfs_dir_inode_operations;
785
786static const struct file_operations efivarfs_file_operations = {
787 .open = efivarfs_file_open,
788 .read = efivarfs_file_read,
789 .write = efivarfs_file_write,
790 .llseek = no_llseek,
791};
792
793static struct inode *efivarfs_get_inode(struct super_block *sb,
794 const struct inode *dir, int mode, dev_t dev)
795{
796 struct inode *inode = new_inode(sb);
797
798 if (inode) {
799 inode->i_ino = get_next_ino();
800 inode->i_uid = inode->i_gid = 0;
801 inode->i_mode = mode;
802 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
803 switch (mode & S_IFMT) {
804 case S_IFREG:
805 inode->i_fop = &efivarfs_file_operations;
806 break;
807 case S_IFDIR:
808 inode->i_op = &efivarfs_dir_inode_operations;
809 inode->i_fop = &simple_dir_operations;
810 inc_nlink(inode);
811 break;
812 }
813 }
814 return inode;
815}
816
817static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
818{
819 guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
820 guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]);
821 guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]);
822 guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]);
823 guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]);
824 guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]);
825 guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]);
826 guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]);
827 guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]);
828 guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]);
829 guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]);
830 guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]);
831 guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]);
832 guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]);
833 guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]);
834 guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]);
835}
836
837static int efivarfs_create(struct inode *dir, struct dentry *dentry,
838 umode_t mode, bool excl)
839{
840 struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
841 struct efivars *efivars = &__efivars;
842 struct efivar_entry *var;
843 int namelen, i = 0, err = 0;
844
845 if (dentry->d_name.len < 38)
846 return -EINVAL;
847
848 if (!inode)
849 return -ENOSPC;
850
851 var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
852
853 if (!var)
854 return -ENOMEM;
855
856 namelen = dentry->d_name.len - GUID_LEN;
857
858 efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
859 &var->var.VendorGuid);
860
861 for (i = 0; i < namelen; i++)
862 var->var.VariableName[i] = dentry->d_name.name[i];
863
864 var->var.VariableName[i] = '\0';
865
866 inode->i_private = var;
867 var->efivars = efivars;
868 var->kobj.kset = efivars->kset;
869
870 err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s",
871 dentry->d_name.name);
872 if (err)
873 goto out;
874
875 kobject_uevent(&var->kobj, KOBJ_ADD);
876 spin_lock(&efivars->lock);
877 list_add(&var->list, &efivars->list);
878 spin_unlock(&efivars->lock);
879 d_instantiate(dentry, inode);
880 dget(dentry);
881out:
882 if (err)
883 kfree(var);
884 return err;
885}
886
887static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
888{
889 struct efivar_entry *var = dentry->d_inode->i_private;
890 struct efivars *efivars = var->efivars;
891 efi_status_t status;
892
893 spin_lock(&efivars->lock);
894
895 status = efivars->ops->set_variable(var->var.VariableName,
896 &var->var.VendorGuid,
897 0, 0, NULL);
898
899 if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) {
900 list_del(&var->list);
901 spin_unlock(&efivars->lock);
902 efivar_unregister(var);
903 drop_nlink(dir);
904 dput(dentry);
905 return 0;
906 }
907
908 spin_unlock(&efivars->lock);
909 return -EINVAL;
910};
911
912int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
913{
914 struct inode *inode = NULL;
915 struct dentry *root;
916 struct efivar_entry *entry, *n;
917 struct efivars *efivars = &__efivars;
918 int err;
919
920 efivarfs_sb = sb;
921
922 sb->s_maxbytes = MAX_LFS_FILESIZE;
923 sb->s_blocksize = PAGE_CACHE_SIZE;
924 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
925 sb->s_magic = PSTOREFS_MAGIC;
926 sb->s_op = &efivarfs_ops;
927 sb->s_time_gran = 1;
928
929 inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
930 if (!inode) {
931 err = -ENOMEM;
932 goto fail;
933 }
934 inode->i_op = &efivarfs_dir_inode_operations;
935
936 root = d_make_root(inode);
937 sb->s_root = root;
938 if (!root) {
939 err = -ENOMEM;
940 goto fail;
941 }
942
943 list_for_each_entry_safe(entry, n, &efivars->list, list) {
944 struct inode *inode;
945 struct dentry *dentry, *root = efivarfs_sb->s_root;
946 char *name;
947 unsigned long size = 0;
948 int len, i;
949
950 len = utf16_strlen(entry->var.VariableName);
951
952 /* GUID plus trailing NULL */
953 name = kmalloc(len + 38, GFP_ATOMIC);
954
955 for (i = 0; i < len; i++)
956 name[i] = entry->var.VariableName[i] & 0xFF;
957
958 name[len] = '-';
959
960 efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);
961
962 name[len+GUID_LEN] = '\0';
963
964 inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
965 S_IFREG | 0644, 0);
966 dentry = d_alloc_name(root, name);
967
968 efivars->ops->get_variable(entry->var.VariableName,
969 &entry->var.VendorGuid,
970 &entry->var.Attributes,
971 &size,
972 NULL);
973
974 mutex_lock(&inode->i_mutex);
975 inode->i_private = entry;
976 i_size_write(inode, size+4);
977 mutex_unlock(&inode->i_mutex);
978 d_add(dentry, inode);
979 }
980
981 return 0;
982fail:
983 iput(inode);
984 return err;
985}
986
987static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
988 int flags, const char *dev_name, void *data)
989{
990 return mount_single(fs_type, flags, data, efivarfs_fill_super);
991}
992
993static void efivarfs_kill_sb(struct super_block *sb)
994{
995 kill_litter_super(sb);
996 efivarfs_sb = NULL;
997}
998
999static struct file_system_type efivarfs_type = {
1000 .name = "efivarfs",
1001 .mount = efivarfs_mount,
1002 .kill_sb = efivarfs_kill_sb,
1003};
1004
1005static const struct inode_operations efivarfs_dir_inode_operations = {
1006 .lookup = simple_lookup,
1007 .unlink = efivarfs_unlink,
1008 .create = efivarfs_create,
1009};
1010
1011static struct pstore_info efi_pstore_info;
1012
640#ifdef CONFIG_PSTORE 1013#ifdef CONFIG_PSTORE
641 1014
642static int efi_pstore_open(struct pstore_info *psi) 1015static int efi_pstore_open(struct pstore_info *psi)
@@ -1198,6 +1571,8 @@ int register_efivars(struct efivars *efivars,
1198 pstore_register(&efivars->efi_pstore_info); 1571 pstore_register(&efivars->efi_pstore_info);
1199 } 1572 }
1200 1573
1574 register_filesystem(&efivarfs_type);
1575
1201out: 1576out:
1202 kfree(variable_name); 1577 kfree(variable_name);
1203 1578
@@ -1205,9 +1580,6 @@ out:
1205} 1580}
1206EXPORT_SYMBOL_GPL(register_efivars); 1581EXPORT_SYMBOL_GPL(register_efivars);
1207 1582
1208static struct efivars __efivars;
1209static struct efivar_operations ops;
1210
1211/* 1583/*
1212 * For now we register the efi subsystem with the firmware subsystem 1584 * For now we register the efi subsystem with the firmware subsystem
1213 * and the vars subsystem with the efi subsystem. In the future, it 1585 * and the vars subsystem with the efi subsystem. In the future, it