Exemple #1
0
bool
efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
		unsigned long data_size)
{
	int i;
	unsigned long utf8_size;
	u8 *utf8_name;

	utf8_size = ucs2_utf8size(var_name);
	utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
	if (!utf8_name)
		return false;

	ucs2_as_utf8(utf8_name, var_name, utf8_size);
	utf8_name[utf8_size] = '\0';

	for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
		const char *name = variable_validate[i].name;
		int match = 0;

		if (efi_guidcmp(vendor, variable_validate[i].vendor))
			continue;

		if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
			if (variable_validate[i].validate == NULL)
				break;
			kfree(utf8_name);
			return variable_validate[i].validate(var_name, match,
							     data, data_size);
		}
	}
	kfree(utf8_name);
	return true;
}
/**
 * efivar_create_sysfs_entry - create a new entry in sysfs
 * @new_var: efivar entry to create
 *
 * Returns 0 on success, negative error code on failure
 */
static int
efivar_create_sysfs_entry(struct efivar_entry *new_var)
{
    int short_name_size;
    char *short_name;
    unsigned long utf8_name_size;
    efi_char16_t *variable_name = new_var->var.VariableName;
    int ret;

    /*
     * Length of the variable bytes in UTF8, plus the '-' separator,
     * plus the GUID, plus trailing NUL
     */
    utf8_name_size = ucs2_utf8size(variable_name);
    short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;

    short_name = kmalloc(short_name_size, GFP_KERNEL);
    if (!short_name)
        return -ENOMEM;

    ucs2_as_utf8(short_name, variable_name, short_name_size);

    /* This is ugly, but necessary to separate one vendor's
       private variables from another's.         */
    short_name[utf8_name_size] = '-';
    efi_guid_to_str(&new_var->var.VendorGuid,
                    short_name + utf8_name_size + 1);

    new_var->kobj.kset = efivars_kset;

    ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
                               NULL, "%s", short_name);
    kfree(short_name);
    if (ret)
        return ret;

    kobject_uevent(&new_var->kobj, KOBJ_ADD);
    efivar_entry_add(new_var, &efivar_sysfs_list);

    return 0;
}
Exemple #3
0
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;
}