예제 #1
0
/**
 * fu_provider_udev_verify:
 **/
static gboolean
fu_provider_udev_verify (FuProvider *provider,
			 FuDevice *device,
			 FuProviderVerifyFlags flags,
			 GError **error)
{
	const gchar *rom_fn;
	g_autoptr(GFile) file = NULL;
	g_autoptr(FuRom) rom = NULL;

	/* open the file */
	rom_fn = fu_device_get_metadata (device, "RomFilename");
	if (rom_fn == NULL) {
		g_set_error_literal (error,
				     FWUPD_ERROR,
				     FWUPD_ERROR_INTERNAL,
				     "Unable to read firmware from device");
		return FALSE;
	}
	file = g_file_new_for_path (rom_fn);
	rom = fu_rom_new ();
	if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, error))
		return FALSE;
	fu_device_set_metadata (device, FU_DEVICE_KEY_FIRMWARE_HASH,
				fu_rom_get_checksum (rom));
	return TRUE;
}
예제 #2
0
/**
 * fu_provider_schedule_update:
 **/
static gboolean
fu_provider_schedule_update (FuProvider *provider,
			     FuDevice *device,
			     GBytes *blob_cab,
			     GError **error)
{
	gchar tmpname[] = {"XXXXXX.cap"};
	guint i;
	g_autofree gchar *dirname = NULL;
	g_autofree gchar *filename = NULL;
	g_autoptr(FuDevice) device_tmp = NULL;
	g_autoptr(FuPending) pending = NULL;
	g_autoptr(GFile) file = NULL;

	/* id already exists */
	pending = fu_pending_new ();
	device_tmp = fu_pending_get_device (pending, fu_device_get_id (device), NULL);
	if (device_tmp != NULL) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_ALREADY_PENDING,
			     "%s is already scheduled to be updated",
			     fu_device_get_id (device));
		return FALSE;
	}

	/* create directory */
	dirname = g_build_filename (LOCALSTATEDIR, "lib", "fwupd", NULL);
	file = g_file_new_for_path (dirname);
	if (!g_file_query_exists (file, NULL)) {
		if (!g_file_make_directory_with_parents (file, NULL, error))
			return FALSE;
	}

	/* get a random filename */
	for (i = 0; i < 6; i++)
		tmpname[i] = g_random_int_range ('A', 'Z');
	filename = g_build_filename (dirname, tmpname, NULL);

	/* just copy to the temp file */
	fu_provider_set_status (provider, FWUPD_STATUS_SCHEDULING);
	if (!g_file_set_contents (filename,
				  g_bytes_get_data (blob_cab, NULL),
				  g_bytes_get_size (blob_cab),
				  error))
		return FALSE;

	/* schedule for next boot */
	g_debug ("schedule %s to be installed to %s on next boot",
		 filename, fu_device_get_id (device));
	fu_device_set_metadata (device, FU_DEVICE_KEY_FILENAME_CAB, filename);

	/* add to database */
	if (!fu_pending_add_device (pending, device, error))
		return FALSE;

	/* next boot we run offline */
	return fu_provider_offline_setup (error);
}
예제 #3
0
파일: fu-provider.c 프로젝트: goliate/fwupd
/**
 * fu_provider_device_add:
 **/
void
fu_provider_device_add (FuProvider *provider, FuDevice *device)
{
	g_debug ("emit added: %s", fu_device_get_id (device));
	fu_device_set_metadata (device, FU_DEVICE_KEY_PROVIDER,
				fu_provider_get_name (provider));
	g_signal_emit (provider, signals[SIGNAL_DEVICE_ADDED], 0, device);
}
예제 #4
0
/**
 * fu_provider_device_add:
 **/
void
fu_provider_device_add (FuProvider *provider, FuDevice *device)
{
	g_debug ("emit added from %s: %s",
		 fu_provider_get_name (provider),
		 fu_device_get_id (device));
	fu_device_set_created (device, g_get_real_time () / G_USEC_PER_SEC);
	fu_device_set_metadata (device, FU_DEVICE_KEY_PROVIDER,
				fu_provider_get_name (provider));
	g_signal_emit (provider, signals[SIGNAL_DEVICE_ADDED], 0, device);
}
예제 #5
0
/**
 * fu_provider_get_results:
 **/
