/** * 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; }
/** * 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); }
/** * 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); }
/** * 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); }
/** * 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; }
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; }
/** * 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); }
/** * 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); }
/** * 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); }