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; unsigned long datasize = 0; u32 attributes; void *data; ssize_t size = 0; int err; while (!__ratelimit(&file->f_cred->user->ratelimit)) { if (!msleep_interruptible(50)) return -EINTR; } err = efivar_entry_size(var, &datasize); /* * efivarfs represents uncommitted variables with * zero-length files. Reading them should return EOF. */ if (err == -ENOENT) return 0; else if (err) return err; data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); if (!data) return -ENOMEM; size = efivar_entry_get(var, &attributes, &datasize, data + sizeof(attributes)); if (size) goto out_free; memcpy(data, &attributes, sizeof(attributes)); size = simple_read_from_buffer(userbuf, count, ppos, data, datasize + sizeof(attributes)); out_free: kfree(data); return size; }
static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor, unsigned long name_size, void *data) { struct super_block *sb = (struct super_block *)data; struct efivar_entry *entry; struct inode *inode = NULL; struct dentry *dentry, *root = sb->s_root; unsigned long size = 0; char *name; int len; int err = -ENOMEM; bool is_removable = false; entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return err; memcpy(entry->var.VariableName, name16, name_size); memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t)); len = ucs2_utf8size(entry->var.VariableName); /* name, plus '-', plus GUID, plus NUL*/ name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL); if (!name) goto fail; ucs2_as_utf8(name, entry->var.VariableName, len); if (efivar_variable_is_removable(entry->var.VendorGuid, name, len)) is_removable = true; name[len] = '-'; efi_guid_unparse(&entry->var.VendorGuid, name + len + 1); name[len + EFI_VARIABLE_GUID_LEN+1] = '\0'; inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0, is_removable); if (!inode) goto fail_name; dentry = efivarfs_alloc_dentry(root, name); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); goto fail_inode; } /* copied by the above to local storage in the dentry. */ kfree(name); efivar_entry_size(entry, &size); efivar_entry_add(entry, &efivarfs_list); mutex_lock(&inode->i_mutex); inode->i_private = entry; i_size_write(inode, size + sizeof(entry->var.Attributes)); mutex_unlock(&inode->i_mutex); d_add(dentry, inode); return 0; fail_inode: iput(inode); fail_name: kfree(name); fail: kfree(entry); return err; }