gboolean
fu_provider_get_results (FuProvider *provider, FuDevice *device, GError **error)
{
	FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider);
	const gchar *tmp;
	guint i;
	g_autoptr(GError) error_local = NULL;
	g_autoptr(FuDevice) device_pending = NULL;
	g_autoptr(FuPending) pending = NULL;
	const gchar *copy_keys[] = {
		FU_DEVICE_KEY_PENDING_STATE,
		FU_DEVICE_KEY_PENDING_ERROR,
		FU_DEVICE_KEY_VERSION,
		FU_DEVICE_KEY_UPDATE_VERSION,
		NULL };

	/* handled by the provider */
	if (klass->get_results != NULL)
		return klass->get_results (provider, device, error);

	/* handled using the database */
	pending = fu_pending_new ();
	device_pending = fu_pending_get_device (pending,
						fu_device_get_id (device),
						&error_local);
	if (device_pending == NULL) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_NOTHING_TO_DO,
			     "Failed to find %s in pending database: %s",
			     fu_device_get_id (device),
			     error_local->message);
		return FALSE;
	}

	/* copy the important parts from the pending device to the real one */
	tmp = fu_device_get_metadata (device_pending, FU_DEVICE_KEY_PENDING_STATE);
	if (tmp == NULL || g_strcmp0 (tmp, "scheduled") == 0) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_NOTHING_TO_DO,
			     "Device %s has not been updated offline yet",
			     fu_device_get_id (device));
		return FALSE;
	}
	for (i = 0; copy_keys[i] != NULL; i++) {
		tmp = fu_device_get_metadata (device_pending, copy_keys[i]);
		if (tmp != NULL)
			fu_device_set_metadata (device, copy_keys[i], tmp);
	}
	return TRUE;
}
예제 #6
0
int
main (int argc, char *argv[])
{
	gboolean action_enable = FALSE;
	gboolean action_info = FALSE;
	gboolean action_list = FALSE;
	gboolean action_log = FALSE;
	gboolean action_set_debug = FALSE;
	gboolean action_supported = FALSE;
	gboolean action_unset_debug = FALSE;
	gboolean action_version = FALSE;
	gboolean ret;
	gboolean verbose = FALSE;
	g_autofree gchar *apply = FALSE;
	g_autofree gchar *esp_path = NULL;
	g_autoptr(FuUtilPrivate) priv = g_new0 (FuUtilPrivate, 1);
	g_autoptr(GError) error = NULL;
	g_autoptr(GPtrArray) devices = NULL;
	const GOptionEntry options[] = {
		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
			/* TRANSLATORS: command line option */
			_("Show extra debugging information"), NULL },
		{ "version", '\0', 0, G_OPTION_ARG_NONE, &action_version,
			/* TRANSLATORS: command line option */
			_("Display version"), NULL },
		{ "log", 'L', 0, G_OPTION_ARG_NONE, &action_log,
			/* TRANSLATORS: command line option */
			_("Show the debug log from the last attempted update"), NULL },
		{ "list", 'l', 0, G_OPTION_ARG_NONE, &action_list,
			/* TRANSLATORS: command line option */
			_("List supported firmware updates"), NULL },
		{ "supported", 's', 0, G_OPTION_ARG_NONE, &action_supported,
			/* TRANSLATORS: command line option */
			_("Query for firmware update support"), NULL },
		{ "info", 'i', 0, G_OPTION_ARG_NONE, &action_info,
			/* TRANSLATORS: command line option */
			_("Show the information of firmware update status"), NULL },
		{ "enable", 'e', 0, G_OPTION_ARG_NONE, &action_enable,
			/* TRANSLATORS: command line option */
			_("Enable firmware update support on supported systems"), NULL },
		{ "esp-path", 'p', 0, G_OPTION_ARG_STRING, &esp_path,
			/* TRANSLATORS: command line option */
			_("Override the default ESP path"), "PATH" },
		{ "set-debug", 'd', 0, G_OPTION_ARG_NONE, &action_set_debug,
			/* TRANSLATORS: command line option */
			_("Set the debugging flag during update"), NULL },
		{ "unset-debug", 'D', 0, G_OPTION_ARG_NONE, &action_unset_debug,
			/* TRANSLATORS: command line option */
			_("Unset the debugging flag during update"), NULL },
		{ "apply", 'a', 0, G_OPTION_ARG_STRING, &apply,
			/* TRANSLATORS: command line option */
			_("Apply firmware updates"), "GUID" },
		{ NULL}
	};

	setlocale (LC_ALL, "");

	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

	/* ensure root user */
	if (getuid () != 0 || geteuid () != 0)
		/* TRANSLATORS: we're poking around as a power user */
		g_printerr ("%s\n", _("This program may only work correctly as root"));

	/* get a action_list of the commands */
	priv->context = g_option_context_new (NULL);
	g_option_context_set_description (priv->context,
		"This tool allows an administrator to debug UpdateCapsule operation.");

	/* TRANSLATORS: program name */
	g_set_application_name (_("UEFI Firmware Utility"));
	g_option_context_add_main_entries (priv->context, options, NULL);
	ret = g_option_context_parse (priv->context, &argc, &argv, &error);
	if (!ret) {
		/* TRANSLATORS: the user didn't read the man page */
		g_print ("%s: %s\n", _("Failed to parse arguments"),
			 error->message);
		return EXIT_FAILURE;
	}

	/* set verbose? */
	if (verbose) {
		g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
	} else {
		g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
				   fu_util_ignore_cb, NULL);
	}

	/* nothing specified */
	if (!action_enable && !action_info && !action_list && !action_log &&
	    !action_set_debug && !action_supported && !action_unset_debug &&
	    !action_version) {
		g_autofree gchar *tmp = NULL;
		tmp = g_option_context_get_help (priv->context, TRUE, NULL);
		g_printerr ("%s\n\n%s", _("No action specified!"), tmp);
		return EXIT_FAILURE;
	}

	/* action_version first */
	if (action_version)
		g_print ("fwupd version: %s\n", PACKAGE_VERSION);

	/* override the default ESP path */
	if (esp_path != NULL) {
		if (!fu_uefi_check_esp_path (esp_path, &error)) {
			/* TRANSLATORS: ESP is EFI System Partition */
			g_print ("%s: %s\n", _("ESP specified was not valid"),
				 error->message);
			return EXIT_FAILURE;
		}
	} else {
		esp_path = fu_uefi_guess_esp_path ();
		if (esp_path == NULL) {
			g_printerr ("Unable to determine EFI system partition "
				    "location, override using --esp-path\n");
			return EXIT_FAILURE;
		}
	}

	/* check free space */
	if (!fu_uefi_check_esp_free_space (esp_path,
					   FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE,
					   &error)) {
		g_printerr ("Unable to use EFI system partition: %s\n", error->message);
		return EXIT_FAILURE;
	}
	g_debug ("ESP mountpoint set as %s", esp_path);

	/* show the debug action_log from the last attempted update */
	if (action_log) {
		gsize sz = 0;
		g_autofree guint8 *buf = NULL;
		g_autofree guint16 *buf_ucs2 = NULL;
		g_autofree gchar *str = NULL;
		g_autoptr(GError) error_local = NULL;
		if (!fu_uefi_vars_get_data (FU_UEFI_VARS_GUID_FWUPDATE,
					    "FWUPDATE_DEBUG_LOG",
					    &buf, &sz, NULL,
					    &error_local)) {
			g_printerr ("failed: %s\n", error_local->message);
			return EXIT_FAILURE;
		}
		buf_ucs2 = g_new0 (guint16, (sz / 2) + 1);
		memcpy (buf_ucs2, buf, sz);
		str = fu_ucs2_to_uft8 (buf_ucs2, sz / 2);
		g_print ("%s", str);
	}

	if (action_list || action_supported || action_info) {
		g_autoptr(GPtrArray) entries = NULL;
		g_autofree gchar *esrt_path = NULL;
		g_autofree gchar *sysfsfwdir = NULL;
		g_autoptr(GError) error_local = NULL;

		/* get the directory of ESRT entries */
		sysfsfwdir = fu_common_get_path (FU_PATH_KIND_SYSFSDIR_FW);
		esrt_path = g_build_filename (sysfsfwdir, "efi", "esrt", NULL);
		entries = fu_uefi_get_esrt_entry_paths (esrt_path, &error_local);
		if (entries == NULL) {
			g_printerr ("failed: %s\n", error_local->message);
			return EXIT_FAILURE;
		}

		/* add each device */
		devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
		for (guint i = 0; i < entries->len; i++) {
			const gchar *path = g_ptr_array_index (entries, i);
			g_autoptr(GError) error_parse = NULL;
			g_autoptr(FuUefiDevice) dev = fu_uefi_device_new_from_entry (path, &error_parse);
			if (dev == NULL) {
				g_warning ("failed to parse %s: %s",
					   path, error_parse->message);
				continue;
			}
			fu_device_set_metadata (FU_DEVICE (dev), "EspPath", esp_path);
			g_ptr_array_add (devices, g_object_ref (dev));
		}
	}

	/* action_list action_supported firmware updates */
	if (action_list) {
		for (guint i = 0; i < devices->len; i++) {
			FuUefiDevice *dev = g_ptr_array_index (devices, i);
			g_print ("%s type, {%s} action_version %" G_GUINT32_FORMAT " can be updated "
				 "to any action_version above %" G_GUINT32_FORMAT "\n",
				 fu_uefi_device_kind_to_string (fu_uefi_device_get_kind (dev)),
				 fu_uefi_device_get_guid (dev),
				 fu_uefi_device_get_version (dev),
				 fu_uefi_device_get_version_lowest (dev) - 1);
		}
	}

	/* query for firmware update support */
	if (action_supported) {
		if (devices->len > 0) {
			g_print ("%s\n", _("Firmware updates are supported on this machine."));
		} else {
			g_print ("%s\n", _("Firmware updates are not supported on this machine."));
		}
	}

	/* show the information of firmware update status */
	if (action_info) {
		for (guint i = 0; i < devices->len; i++) {
			FuUefiDevice *dev = g_ptr_array_index (devices, i);
			g_autoptr(FuUefiUpdateInfo) info = NULL;
			g_autoptr(GError) error_local = NULL;

			/* load any existing update info */
			info = fu_uefi_device_load_update_info (dev, &error_local);
			if (info == NULL) {
				g_printerr ("failed: %s\n", error_local->message);
				continue;
			}
			g_print ("Information for the update status entry %u:\n", i);
			g_print ("  Information Version: %" G_GUINT32_FORMAT "\n",
				 fu_uefi_update_info_get_version (info));
			g_print ("  Firmware GUID: {%s}\n",
				 fu_uefi_update_info_get_guid (info));
			g_print ("  Capsule Flags: 0x%08" G_GUINT32_FORMAT "x\n",
				 fu_uefi_update_info_get_capsule_flags (info));
			g_print ("  Hardware Instance: %" G_GUINT64_FORMAT "\n",
				 fu_uefi_update_info_get_hw_inst (info));
			g_print ("  Update Status: %s\n",
				 fu_uefi_update_info_status_to_string (fu_uefi_update_info_get_status (info)));
			g_print ("  Capsule File Path: %s\n\n",
				 fu_uefi_update_info_get_capsule_fn (info));
		}
	}

	/* action_enable firmware update support on action_supported systems */
	if (action_enable) {
		g_printerr ("Unsupported, use `fwupdmgr unlock`\n");
		return EXIT_FAILURE;
	}

	/* set the debugging flag during update */
	if (action_set_debug) {
		const guint8 data = 1;
		g_autoptr(GError) error_local = NULL;
		if (!fu_uefi_vars_set_data (FU_UEFI_VARS_GUID_FWUPDATE,
					    "FWUPDATE_VERBOSE",
					    &data, sizeof(data),
					    EFI_VARIABLE_NON_VOLATILE |
					    EFI_VARIABLE_BOOTSERVICE_ACCESS |
					    EFI_VARIABLE_RUNTIME_ACCESS,
					    &error_local)) {
			g_printerr ("failed: %s\n", error_local->message);
			return EXIT_FAILURE;
		}
		g_print ("%s\n", _("Enabled fwupdate debugging"));
	}

	/* unset the debugging flag during update */
	if (action_unset_debug) {
		g_autoptr(GError) error_local = NULL;
		if (!fu_uefi_vars_delete (FU_UEFI_VARS_GUID_FWUPDATE,
					  "FWUPDATE_VERBOSE",
					  &error_local)) {
			g_printerr ("failed: %s\n", error_local->message);
			return EXIT_FAILURE;
		}
		g_print ("%s\n", _("Disabled fwupdate debugging"));
	}

	/* apply firmware updates */
	if (apply != NULL) {
		g_autoptr(FuUefiDevice) dev = fu_uefi_device_new_from_guid (apply);
		g_autoptr(GError) error_local = NULL;
		g_autoptr(GBytes) fw = fu_common_get_contents_bytes (argv[1], &error_local);
		if (fw == NULL) {
			g_printerr ("failed: %s\n", error_local->message);
			return EXIT_FAILURE;
		}
		if (!fu_device_write_firmware (FU_DEVICE (dev), fw, &error_local)) {
			g_printerr ("failed: %s\n", error_local->message);
			return EXIT_FAILURE;
		}
	}

	/* success */
	return EXIT_SUCCESS;
}
예제 #7
0
파일: fu-provider.c 프로젝트: goliate/fwupd
/**
 * fu_provider_schedule_update:
 **/
