Example #1
0
static ssize_t
unparse_media_path(char *buffer, size_t buffer_size, EFI_DEVICE_PATH *path)
{

	CDROM_DEVICE_PATH *cdrom = (CDROM_DEVICE_PATH *)path;
	MEDIA_PROTOCOL_DEVICE_PATH *media = (MEDIA_PROTOCOL_DEVICE_PATH *)path;
	FILE_PATH_DEVICE_PATH *file = (FILE_PATH_DEVICE_PATH *)path;
	char *text_guid;
	char file_name[80];
	memset(file_name, 0, sizeof(file_name));
	char a[16], b[16], c[16];
	int rc;

	switch (path->subtype) {
	case 1:
		return unparse_media_hard_drive_path(buffer, buffer_size, path);
	case 2:
		return snprintf(buffer, buffer_size,
				"CD-ROM(%x,%" PRIx64 ",%" PRIx64 ")",
				get(a, cdrom->boot_entry),
				get(b, cdrom->start), get(c, cdrom->size));
	case 3:
		return unparse_vendor_path(buffer, buffer_size, NULL,
				(VENDOR_DEVICE_PATH *)path);
	case 4:
		efichar_to_char(file_name, file->path_name, 80);
		return snprintf(buffer, buffer_size, "File(%s)", file_name);
	case 5:
		rc = efi_guid_to_str(&media->guid, &text_guid);
		if (rc < 0)
			return rc;
		rc = snprintf(buffer, buffer_size, "Media(%s)", text_guid);
		free(text_guid);
		return rc;
	case 6:
		rc = efi_guid_to_str(&media->guid, &text_guid);
		if (rc < 0)
			return rc;
		rc = snprintf(buffer, buffer_size, "FvFile(%s)", text_guid);
		free(text_guid);
		return rc > 0 ? rc + 1 : rc;
	case 7:
		rc = efi_guid_to_str(&media->guid, &text_guid);
		if (rc < 0)
			return rc;
		rc = snprintf(buffer, buffer_size, "FvVol(%s)", text_guid);
		free(text_guid);
		return rc > 0 ? rc + 1 : rc;
	}
	return 0;
}
Example #2
0
File: guid.c Project: btian1/efivar
efi_guid_to_name(efi_guid_t *guid, char **name)
{
	struct guidname *result;
	int rc = _get_common_guidname(guid, &result);
	if (rc >= 0) {
		*name = strndup(result->name, sizeof (result->name) -1);
		return *name ? (int)strlen(*name) : -1;
	}
	return efi_guid_to_str(guid, name);
}
Example #3
0
static int
put_info(update_info *info)
{
	efi_guid_t varguid = FWUPDATE_GUID;
	ssize_t dps, is;
	char *guidstr = NULL;
	char *varname;
	int error;
	int rc;

	rc = efi_guid_to_str(&info->guid, &guidstr);
	if (rc < 0) {
err:
		return rc;
	}
	guidstr = onstack(guidstr, strlen(guidstr)+1);

	rc = asprintf(&varname, "fwupdate-%s-%"PRIx64, guidstr, info->hw_inst);
	if (rc < 0)
		goto err;
	varname = onstack(varname, strlen(varname)+1);

	dps = efidp_size((efidp)info->dp_ptr);
	/* make sure dps is at least big enough to have our structure */
	if (dps < 0 || (size_t)dps < sizeof(*info)) {
		errno = EINVAL;
		return -1;
	}
	/* Make sure sizeof(*info) + dps won't integer overflow */
	if ((size_t)dps > SSIZE_MAX - sizeof(*info)) {
		errno = EOVERFLOW;
		return -1;
	}

	is = sizeof(*info) + dps - sizeof(info->dp_ptr);

	update_info *info2;
	info2 = malloc(is);
	if (!info2)
		return -1;

	memcpy(info2, info, sizeof(*info));
	memcpy(info2->dp, info->dp_ptr, dps);

	uint32_t attributes = EFI_VARIABLE_NON_VOLATILE
			      | EFI_VARIABLE_BOOTSERVICE_ACCESS
			      | EFI_VARIABLE_RUNTIME_ACCESS;
	rc = efi_set_variable(varguid, varname, (uint8_t *)info2,
			      is, attributes, 0600);
	error = errno;
	free(info2);
	errno = error;
	return rc;
}
Example #4
0
static void
pretty_guid(efi_guid_t *guid, char **gname)
{
	char *pretty = NULL;

	if (gflag)
		efi_guid_to_name(guid, &pretty);

	if (pretty == NULL)
		efi_guid_to_str(guid, gname);
	else
		*gname = pretty;
}
/**
 * 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 i, short_name_size;
	char *short_name;
	unsigned long variable_name_size;
	efi_char16_t *variable_name;
	int ret;

	variable_name = new_var->var.VariableName;
	variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);

	/*
	 * 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 + EFI_VARIABLE_GUID_LEN + 1;

	short_name = kzalloc(short_name_size, GFP_KERNEL);

	if (!short_name)
		return -ENOMEM;

	/* Convert Unicode to normal chars (assume top bits are 0),
	   ala UTF-8 */
	for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
		short_name[i] = variable_name[i] & 0xFF;
	}
	/* This is ugly, but necessary to separate one vendor's
	   private variables from another's.         */

	*(short_name + strlen(short_name)) = '-';
	efi_guid_to_str(&new_var->var.VendorGuid,
			 short_name + strlen(short_name));

	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;
}
static ssize_t
efivar_guid_read(struct efivar_entry *entry, char *buf)
{
    struct efi_variable *var = &entry->var;
    char *str = buf;

    if (!entry || !buf)
        return 0;

    efi_guid_to_str(&var->VendorGuid, str);
    str += strlen(str);
    str += sprintf(str, "\n");

    return str - buf;
}
/**
 * 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;
}
Example #8
0
static ssize_t
unparse_media_hard_drive_path(char *buffer, size_t buffer_size,
				EFI_DEVICE_PATH *path)
{
	HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *)path;
	char text_uuid[40], *sig=text_uuid;
	char a[16], b[16], c[16];
	int rc = 0;

	switch (hd->signature_type) {
	case 0x00:
		rc = sprintf(sig, "None");
		if (rc < 0)
			return -1;
		break;
	case 0x01:
		rc = sprintf(sig, "%08x", *(uint32_t *)memcpy(a, &hd->signature,
						 sizeof(hd->signature)));
		if (rc < 0)
			return -1;
		break;
	case 0x02: /* GPT */
		rc = efi_guid_to_str((efi_guid_t *)hd->signature, &sig);
		if (rc < 0)
			return rc;
		break;
	default:
		return 0;
	}

	rc = snprintf(buffer, buffer_size, "HD(%x,%" PRIx64 ",%" PRIx64 ",%s)",
		       get(a, hd->part_num),
		       get(b, hd->start),
		       get(c, hd->size),
		       sig);
	if (hd->signature_type == 0x02)
		free(sig);
	return rc;
}
Example #9
0
static ssize_t
unparse_vendor_path(char *buffer, size_t buffer_size, char *prefix,
	VENDOR_DEVICE_PATH *path)
{
	char *text_guid;
	unsigned char *q = (uint8_t *)path + 20;
	int rc;

	size_t needed;
	off_t buf_offset = 0;

	rc = efi_guid_to_str(&path->vendor_guid, &text_guid);
	if (rc < 0)
		return -1;

	needed = snprintf(buffer, buffer_size, "%s(%s,",
			prefix ? prefix : "Vendor", text_guid);
	free(text_guid);
	if (needed < 0)
		return -1;
	buf_offset += needed;

	needed = unparse_raw(buffer + buf_offset,
		buffer_size == 0 ? 0 : buffer_size - buf_offset,
		q, path->length - 20);
	if (needed < 0)
		return -1;
	buf_offset += needed;

	needed = snprintf(buffer + buf_offset,
		buffer_size == 0 ? 0 : buffer_size - buf_offset,
		")");
	if (needed < 0)
		return -1;
	buf_offset += needed;

	return buf_offset;
}
Example #10
0
static fwup_resource *
fu_provider_uefi_find (fwup_resource_iter *iter, const gchar *guid_str, GError **error)
{
	efi_guid_t *guid_raw;
	fwup_resource *re_matched = NULL;
	fwup_resource *re = NULL;
	g_autofree gchar *guid_str_tmp = NULL;

	/* get the hardware we're referencing */
	guid_str_tmp = g_strdup ("00000000-0000-0000-0000-000000000000");
	while (fwup_resource_iter_next (iter, &re) > 0) {

		/* convert to strings */
		fwup_get_guid (re, &guid_raw);
		if (efi_guid_to_str (guid_raw, &guid_str_tmp) < 0) {
			g_warning ("failed to convert guid to string");
			continue;
		}

		/* FIXME: also match hardware_instance too */
		if (g_strcmp0 (guid_str, guid_str_tmp) == 0) {
			re_matched = re;
			break;
		}
	}

	/* paradoxically, no hardware matched */
	if (re_matched == NULL) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_NOT_SUPPORTED,
			     "No UEFI firmware matched %s",
			     guid_str);
	}

	return re_matched;
}
Example #11
0
static int
get_info(efi_guid_t *guid, uint64_t hw_inst, update_info **info)
{
	efi_guid_t varguid = FWUPDATE_GUID;
	char *varname = NULL;
	char *guidstr = NULL;
	int rc;
	update_info *local;
	int error;

	rc = efi_guid_to_str(guid, &guidstr);
	if (rc < 0)
		return -1;
	guidstr = onstack(guidstr, strlen(guidstr)+1);

	rc = asprintf(&varname, "fwupdate-%s-%"PRIx64, guidstr, hw_inst);
	if (rc < 0)
		return -1;
	varname = onstack(varname, strlen(varname)+1);

	uint8_t *data = NULL;
	size_t data_size = 0;
	uint32_t attributes;

	rc = efi_get_variable(varguid, varname, &data, &data_size, &attributes);
	if (rc < 0) {
		if (errno != ENOENT)
			return -1;
		local = calloc(1, sizeof (*local));
		if (!local)
			return -1;

		local->update_info_version = UPDATE_INFO_VERSION;
		local->guid = *guid;
		local->hw_inst = hw_inst;

		local->dp_ptr = calloc(1, 1024);
		if (!local->dp_ptr) {
alloc_err:
			error = errno;
			free_info(local);
			errno = error;
			return -1;
		}

		ssize_t sz;
		sz = efidp_make_end_entire((uint8_t *)local->dp_ptr, 1024);
		if (sz < 0) {
			rc = sz;
			goto alloc_err;
		}
		*info = local;
		return 0;
	}

	/* If our size is wrong, or our data is otherwise bad, try to delete
	 * the variable and create a new one. */
	if (data_size < sizeof (*local) || !data) {
		if (data)
			free(data);
get_err:
		rc = efi_del_variable(varguid, varname);
		if (rc < 0)
			return -1;
		return get_info(guid, hw_inst, info);
	}
	local = (update_info *)data;

	if (local->update_info_version != UPDATE_INFO_VERSION)
		goto get_err;

	ssize_t sz = efidp_size((efidp)local->dp);
	if (sz < 0) {
		free(data);
		errno = EINVAL;
		return -1;
	}

	efidp_header *dp = malloc((size_t)sz);
	if (!dp) {
		free(data);
		errno = ENOMEM;
		return -1;
	}

	memcpy(dp, local->dp, (size_t)sz);
	local->dp_ptr = dp;

	*info = local;
	return 0;
}
Example #12
0
File: super.c Project: Abioy/kasan
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, i;
	int err = -ENOMEM;

	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_strlen(entry->var.VariableName);

	/* name, plus '-', plus GUID, plus NUL*/
	name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
	if (!name)
		goto fail;

	for (i = 0; i < len; i++)
		name[i] = entry->var.VariableName[i] & 0xFF;

	name[len] = '-';

	efi_guid_to_str(&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);
	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;
}
Example #13
0
static gboolean
fu_provider_uefi_coldplug (FuProvider *provider, GError **error)
{
	AsVersionParseFlag parse_flags;
	g_autofree gchar *display_name = NULL;
	fwup_resource *re;
	gint supported;
	g_autofree gchar *guid = NULL;
	g_autoptr(FuDevice) dev = NULL;
	g_autoptr(fwup_resource_iter) iter = NULL;

	/* supported = 0 : ESRT unspported
	   supported = 1 : unlocked, ESRT supported
	   supported = 2 : it is locked but can be unlocked to support ESRT
	   supported = 3 : it is locked, has been marked to be unlocked on next boot
			   calling unlock again is OK.
	 */
	supported = fwup_supported ();
	if (supported == 0) {
		g_set_error_literal (error,
				     FWUPD_ERROR,
				     FWUPD_ERROR_NOT_SUPPORTED,
				     "UEFI firmware updating not supported");
		return FALSE;
	}

	if (supported >= 2) {
		dev = fu_device_new ();
		fu_device_set_id (dev, "UEFI-dummy-dev0");
		fu_device_add_guid (dev, "2d47f29b-83a2-4f31-a2e8-63474f4d4c2e");
		fu_device_set_version (dev, "0");
		fu_device_add_flag (dev, FU_DEVICE_FLAG_ALLOW_ONLINE);
		fu_device_add_flag (dev, FU_DEVICE_FLAG_LOCKED);
		fu_provider_device_add (provider, dev);
		return TRUE;
	}

	/* this can fail if we have no permissions */
	if (fwup_resource_iter_create (&iter) < 0) {
		g_set_error_literal (error,
				     FWUPD_ERROR,
				     FWUPD_ERROR_INTERNAL,
				     "Cannot create fwup iter");
		return FALSE;
	}

	/* set Display Name to the system for all capsules */
	g_file_get_contents ("/sys/class/dmi/id/product_name",
				  &display_name, NULL, NULL);
	if (display_name != NULL)
		g_strchomp (display_name);

	/* add each device */
	guid = g_strdup ("00000000-0000-0000-0000-000000000000");
	parse_flags = fu_provider_uefi_get_version_format ();
	while (fwup_resource_iter_next (iter, &re) > 0) {
		efi_guid_t *guid_raw;
		guint32 version_raw;
		guint64 hardware_instance = 0;	/* FIXME */
		g_autofree gchar *id = NULL;
		g_autofree gchar *version = NULL;
		g_autofree gchar *version_lowest = NULL;

		/* convert to strings */
		fwup_get_guid (re, &guid_raw);
		if (efi_guid_to_str (guid_raw, &guid) < 0) {
			g_warning ("failed to convert guid to string");
			continue;
		}
		fwup_get_fw_version(re, &version_raw);
		version = as_utils_version_from_uint32 (version_raw,
							parse_flags);
		id = g_strdup_printf ("UEFI-%s-dev%" G_GUINT64_FORMAT,
				      guid, hardware_instance);

		dev = fu_device_new ();
		fu_device_set_id (dev, id);
		fu_device_add_guid (dev, guid);
		fu_device_set_version (dev, version);
		if (display_name != NULL)
			fu_device_set_name(dev, display_name);
		fwup_get_lowest_supported_fw_version (re, &version_raw);
		if (version_raw != 0) {
			version_lowest = as_utils_version_from_uint32 (version_raw,
								       parse_flags);
			fu_device_set_version_lowest (dev, version_lowest);
		}
		fu_device_add_flag (dev, FU_DEVICE_FLAG_INTERNAL);
		fu_device_add_flag (dev, FU_DEVICE_FLAG_ALLOW_OFFLINE);
		fu_device_add_flag (dev, FU_DEVICE_FLAG_REQUIRE_AC);
		fu_provider_device_add (provider, dev);
	}
	return TRUE;
}