summaryrefslogtreecommitdiffstats
path: root/efivarfs-3.7.patch
diff options
context:
space:
mode:
Diffstat (limited to 'efivarfs-3.7.patch')
-rw-r--r--efivarfs-3.7.patch1630
1 files changed, 0 insertions, 1630 deletions
diff --git a/efivarfs-3.7.patch b/efivarfs-3.7.patch
deleted file mode 100644
index 300910716..000000000
--- a/efivarfs-3.7.patch
+++ /dev/null
@@ -1,1630 +0,0 @@
-From cb6f23ee9601297c3c70d0cfe3d77dfde9bd119d Mon Sep 17 00:00:00 2001
-From: Matthew Garrett <mjg@redhat.com>
-Date: Fri, 5 Oct 2012 13:54:56 +0800
-Subject: [PATCH 01/17] 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>
----
- drivers/firmware/efivars.c | 384 ++++++++++++++++++++++++++++++++++++++++++++-
- include/linux/efi.h | 5 +
- 2 files changed, 383 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index d10c987..b605c48 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -80,6 +80,10 @@
- #include <linux/slab.h>
- #include <linux/pstore.h>
-
-+#include <linux/fs.h>
-+#include <linux/ramfs.h>
-+#include <linux/pagemap.h>
-+
- #include <asm/uaccess.h>
-
- #define EFIVARS_VERSION "0.08"
-@@ -91,6 +95,7 @@ MODULE_LICENSE("GPL");
- MODULE_VERSION(EFIVARS_VERSION);
-
- #define DUMP_NAME_LEN 52
-+#define GUID_LEN 37
-
- /*
- * The maximum size of VariableName + Data = 1024
-@@ -108,7 +113,6 @@ struct efi_variable {
- __u32 Attributes;
- } __attribute__((packed));
-
--
- struct efivar_entry {
- struct efivars *efivars;
- struct efi_variable var;
-@@ -122,6 +126,9 @@ struct efivar_attribute {
- ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
- };
-
-+static struct efivars __efivars;
-+static struct efivar_operations ops;
-+
- #define PSTORE_EFI_ATTRIBUTES \
- (EFI_VARIABLE_NON_VOLATILE | \
- EFI_VARIABLE_BOOTSERVICE_ACCESS | \
-@@ -629,14 +636,380 @@ static struct kobj_type efivar_ktype = {
- .default_attrs = def_attrs,
- };
-
--static struct pstore_info efi_pstore_info;
--
- static inline void
- efivar_unregister(struct efivar_entry *var)
- {
- kobject_put(&var->kobj);
- }
-
-+static int efivarfs_file_open(struct inode *inode, struct file *file)
-+{
-+ file->private_data = inode->i_private;
-+ return 0;
-+}
-+
-+static ssize_t efivarfs_file_write(struct file *file,
-+ const char __user *userbuf, size_t count, loff_t *ppos)
-+{
-+ struct efivar_entry *var = file->private_data;
-+ struct efivars *efivars;
-+ efi_status_t status;
-+ void *data;
-+ u32 attributes;
-+ struct inode *inode = file->f_mapping->host;
-+ int datasize = count - sizeof(attributes);
-+
-+ if (count < sizeof(attributes))
-+ return -EINVAL;
-+
-+ data = kmalloc(datasize, GFP_KERNEL);
-+
-+ if (!data)
-+ return -ENOMEM;
-+
-+ efivars = var->efivars;
-+
-+ if (copy_from_user(&attributes, userbuf, sizeof(attributes))) {
-+ count = -EFAULT;
-+ goto out;
-+ }
-+
-+ if (attributes & ~(EFI_VARIABLE_MASK)) {
-+ count = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
-+ count = -EFAULT;
-+ goto out;
-+ }
-+
-+ if (validate_var(&var->var, data, datasize) == false) {
-+ count = -EINVAL;
-+ goto out;
-+ }
-+
-+ status = efivars->ops->set_variable(var->var.VariableName,
-+ &var->var.VendorGuid,
-+ attributes, datasize,
-+ data);
-+
-+ switch (status) {
-+ case EFI_SUCCESS:
-+ mutex_lock(&inode->i_mutex);
-+ i_size_write(inode, count);
-+ mutex_unlock(&inode->i_mutex);
-+ break;
-+ case EFI_INVALID_PARAMETER:
-+ count = -EINVAL;
-+ break;
-+ case EFI_OUT_OF_RESOURCES:
-+ count = -ENOSPC;
-+ break;
-+ case EFI_DEVICE_ERROR:
-+ count = -EIO;
-+ break;
-+ case EFI_WRITE_PROTECTED:
-+ count = -EROFS;
-+ break;
-+ case EFI_SECURITY_VIOLATION:
-+ count = -EACCES;
-+ break;
-+ case EFI_NOT_FOUND:
-+ count = -ENOENT;
-+ break;
-+ default:
-+ count = -EINVAL;
-+ break;
-+ }
-+out:
-+ kfree(data);
-+
-+ return count;
-+}
-+
-+static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct efivar_entry *var = file->private_data;
-+ struct efivars *efivars = var->efivars;
-+ efi_status_t status;
-+ unsigned long datasize = 0;
-+ u32 attributes;
-+ void *data;
-+ ssize_t size;
-+
-+ status = efivars->ops->get_variable(var->var.VariableName,
-+ &var->var.VendorGuid,
-+ &attributes, &datasize, NULL);
-+
-+ if (status != EFI_BUFFER_TOO_SMALL)
-+ return 0;
-+
-+ data = kmalloc(datasize + 4, GFP_KERNEL);
-+
-+ if (!data)
-+ return 0;
-+
-+ status = efivars->ops->get_variable(var->var.VariableName,
-+ &var->var.VendorGuid,
-+ &attributes, &datasize,
-+ (data + 4));
-+
-+ if (status != EFI_SUCCESS)
-+ return 0;
-+
-+ memcpy(data, &attributes, 4);
-+ size = simple_read_from_buffer(userbuf, count, ppos,
-+ data, datasize + 4);
-+ kfree(data);
-+
-+ return size;
-+}
-+
-+static void efivarfs_evict_inode(struct inode *inode)
-+{
-+ clear_inode(inode);
-+}
-+
-+static const struct super_operations efivarfs_ops = {
-+ .statfs = simple_statfs,
-+ .drop_inode = generic_delete_inode,
-+ .evict_inode = efivarfs_evict_inode,
-+ .show_options = generic_show_options,
-+};
-+
-+static struct super_block *efivarfs_sb;
-+
-+static const struct inode_operations efivarfs_dir_inode_operations;
-+
-+static const struct file_operations efivarfs_file_operations = {
-+ .open = efivarfs_file_open,
-+ .read = efivarfs_file_read,
-+ .write = efivarfs_file_write,
-+ .llseek = no_llseek,
-+};
-+
-+static struct inode *efivarfs_get_inode(struct super_block *sb,
-+ const struct inode *dir, int mode, dev_t dev)
-+{
-+ struct inode *inode = new_inode(sb);
-+
-+ if (inode) {
-+ inode->i_ino = get_next_ino();
-+ inode->i_uid = inode->i_gid = 0;
-+ inode->i_mode = mode;
-+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-+ switch (mode & S_IFMT) {
-+ case S_IFREG:
-+ inode->i_fop = &efivarfs_file_operations;
-+ break;
-+ case S_IFDIR:
-+ inode->i_op = &efivarfs_dir_inode_operations;
-+ inode->i_fop = &simple_dir_operations;
-+ inc_nlink(inode);
-+ break;
-+ }
-+ }
-+ return inode;
-+}
-+
-+static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
-+{
-+ guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
-+ guid->b[1] = hex_to_bin(str[4]) << 4 | hex_to_bin(str[5]);
-+ guid->b[2] = hex_to_bin(str[2]) << 4 | hex_to_bin(str[3]);
-+ guid->b[3] = hex_to_bin(str[0]) << 4 | hex_to_bin(str[1]);
-+ guid->b[4] = hex_to_bin(str[11]) << 4 | hex_to_bin(str[12]);
-+ guid->b[5] = hex_to_bin(str[9]) << 4 | hex_to_bin(str[10]);
-+ guid->b[6] = hex_to_bin(str[16]) << 4 | hex_to_bin(str[17]);
-+ guid->b[7] = hex_to_bin(str[14]) << 4 | hex_to_bin(str[15]);
-+ guid->b[8] = hex_to_bin(str[19]) << 4 | hex_to_bin(str[20]);
-+ guid->b[9] = hex_to_bin(str[21]) << 4 | hex_to_bin(str[22]);
-+ guid->b[10] = hex_to_bin(str[24]) << 4 | hex_to_bin(str[25]);
-+ guid->b[11] = hex_to_bin(str[26]) << 4 | hex_to_bin(str[27]);
-+ guid->b[12] = hex_to_bin(str[28]) << 4 | hex_to_bin(str[29]);
-+ guid->b[13] = hex_to_bin(str[30]) << 4 | hex_to_bin(str[31]);
-+ guid->b[14] = hex_to_bin(str[32]) << 4 | hex_to_bin(str[33]);
-+ guid->b[15] = hex_to_bin(str[34]) << 4 | hex_to_bin(str[35]);
-+}
-+
-+static int efivarfs_create(struct inode *dir, struct dentry *dentry,
-+ umode_t mode, bool excl)
-+{
-+ struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
-+ struct efivars *efivars = &__efivars;
-+ struct efivar_entry *var;
-+ int namelen, i = 0, err = 0;
-+
-+ if (dentry->d_name.len < 38)
-+ return -EINVAL;
-+
-+ if (!inode)
-+ return -ENOSPC;
-+
-+ var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
-+
-+ if (!var)
-+ return -ENOMEM;
-+
-+ namelen = dentry->d_name.len - GUID_LEN;
-+
-+ efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
-+ &var->var.VendorGuid);
-+
-+ for (i = 0; i < namelen; i++)
-+ var->var.VariableName[i] = dentry->d_name.name[i];
-+
-+ var->var.VariableName[i] = '\0';
-+
-+ inode->i_private = var;
-+ var->efivars = efivars;
-+ var->kobj.kset = efivars->kset;
-+
-+ err = kobject_init_and_add(&var->kobj, &efivar_ktype, NULL, "%s",
-+ dentry->d_name.name);
-+ if (err)
-+ goto out;
-+
-+ kobject_uevent(&var->kobj, KOBJ_ADD);
-+ spin_lock(&efivars->lock);
-+ list_add(&var->list, &efivars->list);
-+ spin_unlock(&efivars->lock);
-+ d_instantiate(dentry, inode);
-+ dget(dentry);
-+out:
-+ if (err)
-+ kfree(var);
-+ return err;
-+}
-+
-+static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+ struct efivar_entry *var = dentry->d_inode->i_private;
-+ struct efivars *efivars = var->efivars;
-+ efi_status_t status;
-+
-+ spin_lock(&efivars->lock);
-+
-+ status = efivars->ops->set_variable(var->var.VariableName,
-+ &var->var.VendorGuid,
-+ 0, 0, NULL);
-+
-+ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) {
-+ list_del(&var->list);
-+ spin_unlock(&efivars->lock);
-+ efivar_unregister(var);
-+ drop_nlink(dir);
-+ dput(dentry);
-+ return 0;
-+ }
-+
-+ spin_unlock(&efivars->lock);
-+ return -EINVAL;
-+};
-+
-+int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
-+{
-+ struct inode *inode = NULL;
-+ struct dentry *root;
-+ struct efivar_entry *entry, *n;
-+ struct efivars *efivars = &__efivars;
-+ int err;
-+
-+ efivarfs_sb = sb;
-+
-+ sb->s_maxbytes = MAX_LFS_FILESIZE;
-+ sb->s_blocksize = PAGE_CACHE_SIZE;
-+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-+ sb->s_magic = PSTOREFS_MAGIC;
-+ sb->s_op = &efivarfs_ops;
-+ sb->s_time_gran = 1;
-+
-+ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
-+ if (!inode) {
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+ inode->i_op = &efivarfs_dir_inode_operations;
-+
-+ root = d_make_root(inode);
-+ sb->s_root = root;
-+ if (!root) {
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ list_for_each_entry_safe(entry, n, &efivars->list, list) {
-+ struct inode *inode;
-+ struct dentry *dentry, *root = efivarfs_sb->s_root;
-+ char *name;
-+ unsigned long size = 0;
-+ int len, i;
-+
-+ len = utf16_strlen(entry->var.VariableName);
-+
-+ /* GUID plus trailing NULL */
-+ name = kmalloc(len + 38, GFP_ATOMIC);
-+
-+ for (i = 0; i < len; i++)
-+ name[i] = entry->var.VariableName[i] & 0xFF;
-+
-+ name[len] = '-';
-+
-+ efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);
-+
-+ name[len+GUID_LEN] = '\0';
-+
-+ inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
-+ S_IFREG | 0644, 0);
-+ dentry = d_alloc_name(root, name);
-+
-+ efivars->ops->get_variable(entry->var.VariableName,
-+ &entry->var.VendorGuid,
-+ &entry->var.Attributes,
-+ &size,
-+ NULL);
-+
-+ mutex_lock(&inode->i_mutex);
-+ inode->i_private = entry;
-+ i_size_write(inode, size+4);
-+ mutex_unlock(&inode->i_mutex);
-+ d_add(dentry, inode);
-+ }
-+
-+ return 0;
-+fail:
-+ iput(inode);
-+ return err;
-+}
-+
-+static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
-+ int flags, const char *dev_name, void *data)
-+{
-+ return mount_single(fs_type, flags, data, efivarfs_fill_super);
-+}
-+
-+static void efivarfs_kill_sb(struct super_block *sb)
-+{
-+ kill_litter_super(sb);
-+ efivarfs_sb = NULL;
-+}
-+
-+static struct file_system_type efivarfs_type = {
-+ .name = "efivarfs",
-+ .mount = efivarfs_mount,
-+ .kill_sb = efivarfs_kill_sb,
-+};
-+
-+static const struct inode_operations efivarfs_dir_inode_operations = {
-+ .lookup = simple_lookup,
-+ .unlink = efivarfs_unlink,
-+ .create = efivarfs_create,
-+};
-+
-+static struct pstore_info efi_pstore_info;
-+
- #ifdef CONFIG_PSTORE
-
- static int efi_pstore_open(struct pstore_info *psi)
-@@ -1198,6 +1571,8 @@ int register_efivars(struct efivars *efivars,
- pstore_register(&efivars->efi_pstore_info);
- }
-
-+ register_filesystem(&efivarfs_type);
-+
- out:
- kfree(variable_name);
-
-@@ -1205,9 +1580,6 @@ out:
- }
- EXPORT_SYMBOL_GPL(register_efivars);
-
--static struct efivars __efivars;
--static struct efivar_operations ops;
--
- /*
- * For now we register the efi subsystem with the firmware subsystem
- * and the vars subsystem with the efi subsystem. In the future, it
-diff --git a/include/linux/efi.h b/include/linux/efi.h
-index 8670eb1..b2af157 100644
---- a/include/linux/efi.h
-+++ b/include/linux/efi.h
-@@ -29,7 +29,12 @@
- #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
- #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
- #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
-+#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1)))
-+#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1)))
-+#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
-+#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
- #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
-+#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))
-
- typedef unsigned long efi_status_t;
- typedef u8 efi_bool_t;
---
-1.7.12.1
-
-
-From 2fc1dc88e97665c70f203f0132232ea55e8dd7eb Mon Sep 17 00:00:00 2001
-From: Jeremy Kerr <jeremy.kerr@canonical.com>
-Date: Fri, 5 Oct 2012 13:54:56 +0800
-Subject: [PATCH 02/17] efi: Handle deletions and size changes in
- efivarfs_write_file
-
-A write to an efivarfs file will not always result in a variable of
-'count' size after the EFI SetVariable() call. We may have appended to
-the existing data (ie, with the EFI_VARIABLE_APPEND_WRITE attribute), or
-even have deleted the variable (with an authenticated variable update,
-with a zero datasize).
-
-This change re-reads the updated variable from firmware, to check for
-size changes and deletions. In the latter case, we need to drop the
-dentry.
-
-Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 49 ++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 39 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index b605c48..d7658b4 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -658,6 +658,7 @@ static ssize_t efivarfs_file_write(struct file *file,
- u32 attributes;
- struct inode *inode = file->f_mapping->host;
- int datasize = count - sizeof(attributes);
-+ unsigned long newdatasize;
-
- if (count < sizeof(attributes))
- return -EINVAL;
-@@ -696,32 +697,60 @@ static ssize_t efivarfs_file_write(struct file *file,
-
- switch (status) {
- case EFI_SUCCESS:
-- mutex_lock(&inode->i_mutex);
-- i_size_write(inode, count);
-- mutex_unlock(&inode->i_mutex);
- break;
- case EFI_INVALID_PARAMETER:
- count = -EINVAL;
-- break;
-+ goto out;
- case EFI_OUT_OF_RESOURCES:
- count = -ENOSPC;
-- break;
-+ goto out;
- case EFI_DEVICE_ERROR:
- count = -EIO;
-- break;
-+ goto out;
- case EFI_WRITE_PROTECTED:
- count = -EROFS;
-- break;
-+ goto out;
- case EFI_SECURITY_VIOLATION:
- count = -EACCES;
-- break;
-+ goto out;
- case EFI_NOT_FOUND:
- count = -ENOENT;
-- break;
-+ goto out;
- default:
- count = -EINVAL;
-- break;
-+ goto out;
- }
-+
-+ /*
-+ * Writing to the variable may have caused a change in size (which
-+ * could either be an append or an overwrite), or the variable to be
-+ * deleted. Perform a GetVariable() so we can tell what actually
-+ * happened.
-+ */
-+ newdatasize = 0;
-+ status = efivars->ops->get_variable(var->var.VariableName,
-+ &var->var.VendorGuid,
-+ NULL, &newdatasize,
-+ NULL);
-+
-+ if (status == EFI_BUFFER_TOO_SMALL) {
-+ mutex_lock(&inode->i_mutex);
-+ i_size_write(inode, newdatasize + sizeof(attributes));
-+ mutex_unlock(&inode->i_mutex);
-+
-+ } else if (status == EFI_NOT_FOUND) {
-+ spin_lock(&efivars->lock);
-+ list_del(&var->list);
-+ spin_unlock(&efivars->lock);
-+ efivar_unregister(var);
-+ drop_nlink(inode);
-+ dput(file->f_dentry);
-+
-+ } else {
-+ pr_warn("efivarfs: inconsistent EFI variable implementation? "
-+ "status = %lx\n", status);
-+ }
-+
- out:
- kfree(data);
-
---
-1.7.12.1
-
-
-From c98611fc95672862950c9bc4d6a3a4c4453a3c3e Mon Sep 17 00:00:00 2001
-From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com>
-Date: Fri, 5 Oct 2012 13:54:56 +0800
-Subject: [PATCH 03/17] efi: add efivars kobject to efi sysfs folder
-
-UEFI variable filesystem need a new mount point, so this patch add
-efivars kobject to efi_kobj for create a /sys/firmware/efi/efivars
-folder.
-
-Cc: Matthew Garrett <mjg@redhat.com>
-Cc: H. Peter Anvin <hpa@zytor.com>
-Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
-Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 9 +++++++++
- include/linux/efi.h | 1 +
- 2 files changed, 10 insertions(+)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index d7658b4..6793965 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -1527,6 +1527,7 @@ void unregister_efivars(struct efivars *efivars)
- sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
- kfree(efivars->new_var);
- kfree(efivars->del_var);
-+ kobject_put(efivars->kobject);
- kset_unregister(efivars->kset);
- }
- EXPORT_SYMBOL_GPL(unregister_efivars);
-@@ -1558,6 +1559,14 @@ int register_efivars(struct efivars *efivars,
- goto out;
- }
-
-+ efivars->kobject = kobject_create_and_add("efivars", parent_kobj);
-+ if (!efivars->kobject) {
-+ pr_err("efivars: Subsystem registration failed.\n");
-+ error = -ENOMEM;
-+ kset_unregister(efivars->kset);
-+ goto out;
-+ }
-+
- /*
- * Per EFI spec, the maximum storage allocated for both
- * the variable name and variable data is 1024 bytes.
-diff --git a/include/linux/efi.h b/include/linux/efi.h
-index b2af157..337aefb 100644
---- a/include/linux/efi.h
-+++ b/include/linux/efi.h
-@@ -662,6 +662,7 @@ struct efivars {
- spinlock_t lock;
- struct list_head list;
- struct kset *kset;
-+ struct kobject *kobject;
- struct bin_attribute *new_var, *del_var;
- const struct efivar_operations *ops;
- struct efivar_entry *walk_entry;
---
-1.7.12.1
-
-
-From 8ef5f49da57087022f2031820ceb3b1c6101d76c Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Thu, 4 Oct 2012 09:57:31 +0100
-Subject: [PATCH 04/17] efivarfs: Add documentation for the EFI variable
- filesystem
-
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- Documentation/filesystems/00-INDEX | 2 ++
- Documentation/filesystems/efivarfs.txt | 16 ++++++++++++++++
- 2 files changed, 18 insertions(+)
- create mode 100644 Documentation/filesystems/efivarfs.txt
-
-diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
-index 8c624a1..7b52ba7 100644
---- a/Documentation/filesystems/00-INDEX
-+++ b/Documentation/filesystems/00-INDEX
-@@ -38,6 +38,8 @@ dnotify_test.c
- - example program for dnotify
- ecryptfs.txt
- - docs on eCryptfs: stacked cryptographic filesystem for Linux.
-+efivarfs.txt
-+ - info for the efivarfs filesystem.
- exofs.txt
- - info, usage, mount options, design about EXOFS.
- ext2.txt
-diff --git a/Documentation/filesystems/efivarfs.txt b/Documentation/filesystems/efivarfs.txt
-new file mode 100644
-index 0000000..c477af0
---- /dev/null
-+++ b/Documentation/filesystems/efivarfs.txt
-@@ -0,0 +1,16 @@
-+
-+efivarfs - a (U)EFI variable filesystem
-+
-+The efivarfs filesystem was created to address the shortcomings of
-+using entries in sysfs to maintain EFI variables. The old sysfs EFI
-+variables code only supported 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.
-+
-+Variables can be created, deleted and modified with the efivarfs
-+filesystem.
-+
-+efivarfs is typically mounted like this,
-+
-+ mount -t efivarfs none /sys/firmware/efi/efivars
---
-1.7.12.1
-
-
-From f69c39248e2f1eebf24f5ee55139602c56d15aec Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Thu, 11 Oct 2012 11:32:17 +0100
-Subject: [PATCH 05/17] efivarfs: efivarfs_file_read ensure we free data in
- error paths
-
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Matthew Garrett <mjg@redhat.com>
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 6793965..b7c9a32 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -766,7 +766,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- unsigned long datasize = 0;
- u32 attributes;
- void *data;
-- ssize_t size;
-+ ssize_t size = 0;
-
- status = efivars->ops->get_variable(var->var.VariableName,
- &var->var.VendorGuid,
-@@ -784,13 +784,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- &var->var.VendorGuid,
- &attributes, &datasize,
- (data + 4));
--
- if (status != EFI_SUCCESS)
-- return 0;
-+ goto out_free;
-
- memcpy(data, &attributes, 4);
- size = simple_read_from_buffer(userbuf, count, ppos,
- data, datasize + 4);
-+out_free:
- kfree(data);
-
- return size;
---
-1.7.12.1
-
-
-From 429136e16c7c43bbebb8b8030203161a2d3fc3ce Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Thu, 11 Oct 2012 11:32:18 +0100
-Subject: [PATCH 06/17] efivarfs: efivarfs_create() ensure we drop our
- reference on inode on error
-
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Matthew Garrett <mjg@redhat.com>
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 14 +++++++++-----
- 1 file changed, 9 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index b7c9a32..6e5f367 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -866,7 +866,7 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
- static int efivarfs_create(struct inode *dir, struct dentry *dentry,
- umode_t mode, bool excl)
- {
-- struct inode *inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
-+ struct inode *inode;
- struct efivars *efivars = &__efivars;
- struct efivar_entry *var;
- int namelen, i = 0, err = 0;
-@@ -874,13 +874,15 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
- if (dentry->d_name.len < 38)
- return -EINVAL;
-
-+ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
- if (!inode)
- return -ENOSPC;
-
- var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
--
-- if (!var)
-- return -ENOMEM;
-+ if (!var) {
-+ err = -ENOMEM;
-+ goto out;
-+ }
-
- namelen = dentry->d_name.len - GUID_LEN;
-
-@@ -908,8 +910,10 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
- d_instantiate(dentry, inode);
- dget(dentry);
- out:
-- if (err)
-+ if (err) {
- kfree(var);
-+ iput(inode);
-+ }
- return err;
- }
-
---
-1.7.12.1
-
-
-From 1a19268e8a4bae43c1feb3f71ee468c6bc70aca6 Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Thu, 11 Oct 2012 11:32:19 +0100
-Subject: [PATCH 07/17] efivarfs: efivarfs_fill_super() fix inode reference
- counts
-
-When d_make_root() fails it will automatically drop the reference
-on the root inode. We should not be doing so as well.
-
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Matthew Garrett <mjg@redhat.com>
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 16 ++++------------
- 1 file changed, 4 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 6e5f367..adfc486 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -948,7 +948,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- struct dentry *root;
- struct efivar_entry *entry, *n;
- struct efivars *efivars = &__efivars;
-- int err;
-
- efivarfs_sb = sb;
-
-@@ -960,18 +959,14 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- sb->s_time_gran = 1;
-
- inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
-- if (!inode) {
-- err = -ENOMEM;
-- goto fail;
-- }
-+ if (!inode)
-+ return -ENOMEM;
- inode->i_op = &efivarfs_dir_inode_operations;
-
- root = d_make_root(inode);
- sb->s_root = root;
-- if (!root) {
-- err = -ENOMEM;
-- goto fail;
-- }
-+ if (!root)
-+ return -ENOMEM;
-
- list_for_each_entry_safe(entry, n, &efivars->list, list) {
- struct inode *inode;
-@@ -1012,9 +1007,6 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- }
-
- return 0;
--fail:
-- iput(inode);
-- return err;
- }
-
- static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
---
-1.7.12.1
-
-
-From f0d90a4024493aed6fc77ce5cd3b93f278fed9c0 Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Thu, 11 Oct 2012 11:32:20 +0100
-Subject: [PATCH 08/17] efivarfs: efivarfs_fill_super() ensure we free our
- temporary name
-
-d_alloc_name() copies the passed name to new storage, once complete we
-no longer need our name.
-
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Matthew Garrett <mjg@redhat.com>
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index adfc486..36b3dd6 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -992,6 +992,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
- S_IFREG | 0644, 0);
- dentry = d_alloc_name(root, name);
-+ /* copied by the above to local storage in the dentry. */
-+ kfree(name);
-
- efivars->ops->get_variable(entry->var.VariableName,
- &entry->var.VendorGuid,
---
-1.7.12.1
-
-
-From c4cf244c318218153200d0011d8ef0ebcf3146ea Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Thu, 11 Oct 2012 11:32:21 +0100
-Subject: [PATCH 09/17] efivarfs: efivarfs_fill_super() ensure we clean up
- correctly on error
-
-Ensure we free both the name and inode on error when building the
-individual variables.
-
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Matthew Garrett <mjg@redhat.com>
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 20 ++++++++++++++++++--
- 1 file changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 36b3dd6..216086d 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -948,6 +948,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- struct dentry *root;
- struct efivar_entry *entry, *n;
- struct efivars *efivars = &__efivars;
-+ char *name;
-
- efivarfs_sb = sb;
-
-@@ -969,16 +970,18 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- return -ENOMEM;
-
- list_for_each_entry_safe(entry, n, &efivars->list, list) {
-- struct inode *inode;
- struct dentry *dentry, *root = efivarfs_sb->s_root;
-- char *name;
- unsigned long size = 0;
- int len, i;
-
-+ inode = NULL;
-+
- len = utf16_strlen(entry->var.VariableName);
-
- /* GUID plus trailing NULL */
- name = kmalloc(len + 38, GFP_ATOMIC);
-+ if (!name)
-+ goto fail;
-
- for (i = 0; i < len; i++)
- name[i] = entry->var.VariableName[i] & 0xFF;
-@@ -991,7 +994,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
-
- inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
- S_IFREG | 0644, 0);
-+ if (!inode)
-+ goto fail_name;
-+
- dentry = d_alloc_name(root, name);
-+ if (!dentry)
-+ goto fail_inode;
-+
- /* copied by the above to local storage in the dentry. */
- kfree(name);
-
-@@ -1009,6 +1018,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- }
-
- return 0;
-+
-+fail_inode:
-+ iput(inode);
-+fail_name:
-+ kfree(name);
-+fail:
-+ return -ENOMEM;
- }
-
- static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
---
-1.7.12.1
-
-
-From d3b7165568bcb50e4526c3dadda59e43f6681bc0 Mon Sep 17 00:00:00 2001
-From: Jeremy Kerr <jeremy.kerr@canonical.com>
-Date: Thu, 11 Oct 2012 21:19:11 +0800
-Subject: [PATCH 10/17] efivarfs: Implement exclusive access for
- {get,set}_variable
-
-Currently, efivarfs does not enforce exclusion over the get_variable and
-set_variable operations. Section 7.1 of UEFI requires us to only allow a
-single processor to enter {get,set}_variable services at once.
-
-This change acquires the efivars->lock over calls to these operations
-from the efivarfs paths.
-
-Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 68 +++++++++++++++++++++++++++++-----------------
- 1 file changed, 43 insertions(+), 25 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 216086d..d478c56 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -690,35 +690,45 @@ static ssize_t efivarfs_file_write(struct file *file,
- goto out;
- }
-
-+ /*
-+ * The lock here protects the get_variable call, the conditional
-+ * set_variable call, and removal of the variable from the efivars
-+ * list (in the case of an authenticated delete).
-+ */
-+ spin_lock(&efivars->lock);
-+
- status = efivars->ops->set_variable(var->var.VariableName,
- &var->var.VendorGuid,
- attributes, datasize,
- data);
-
-- switch (status) {
-- case EFI_SUCCESS:
-- break;
-- case EFI_INVALID_PARAMETER:
-- count = -EINVAL;
-- goto out;
-- case EFI_OUT_OF_RESOURCES:
-- count = -ENOSPC;
-- goto out;
-- case EFI_DEVICE_ERROR:
-- count = -EIO;
-- goto out;
-- case EFI_WRITE_PROTECTED:
-- count = -EROFS;
-- goto out;
-- case EFI_SECURITY_VIOLATION:
-- count = -EACCES;
-- goto out;
-- case EFI_NOT_FOUND:
-- count = -ENOENT;
-- goto out;
-- default:
-- count = -EINVAL;
-- goto out;
-+ if (status != EFI_SUCCESS) {
-+ spin_unlock(&efivars->lock);
-+ kfree(data);
-+
-+ switch (status) {
-+ case EFI_INVALID_PARAMETER:
-+ count = -EINVAL;
-+ break;
-+ case EFI_OUT_OF_RESOURCES:
-+ count = -ENOSPC;
-+ break;
-+ case EFI_DEVICE_ERROR:
-+ count = -EIO;
-+ break;
-+ case EFI_WRITE_PROTECTED:
-+ count = -EROFS;
-+ break;
-+ case EFI_SECURITY_VIOLATION:
-+ count = -EACCES;
-+ break;
-+ case EFI_NOT_FOUND:
-+ count = -ENOENT;
-+ break;
-+ default:
-+ count = -EINVAL;
-+ }
-+ return count;
- }
-
- /*
-@@ -734,12 +744,12 @@ static ssize_t efivarfs_file_write(struct file *file,
- NULL);
-
- if (status == EFI_BUFFER_TOO_SMALL) {
-+ spin_unlock(&efivars->lock);
- mutex_lock(&inode->i_mutex);
- i_size_write(inode, newdatasize + sizeof(attributes));
- mutex_unlock(&inode->i_mutex);
-
- } else if (status == EFI_NOT_FOUND) {
-- spin_lock(&efivars->lock);
- list_del(&var->list);
- spin_unlock(&efivars->lock);
- efivar_unregister(var);
-@@ -747,6 +757,7 @@ static ssize_t efivarfs_file_write(struct file *file,
- dput(file->f_dentry);
-
- } else {
-+ spin_unlock(&efivars->lock);
- pr_warn("efivarfs: inconsistent EFI variable implementation? "
- "status = %lx\n", status);
- }
-@@ -768,9 +779,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- void *data;
- ssize_t size = 0;
-
-+ spin_lock(&efivars->lock);
- status = efivars->ops->get_variable(var->var.VariableName,
- &var->var.VendorGuid,
- &attributes, &datasize, NULL);
-+ spin_unlock(&efivars->lock);
-
- if (status != EFI_BUFFER_TOO_SMALL)
- return 0;
-@@ -780,10 +793,13 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- if (!data)
- return 0;
-
-+ spin_lock(&efivars->lock);
- status = efivars->ops->get_variable(var->var.VariableName,
- &var->var.VendorGuid,
- &attributes, &datasize,
- (data + 4));
-+ spin_unlock(&efivars->lock);
-+
- if (status != EFI_SUCCESS)
- goto out_free;
-
-@@ -1004,11 +1020,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- /* copied by the above to local storage in the dentry. */
- kfree(name);
-
-+ spin_lock(&efivars->lock);
- efivars->ops->get_variable(entry->var.VariableName,
- &entry->var.VendorGuid,
- &entry->var.Attributes,
- &size,
- NULL);
-+ spin_unlock(&efivars->lock);
-
- mutex_lock(&inode->i_mutex);
- inode->i_private = entry;
---
-1.7.12.1
-
-
-From 90a462e9cf439a1987e0f9434d1f615addcc1970 Mon Sep 17 00:00:00 2001
-From: Jeremy Kerr <jeremy.kerr@canonical.com>
-Date: Fri, 19 Oct 2012 15:16:45 +0800
-Subject: [PATCH 11/17] efi: Clarify GUID length calculations
-
-At present, the handling of GUIDs in efivar file names isn't consistent.
-We use GUID_LEN in some places, and 38 in others (GUID_LEN plus
-separator), and implicitly use the presence of the trailing NUL.
-
-This change removes the trailing NUL from GUID_LEN, so that we're
-explicitly adding it when required. We also replace magic numbers
-with GUID_LEN, and clarify the comments where appropriate.
-
-We also fix the allocation size in efivar_create_sysfs_entry, where
-we're allocating one byte too much, due to counting the trailing NUL
-twice - once when calculating short_name_size, and once in the kzalloc.
-
-Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 33 +++++++++++++++++++++++++--------
- 1 file changed, 25 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index d478c56..a93e401 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -95,7 +95,12 @@ MODULE_LICENSE("GPL");
- MODULE_VERSION(EFIVARS_VERSION);
-
- #define DUMP_NAME_LEN 52
--#define GUID_LEN 37
-+
-+/*
-+ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
-+ * not including trailing NUL
-+ */
-+#define GUID_LEN 36
-
- /*
- * The maximum size of VariableName + Data = 1024
-@@ -887,7 +892,11 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
- struct efivar_entry *var;
- int namelen, i = 0, err = 0;
-
-- if (dentry->d_name.len < 38)
-+ /*
-+ * We need a GUID, plus at least one letter for the variable name,
-+ * plus the '-' separator
-+ */
-+ if (dentry->d_name.len < GUID_LEN + 2)
- return -EINVAL;
-
- inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
-@@ -900,7 +909,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
- goto out;
- }
-
-- namelen = dentry->d_name.len - GUID_LEN;
-+ /* length of the variable name itself: remove GUID and separator */
-+ namelen = dentry->d_name.len - GUID_LEN - 1;
-
- efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
- &var->var.VendorGuid);
-@@ -994,8 +1004,8 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
-
- len = utf16_strlen(entry->var.VariableName);
-
-- /* GUID plus trailing NULL */
-- name = kmalloc(len + 38, GFP_ATOMIC);
-+ /* name, plus '-', plus GUID, plus NUL*/
-+ name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
- if (!name)
- goto fail;
-
-@@ -1006,7 +1016,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
-
- efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);
-
-- name[len+GUID_LEN] = '\0';
-+ name[len+GUID_LEN+1] = '\0';
-
- inode = efivarfs_get_inode(efivarfs_sb, root->d_inode,
- S_IFREG | 0644, 0);
-@@ -1435,11 +1445,18 @@ efivar_create_sysfs_entry(struct efivars *efivars,
- efi_char16_t *variable_name,
- efi_guid_t *vendor_guid)
- {
-- int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
-+ int i, short_name_size;
- char *short_name;
- struct efivar_entry *new_efivar;
-
-- short_name = kzalloc(short_name_size + 1, GFP_KERNEL);
-+ /*
-+ * Length of the variable bytes in ASCII, plus the '-' separator,
-+ * plus the GUID, plus trailing NUL
-+ */
-+ short_name_size = variable_name_size / sizeof(efi_char16_t)
-+ + 1 + GUID_LEN + 1;
-+
-+ short_name = kzalloc(short_name_size, GFP_KERNEL);
- new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
-
- if (!short_name || !new_efivar) {
---
-1.7.12.1
-
-
-From ecbf90823d85ebb41e68e6be01f476862d184825 Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Tue, 16 Oct 2012 15:58:07 +0100
-Subject: [PATCH 12/17] efivarfs: Return an error if we fail to read a
- variable
-
-Instead of always returning 0 in efivarfs_file_read(), even when we
-fail to successfully read the variable, convert the EFI status to
-something meaningful and return that to the caller. This way the user
-will have some hint as to why the read failed.
-
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 62 +++++++++++++++++++++++++++-------------------
- 1 file changed, 36 insertions(+), 26 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index a93e401..277e426 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -653,6 +653,36 @@ static int efivarfs_file_open(struct inode *inode, struct file *file)
- return 0;
- }
-
-+static int efi_status_to_err(efi_status_t status)
-+{
-+ int err;
-+
-+ switch (status) {
-+ case EFI_INVALID_PARAMETER:
-+ err = -EINVAL;
-+ break;
-+ case EFI_OUT_OF_RESOURCES:
-+ err = -ENOSPC;
-+ break;
-+ case EFI_DEVICE_ERROR:
-+ err = -EIO;
-+ break;
-+ case EFI_WRITE_PROTECTED:
-+ err = -EROFS;
-+ break;
-+ case EFI_SECURITY_VIOLATION:
-+ err = -EACCES;
-+ break;
-+ case EFI_NOT_FOUND:
-+ err = -ENOENT;
-+ break;
-+ default:
-+ err = -EINVAL;
-+ }
-+
-+ return err;
-+}
-+
- static ssize_t efivarfs_file_write(struct file *file,
- const char __user *userbuf, size_t count, loff_t *ppos)
- {
-@@ -711,29 +741,7 @@ static ssize_t efivarfs_file_write(struct file *file,
- spin_unlock(&efivars->lock);
- kfree(data);
-
-- switch (status) {
-- case EFI_INVALID_PARAMETER:
-- count = -EINVAL;
-- break;
-- case EFI_OUT_OF_RESOURCES:
-- count = -ENOSPC;
-- break;
-- case EFI_DEVICE_ERROR:
-- count = -EIO;
-- break;
-- case EFI_WRITE_PROTECTED:
-- count = -EROFS;
-- break;
-- case EFI_SECURITY_VIOLATION:
-- count = -EACCES;
-- break;
-- case EFI_NOT_FOUND:
-- count = -ENOENT;
-- break;
-- default:
-- count = -EINVAL;
-- }
-- return count;
-+ return efi_status_to_err(status);
- }
-
- /*
-@@ -791,12 +799,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- spin_unlock(&efivars->lock);
-
- if (status != EFI_BUFFER_TOO_SMALL)
-- return 0;
-+ return efi_status_to_err(status);
-
- data = kmalloc(datasize + 4, GFP_KERNEL);
-
- if (!data)
-- return 0;
-+ return -ENOMEM;
-
- spin_lock(&efivars->lock);
- status = efivars->ops->get_variable(var->var.VariableName,
-@@ -805,8 +813,10 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- (data + 4));
- spin_unlock(&efivars->lock);
-
-- if (status != EFI_SUCCESS)
-+ if (status != EFI_SUCCESS) {
-+ size = efi_status_to_err(status);
- goto out_free;
-+ }
-
- memcpy(data, &attributes, 4);
- size = simple_read_from_buffer(userbuf, count, ppos,
---
-1.7.12.1
-
-
-From 39210330739b943856ff21b29b4a0804f4e8349f Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Mon, 22 Oct 2012 15:23:29 +0100
-Subject: [PATCH 13/17] efivarfs: Replace magic number with sizeof(attributes)
-
-Seeing "+ 4" littered throughout the functions gets a bit
-confusing. Use "sizeof(attributes)" which clearly explains what
-quantity we're adding.
-
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 277e426..2c04434 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -801,7 +801,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- if (status != EFI_BUFFER_TOO_SMALL)
- return efi_status_to_err(status);
-
-- data = kmalloc(datasize + 4, GFP_KERNEL);
-+ data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
-
- if (!data)
- return -ENOMEM;
-@@ -810,7 +810,7 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- status = efivars->ops->get_variable(var->var.VariableName,
- &var->var.VendorGuid,
- &attributes, &datasize,
-- (data + 4));
-+ (data + sizeof(attributes)));
- spin_unlock(&efivars->lock);
-
- if (status != EFI_SUCCESS) {
-@@ -818,9 +818,9 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
- goto out_free;
- }
-
-- memcpy(data, &attributes, 4);
-+ memcpy(data, &attributes, sizeof(attributes));
- size = simple_read_from_buffer(userbuf, count, ppos,
-- data, datasize + 4);
-+ data, datasize + sizeof(attributes));
- out_free:
- kfree(data);
-
---
-1.7.12.1
-
-
-From 5555f0af6294b3675a95a06da23101150644936d Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Mon, 22 Oct 2012 15:51:45 +0100
-Subject: [PATCH 14/17] efivarfs: Add unique magic number
-
-Using pstore's superblock magic number is no doubt going to cause
-problems in the future. Give efivarfs its own magic number.
-
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 2 +-
- include/uapi/linux/magic.h | 1 +
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 2c04434..3b0cf9a 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -991,7 +991,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-- sb->s_magic = PSTOREFS_MAGIC;
-+ sb->s_magic = EFIVARFS_MAGIC;
- sb->s_op = &efivarfs_ops;
- sb->s_time_gran = 1;
-
-diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
-index e15192c..12f68c7 100644
---- a/include/uapi/linux/magic.h
-+++ b/include/uapi/linux/magic.h
-@@ -27,6 +27,7 @@
- #define ISOFS_SUPER_MAGIC 0x9660
- #define JFFS2_SUPER_MAGIC 0x72b6
- #define PSTOREFS_MAGIC 0x6165676C
-+#define EFIVARFS_MAGIC 0xde5e81e4
-
- #define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */
- #define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */
---
-1.7.12.1
-
-
-From a42845c67f2386b164d0c5d8220838d7faf5a409 Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Tue, 23 Oct 2012 12:35:43 +0100
-Subject: [PATCH 15/17] efivarfs: Make 'datasize' unsigned long
-
-There's no reason to declare 'datasize' as an int, since the majority
-of the functions it's passed to expect an unsigned long anyway. Plus,
-this way we avoid any sign problems during arithmetic.
-
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 3b0cf9a..6a858d1 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -692,7 +692,7 @@ static ssize_t efivarfs_file_write(struct file *file,
- void *data;
- u32 attributes;
- struct inode *inode = file->f_mapping->host;
-- int datasize = count - sizeof(attributes);
-+ unsigned long datasize = count - sizeof(attributes);
- unsigned long newdatasize;
-
- if (count < sizeof(attributes))
---
-1.7.12.1
-
-
-From a268bdf6d7ce623ea4bdfcf39aa52ed3fbfdfd65 Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Tue, 23 Oct 2012 12:41:03 +0100
-Subject: [PATCH 16/17] efivarfs: Return a consistent error when
- efivarfs_get_inode() fails
-
-Instead of returning -ENOSPC if efivarfs_get_inode() fails we should
-be returning -ENOMEM, since running out of memory is the only reason
-it can fail. Furthermore, that's the error value used everywhere else
-in this file. It's also less likely to confuse users that hit this
-error case.
-
-Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 6a858d1..58cec62 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -911,7 +911,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
-
- inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
- if (!inode)
-- return -ENOSPC;
-+ return -ENOMEM;
-
- var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
- if (!var) {
---
-1.7.12.1
-
-
-From 9c3136c987175b179c0aa725d76cda156894f918 Mon Sep 17 00:00:00 2001
-From: Matt Fleming <matt.fleming@intel.com>
-Date: Fri, 26 Oct 2012 12:18:53 +0100
-Subject: [PATCH 17/17] efivarfs: Fix return value of efivarfs_file_write()
-
-We're stuffing a variable of type size_t (unsigned) into a ssize_t
-(signed) which, even though both types should be the same number of
-bits, it's just asking for sign issues to be introduced.
-
-Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
-Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
-Signed-off-by: Matt Fleming <matt.fleming@intel.com>
----
- drivers/firmware/efivars.c | 13 ++++++++-----
- 1 file changed, 8 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 58cec62..9ac9340 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -694,6 +694,7 @@ static ssize_t efivarfs_file_write(struct file *file,
- struct inode *inode = file->f_mapping->host;
- unsigned long datasize = count - sizeof(attributes);
- unsigned long newdatasize;
-+ ssize_t bytes = 0;
-
- if (count < sizeof(attributes))
- return -EINVAL;
-@@ -706,22 +707,22 @@ static ssize_t efivarfs_file_write(struct file *file,
- efivars = var->efivars;
-
- if (copy_from_user(&attributes, userbuf, sizeof(attributes))) {
-- count = -EFAULT;
-+ bytes = -EFAULT;
- goto out;
- }
-
- if (attributes & ~(EFI_VARIABLE_MASK)) {
-- count = -EINVAL;
-+ bytes = -EINVAL;
- goto out;
- }
-
- if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
-- count = -EFAULT;
-+ bytes = -EFAULT;
- goto out;
- }
-
- if (validate_var(&var->var, data, datasize) == false) {
-- count = -EINVAL;
-+ bytes = -EINVAL;
- goto out;
- }
-
-@@ -744,6 +745,8 @@ static ssize_t efivarfs_file_write(struct file *file,
- return efi_status_to_err(status);
- }
-
-+ bytes = count;
-+
- /*
- * Writing to the variable may have caused a change in size (which
- * could either be an append or an overwrite), or the variable to be
-@@ -778,7 +781,7 @@ static ssize_t efivarfs_file_write(struct file *file,
- out:
- kfree(data);
-
-- return count;
-+ return bytes;
- }
-
- static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
---
-1.7.12.1
-