static gboolean
fu_provider_schedule_update (FuProvider *provider,
			     FuDevice *device,
			     GInputStream *stream,
			     GError **error)
{
	gchar tmpname[] = {"XXXXXX.cap"};
	guint i;
	_cleanup_bytes_unref_ GBytes *fwbin = NULL;
	_cleanup_free_ gchar *dirname = NULL;
	_cleanup_free_ gchar *filename = NULL;
	_cleanup_object_unref_ FuDevice *device_tmp = NULL;
	_cleanup_object_unref_ FuPending *pending = NULL;
	_cleanup_object_unref_ GFile *file = NULL;

	/* id already exists */
	pending = fu_pending_new ();
	device_tmp = fu_pending_get_device (pending, fu_device_get_id (device), NULL);
	if (device_tmp != NULL) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_ALREADY_PENDING,
			     "%s is already scheduled to be updated",
			     fu_device_get_id (device));
		return FALSE;
	}

	/* create directory */
	dirname = g_build_filename (LOCALSTATEDIR, "lib", "fwupd", NULL);
	file = g_file_new_for_path (dirname);
	if (!g_file_query_exists (file, NULL)) {
		if (!g_file_make_directory_with_parents (file, NULL, error))
			return FALSE;
	}

	/* get a random filename */
	for (i = 0; i < 6; i++)
		tmpname[i] = g_random_int_range ('A', 'Z');
	filename = g_build_filename (dirname, tmpname, NULL);

	/* just copy to the temp file */
	fu_provider_set_status (provider, FWUPD_STATUS_SCHEDULING);
	if (!g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, error))
		return FALSE;
	fwbin = g_input_stream_read_bytes (stream,
					   FU_PROVIDER_FIRMWARE_MAX,
					   NULL, error);
	if (fwbin == NULL)
		return FALSE;
	if (!g_file_set_contents (filename,
				  g_bytes_get_data (fwbin, NULL),
				  g_bytes_get_size (fwbin),
				  error))
		return FALSE;

	/* schedule for next boot */
	g_debug ("schedule %s to be installed to %s on next boot",
		 filename, fu_device_get_id (device));
	fu_device_set_metadata (device, FU_DEVICE_KEY_FILENAME_CAB, filename);

	/* add to database */
	if (!fu_pending_add_device (pending, device, error))
		return FALSE;

	/* next boot we run offline */
	return fu_provider_offline_setup (error);
}
예제 #8
0
/**
 * fu_provider_udev_client_add:
 **/
static void
fu_provider_udev_client_add (FuProviderUdev *provider_udev, GUdevDevice *device)
{
	FuProviderUdevPrivate *priv = GET_PRIVATE (provider_udev);
	FuDevice *dev;
	const gchar *display_name;
	const gchar *guid;
	const gchar *product;
	const gchar *vendor;
	g_autofree gchar *guid_new = NULL;
	g_autofree gchar *id = NULL;
	g_autofree gchar *rom_fn = NULL;
	g_autofree gchar *version = NULL;
	g_auto(GStrv) split = NULL;

	/* interesting device? */
	guid = g_udev_device_get_property (device, "FWUPD_GUID");
	if (guid == NULL)
		return;

	/* get data */
	g_debug ("adding udev device: %s", g_udev_device_get_sysfs_path (device));
	if (0) {
		const gchar * const *keys;
		guint i;
		keys = g_udev_device_get_property_keys (device);
		for (i = 0; keys[i] != NULL; i++)
			g_debug ("KEY: %s=%s", keys[i],
				 g_udev_device_get_property (device, keys[i]));

		keys = g_udev_device_get_sysfs_attr_keys (device);
		for (i = 0; keys[i] != NULL; i++)
			g_debug ("SYS: %s=%s", keys[i],
				 g_udev_device_get_sysfs_attr (device, keys[i]));
	}

	/* is already in database */
	id = fu_provider_udev_get_id (device);
	dev = g_hash_table_lookup (priv->devices, id);
	if (dev != NULL) {
		g_debug ("ignoring duplicate %s", id);
		return;
	}

	/* get the FW version from the BCD device revision */
	product = g_udev_device_get_property (device, "PRODUCT");
	if (product != NULL) {
		split = g_strsplit (product, "/", -1);
		if (g_strv_length (split) != 3) {
			g_warning ("env{PRODUCT} is invalid: %s", product);
			return;
		}
		version = g_strdup (split[2]);
	}

	/* get the FW version from the rom */
	rom_fn = g_build_filename (g_udev_device_get_sysfs_path (device), "rom", NULL);
	if (g_file_test (rom_fn, G_FILE_TEST_EXISTS)) {
		g_autoptr(GError) error = NULL;
		g_autoptr(GFile) file = NULL;
		g_autoptr(FuRom) rom = NULL;
		file = g_file_new_for_path (rom_fn);
		rom = fu_rom_new ();
		if (!fu_rom_load_file (rom, file, FU_ROM_LOAD_FLAG_BLANK_PPID, NULL, &error)) {
			g_warning ("Failed to parse ROM from %s: %s",
				   rom_fn, error->message);
		}
		version = g_strdup (fu_rom_get_version (rom));

		/* prefer the GUID from the firmware rather than the
		 * hardware as the firmware may be more generic, which
		 * also allows us to match the GUID when doing 'verify'
		 * on a device with a different PID to the firmware */
		guid_new = g_strdup (fu_rom_get_guid (rom));
	}

	/* we failed */
	if (version == NULL)
		return;

	/* no GUID from the ROM, so fix up the VID:PID */
	if (guid_new == NULL) {
		if (!as_utils_guid_is_valid (guid)) {
			guid_new = as_utils_guid_from_string (guid);
			g_debug ("Fixing GUID %s->%s", guid, guid_new);
		} else {
			guid_new = g_strdup (guid);
		}
	}

	/* did we get enough data */
	dev = fu_device_new ();
	fu_device_add_flag (dev, FU_DEVICE_FLAG_INTERNAL);
	fu_device_set_id (dev, id);
	fu_device_set_guid (dev, guid_new);
	display_name = g_udev_device_get_property (device, "FWUPD_MODEL");
	if (display_name == NULL)
		display_name = g_udev_device_get_property (device, "ID_MODEL_FROM_DATABASE");
	if (display_name != NULL)
		fu_device_set_display_name (dev, display_name);
	vendor = g_udev_device_get_property (device, "FWUPD_VENDOR");
	if (vendor == NULL)
		vendor = g_udev_device_get_property (device, "ID_VENDOR_FROM_DATABASE");
	if (vendor != NULL)
		fu_device_set_metadata (dev, FU_DEVICE_KEY_VENDOR, vendor);
	fu_device_set_metadata (dev, FU_DEVICE_KEY_VERSION, version);
	if (g_file_test (rom_fn, G_FILE_TEST_EXISTS))
		fu_device_set_metadata (dev, "RomFilename", rom_fn);

	/* insert to hash */
	g_hash_table_insert (priv->devices, g_strdup (id), dev);
	fu_provider_device_add (FU_PROVIDER (provider_udev), dev);
}
예제 #9
0
/**
 * fu_provider_udev_client_add:
 **/
static void
fu_provider_udev_client_add (FuProviderUdev *provider_udev, GUdevDevice *device)
{
	FuProviderUdevPrivate *priv = GET_PRIVATE (provider_udev);
	FuDevice *dev;
	const gchar *display_name;
	const gchar *guid;
	const gchar *product;
	const gchar *vendor;
	g_autofree gchar *guid_new = NULL;
	g_autofree gchar *id = NULL;
	g_autofree gchar *rom_fn = NULL;
	g_autofree gchar *version = NULL;
	g_auto(GStrv) split = NULL;
	g_autoptr(AsProfile) profile = as_profile_new ();
	g_autoptr(AsProfileTask) ptask = NULL;

	/* interesting device? */
	guid = g_udev_device_get_property (device, "FWUPD_GUID");
	if (guid == NULL)
		return;

	/* get data */
	ptask = as_profile_start (profile, "FuProviderUdev:client-add{%s}", guid);
	g_debug ("adding udev device: %s", g_udev_device_get_sysfs_path (device));

	/* is already in database */
	id = fu_provider_udev_get_id (device);
	dev = g_hash_table_lookup (priv->devices, id);
	if (dev != NULL) {
		g_debug ("ignoring duplicate %s", id);
		return;
	}

	/* get the FW version from the BCD device revision */
	product = g_udev_device_get_property (device, "PRODUCT");
	if (product != NULL) {
		split = g_strsplit (product, "/", -1);
		if (g_strv_length (split) != 3) {
			g_warning ("env{PRODUCT} is invalid: %s", product);
			return;
		}
		version = g_strdup (split[2]);
	}

	/* no GUID from the ROM, so fix up the VID:PID */
	if (!as_utils_guid_is_valid (guid)) {
		guid_new = as_utils_guid_from_string (guid);
		g_debug ("fixing GUID %s->%s", guid, guid_new);
	} else {
		guid_new = g_strdup (guid);
	}

	/* did we get enough data */
	dev = fu_device_new ();
	fu_device_add_flag (dev, FU_DEVICE_FLAG_INTERNAL);
	fu_device_set_id (dev, id);
	fu_device_set_guid (dev, guid_new);
	display_name = g_udev_device_get_property (device, "FWUPD_MODEL");
	if (display_name == NULL)
		display_name = g_udev_device_get_property (device, "ID_MODEL_FROM_DATABASE");
	if (display_name != NULL)
		fu_device_set_name (dev, display_name);
	vendor = g_udev_device_get_property (device, "FWUPD_VENDOR");
	if (vendor == NULL)
		vendor = g_udev_device_get_property (device, "ID_VENDOR_FROM_DATABASE");
	if (vendor != NULL)
		fu_device_set_vendor (dev, vendor);
	if (version != NULL)
		fu_device_set_version (dev, version);

	/* get the FW version from the rom when unlocked */
	rom_fn = g_build_filename (g_udev_device_get_sysfs_path (device), "rom", NULL);
	if (g_file_test (rom_fn, G_FILE_TEST_EXISTS)) {
		fu_device_set_metadata (dev, "RomFilename", rom_fn);
		fu_device_add_flag (dev, FU_DEVICE_FLAG_LOCKED);
	}

	/* insert to hash */
	g_hash_table_insert (priv->devices, g_strdup (id), dev);
	fu_provider_device_add (FU_PROVIDER (provider_udev), dev);
}