mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-03 11:28:58 +00:00
Add support for Microsoft HardwareIDs
This commit provides a new "hwids" subcommand for fwupdmgr that shows the hardware GUIDs on the local system. It also provides API that plugins can use to self-disable when a specific HWID does not match. The GUIDs used in this implementation match that of ComputerHardwareIds.exe
This commit is contained in:
parent
f29a6eeb2c
commit
b8f8db2082
315
src/fu-hwids.c
Normal file
315
src/fu-hwids.c
Normal file
@ -0,0 +1,315 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License Version 2.1
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
#include <appstream-glib.h>
|
||||
|
||||
#include "fu-hwids.h"
|
||||
|
||||
struct _FuHwids {
|
||||
GObject parent_instance;
|
||||
GHashTable *hash;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (FuHwids, fu_hwids, G_TYPE_OBJECT)
|
||||
|
||||
const gchar *
|
||||
fu_hwids_get_value (FuHwids *self, const gchar *key)
|
||||
{
|
||||
return g_hash_table_lookup (self->hash, key);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
fu_hwids_get_guid_for_str (const gchar *str, GError **error)
|
||||
{
|
||||
#if AS_CHECK_VERSION(0,6,13)
|
||||
const gchar *namespace_id = "70ffd812-4c7f-4c7d-0000-000000000000";
|
||||
glong items_written = 0;
|
||||
g_autofree gunichar2 *data = NULL;
|
||||
|
||||
/* convert to UTF-16 and convert to GUID using custom namespace */
|
||||
data = g_utf8_to_utf16 (str, -1, NULL, &items_written, error);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
return as_utils_guid_from_data (namespace_id,
|
||||
(guint8*) data,
|
||||
items_written * 2,
|
||||
error);
|
||||
#else
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_SUPPORTED,
|
||||
"libappstream-glib 0.6.13 is required");
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_hwids_get_replace_keys:
|
||||
* @self: A #FuHwids
|
||||
* @key: A HardwareID key, e.g. "HardwareID-3"
|
||||
*
|
||||
* Gets the replacement key for a well known value.
|
||||
*
|
||||
* Returns: the replacement value, e.g. "Manufacturer&ProductName", or %NULL for error.
|
||||
**/
|
||||
const gchar *
|
||||
fu_hwids_get_replace_keys (FuHwids *self, const gchar *key)
|
||||
{
|
||||
struct {
|
||||
const gchar *search;
|
||||
const gchar *replace;
|
||||
} msdefined[] = {
|
||||
{ "HardwareID-0", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME "&"
|
||||
FU_HWIDS_KEY_PRODUCT_SKU "&"
|
||||
FU_HWIDS_KEY_BIOS_VENDOR "&"
|
||||
FU_HWIDS_KEY_BIOS_VERSION "&"
|
||||
FU_HWIDS_KEY_BIOS_MAJOR_RELEASE "&"
|
||||
FU_HWIDS_KEY_BIOS_MINOR_RELEASE },
|
||||
{ "HardwareID-1", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME "&"
|
||||
FU_HWIDS_KEY_BIOS_VENDOR "&"
|
||||
FU_HWIDS_KEY_BIOS_VERSION "&"
|
||||
FU_HWIDS_KEY_BIOS_MAJOR_RELEASE "&"
|
||||
FU_HWIDS_KEY_BIOS_MINOR_RELEASE },
|
||||
{ "HardwareID-2", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME "&"
|
||||
FU_HWIDS_KEY_BIOS_VENDOR "&"
|
||||
FU_HWIDS_KEY_BIOS_VERSION "&"
|
||||
FU_HWIDS_KEY_BIOS_MAJOR_RELEASE "&"
|
||||
FU_HWIDS_KEY_BIOS_MINOR_RELEASE },
|
||||
{ "HardwareID-3", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME "&"
|
||||
FU_HWIDS_KEY_PRODUCT_SKU "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_PRODUCT },
|
||||
{ "HardwareID-4", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME "&"
|
||||
FU_HWIDS_KEY_PRODUCT_SKU },
|
||||
{ "HardwareID-5", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME },
|
||||
{ "HardwareID-6", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_PRODUCT_SKU "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_PRODUCT },
|
||||
{ "HardwareID-7", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_PRODUCT_SKU },
|
||||
{ "HardwareID-8", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_PRODUCT },
|
||||
{ "HardwareID-9", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_PRODUCT_NAME },
|
||||
{ "HardwareID-10", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_PRODUCT },
|
||||
{ "HardwareID-11", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_FAMILY },
|
||||
{ "HardwareID-12", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_ENCLOSURE_KIND },
|
||||
{ "HardwareID-13", FU_HWIDS_KEY_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_MANUFACTURER "&"
|
||||
FU_HWIDS_KEY_BASEBOARD_PRODUCT },
|
||||
{ "HardwareID-14", FU_HWIDS_KEY_MANUFACTURER },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* defined for Windows 10 */
|
||||
for (guint i = 0; msdefined[i].search != NULL; i++) {
|
||||
if (g_strcmp0 (msdefined[i].search, key) == 0) {
|
||||
key = msdefined[i].replace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_hwids_get_replace_values:
|
||||
* @self: A #FuHwids
|
||||
* @keys: A key, e.g. "HardwareID-3" or %FU_HWIDS_KEY_PRODUCT_SKU
|
||||
* @error: A #GError or %NULL
|
||||
*
|
||||
* Gets the replacement values for a HardwareID key or plain key.
|
||||
*
|
||||
* Returns: a string, e.g. "LENOVO&ThinkPad T440s", or %NULL for error.
|
||||
**/
|
||||
gchar *
|
||||
fu_hwids_get_replace_values (FuHwids *self, const gchar *keys, GError **error)
|
||||
{
|
||||
g_auto(GStrv) split = NULL;
|
||||
g_autoptr(GString) str = g_string_new (NULL);
|
||||
|
||||
/* do any replacements */
|
||||
keys = fu_hwids_get_replace_keys (self, keys);
|
||||
|
||||
/* get each part of the HWID */
|
||||
split = g_strsplit (keys, "&", -1);
|
||||
for (guint j = 0; split[j] != NULL; j++) {
|
||||
const gchar *tmp = g_hash_table_lookup (self->hash, split[j]);
|
||||
if (tmp == NULL) {
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"not available as '%s' unknown",
|
||||
split[j]);
|
||||
return NULL;
|
||||
}
|
||||
g_string_append_printf (str, "%s&", tmp);
|
||||
}
|
||||
if (str->len > 0)
|
||||
g_string_truncate (str, str->len - 1);
|
||||
return g_strdup (str->str);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_hwids_get_guid:
|
||||
* @self: A #FuHwids
|
||||
* @keys: A key, e.g. "HardwareID-3" or %FU_HWIDS_KEY_PRODUCT_SKU
|
||||
* @error: A #GError or %NULL
|
||||
*
|
||||
* Gets the GUID for a specific key.
|
||||
*
|
||||
* Returns: a string, or %NULL for error.
|
||||
**/
|
||||
gchar *
|
||||
fu_hwids_get_guid (FuHwids *self, const gchar *keys, GError **error)
|
||||
{
|
||||
g_autofree gchar *tmp = fu_hwids_get_replace_values (self, keys, error);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
return fu_hwids_get_guid_for_str (tmp, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_hwids_setup:
|
||||
* @self: A #FuHwids
|
||||
* @sysfsdir: The sysfs directory, or %NULL for the default
|
||||
* @error: A #GError or %NULL
|
||||
*
|
||||
* Reads all the SMBIOS values from the hardware.
|
||||
*
|
||||
* Returns: %TRUE for success
|
||||
**/
|
||||
gboolean
|
||||
fu_hwids_setup (FuHwids *self, const gchar *sysfsdir, GError **error)
|
||||
{
|
||||
struct {
|
||||
const gchar *key;
|
||||
const gchar *value;
|
||||
} sysfsfile[] = {
|
||||
{ FU_HWIDS_KEY_MANUFACTURER, "sys_vendor" },
|
||||
{ FU_HWIDS_KEY_ENCLOSURE_KIND, "chassis_type" },
|
||||
{ FU_HWIDS_KEY_FAMILY, "product_family" },
|
||||
{ FU_HWIDS_KEY_PRODUCT_NAME, "product_name" },
|
||||
{ FU_HWIDS_KEY_PRODUCT_SKU, "product_sku" },
|
||||
{ FU_HWIDS_KEY_BIOS_VENDOR, "bios_vendor" },
|
||||
{ FU_HWIDS_KEY_BIOS_VERSION, "bios_version" },
|
||||
{ FU_HWIDS_KEY_BIOS_MAJOR_RELEASE, "bios_major_release" },
|
||||
{ FU_HWIDS_KEY_BIOS_MINOR_RELEASE, "bios_minor_release" },
|
||||
{ FU_HWIDS_KEY_BASEBOARD_MANUFACTURER, "board_vendor" },
|
||||
{ FU_HWIDS_KEY_BASEBOARD_PRODUCT, "board_name" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
g_return_val_if_fail (FU_IS_HWIDS (self), FALSE);
|
||||
|
||||
/* default value */
|
||||
if (sysfsdir == NULL)
|
||||
sysfsdir = "/sys/class/dmi/id";
|
||||
|
||||
/* does not exist in a container */
|
||||
if (!g_file_test (sysfsdir, G_FILE_TEST_EXISTS))
|
||||
return TRUE;
|
||||
|
||||
/* get all DMI data */
|
||||
for (guint i = 0; sysfsfile[i].key != NULL; i++) {
|
||||
g_autofree gchar *contents = NULL;
|
||||
g_autofree gchar *fn = NULL;
|
||||
const gchar *contents_hdr;
|
||||
|
||||
fn = g_build_filename (sysfsdir, sysfsfile[i].value, NULL);
|
||||
if (!g_file_test (fn, G_FILE_TEST_EXISTS)) {
|
||||
g_debug ("no %s so ignoring", fn);
|
||||
continue;
|
||||
}
|
||||
if (!g_file_get_contents (fn, &contents, NULL, error))
|
||||
return FALSE;
|
||||
g_strdelimit (contents, "\n\r", '\0');
|
||||
g_debug ("smbios property %s=%s", fn, contents);
|
||||
if (g_strcmp0 (contents, "Not Available") == 0)
|
||||
continue;
|
||||
if (g_strcmp0 (contents, "Not Defined") == 0)
|
||||
continue;
|
||||
|
||||
/* weirdly, remove leading zeros */
|
||||
contents_hdr = contents;
|
||||
while (contents_hdr[0] == '0')
|
||||
contents_hdr++;
|
||||
g_hash_table_insert (self->hash,
|
||||
g_strdup (sysfsfile[i].key),
|
||||
g_strdup (contents_hdr));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_hwids_finalize (GObject *object)
|
||||
{
|
||||
FuHwids *self;
|
||||
g_return_if_fail (FU_IS_HWIDS (object));
|
||||
self = FU_HWIDS (object);
|
||||
|
||||
g_hash_table_unref (self->hash);
|
||||
G_OBJECT_CLASS (fu_hwids_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_hwids_class_init (FuHwidsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
object_class->finalize = fu_hwids_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_hwids_init (FuHwids *self)
|
||||
{
|
||||
self->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
}
|
||||
|
||||
FuHwids *
|
||||
fu_hwids_new (void)
|
||||
{
|
||||
FuHwids *self;
|
||||
self = g_object_new (FU_TYPE_HWIDS, NULL);
|
||||
return FU_HWIDS (self);
|
||||
}
|
63
src/fu-hwids.h
Normal file
63
src/fu-hwids.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License Version 2.1
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __FU_HWIDS_H
|
||||
#define __FU_HWIDS_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define FU_TYPE_HWIDS (fu_hwids_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (FuHwids, fu_hwids, FU, HWIDS, GObject)
|
||||
|
||||
#define FU_HWIDS_KEY_BASEBOARD_MANUFACTURER "BaseboardManufacturer"
|
||||
#define FU_HWIDS_KEY_BASEBOARD_PRODUCT "BaseboardProduct"
|
||||
#define FU_HWIDS_KEY_BIOS_MAJOR_RELEASE "BiosMajorRelease"
|
||||
#define FU_HWIDS_KEY_BIOS_MINOR_RELEASE "BiosMinorRelease"
|
||||
#define FU_HWIDS_KEY_BIOS_VENDOR "BiosVendor"
|
||||
#define FU_HWIDS_KEY_BIOS_VERSION "BiosVersion"
|
||||
#define FU_HWIDS_KEY_ENCLOSURE_KIND "EnclosureKind"
|
||||
#define FU_HWIDS_KEY_FAMILY "Family"
|
||||
#define FU_HWIDS_KEY_MANUFACTURER "Manufacturer"
|
||||
#define FU_HWIDS_KEY_PRODUCT_NAME "ProductName"
|
||||
#define FU_HWIDS_KEY_PRODUCT_SKU "ProductSku"
|
||||
|
||||
FuHwids *fu_hwids_new (void);
|
||||
|
||||
const gchar *fu_hwids_get_value (FuHwids *self,
|
||||
const gchar *key);
|
||||
const gchar *fu_hwids_get_replace_keys (FuHwids *self,
|
||||
const gchar *key);
|
||||
gchar *fu_hwids_get_replace_values (FuHwids *self,
|
||||
const gchar *keys,
|
||||
GError **error);
|
||||
gchar *fu_hwids_get_guid (FuHwids *self,
|
||||
const gchar *keys,
|
||||
GError **error);
|
||||
gboolean fu_hwids_setup (FuHwids *self,
|
||||
const gchar *sysfsdir,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FU_HWIDS_H */
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "fu-debug.h"
|
||||
#include "fu-device.h"
|
||||
#include "fu-hwids.h"
|
||||
#include "fu-plugin-private.h"
|
||||
#include "fu-keyring.h"
|
||||
#include "fu-pending.h"
|
||||
@ -72,6 +73,7 @@ typedef struct {
|
||||
guint coldplug_delay;
|
||||
GPtrArray *plugins; /* of FuPlugin */
|
||||
GHashTable *plugins_hash; /* of name : FuPlugin */
|
||||
GHashTable *hwids; /* of hwid : 1 */
|
||||
} FuMainPrivate;
|
||||
|
||||
typedef struct {
|
||||
@ -2666,6 +2668,41 @@ fu_main_plugin_set_coldplug_delay_cb (FuPlugin *plugin, guint duration, FuMainPr
|
||||
duration, priv->coldplug_delay);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_main_load_hwids (FuMainPrivate *priv, GError **error)
|
||||
{
|
||||
g_autoptr(FuHwids) hwids = fu_hwids_new ();
|
||||
|
||||
/* read files in /sys */
|
||||
if (!fu_hwids_setup (hwids, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
/* add GUIDs */
|
||||
for (guint i = 0; i < 15; i++) {
|
||||
g_autofree gchar *guid = NULL;
|
||||
g_autofree gchar *key = NULL;
|
||||
g_autofree gchar *values = NULL;
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
|
||||
/* get the GUID and add to hash */
|
||||
key = g_strdup_printf ("HardwareID-%u", i);
|
||||
guid = fu_hwids_get_guid (hwids, key, &error_local);
|
||||
if (guid == NULL) {
|
||||
g_debug ("%s is not available, %s", key, error_local->message);
|
||||
continue;
|
||||
}
|
||||
g_hash_table_insert (priv->hwids,
|
||||
g_strdup (guid),
|
||||
GUINT_TO_POINTER (1));
|
||||
|
||||
/* show what makes up the GUID */
|
||||
values = fu_hwids_get_replace_values (hwids, key, NULL);
|
||||
g_debug ("{%s} <- %s", guid, values);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_main_load_plugins (FuMainPrivate *priv, GError **error)
|
||||
{
|
||||
@ -2697,6 +2734,7 @@ fu_main_load_plugins (FuMainPrivate *priv, GError **error)
|
||||
filename = g_build_filename (PLUGINDIR, fn, NULL);
|
||||
plugin = fu_plugin_new ();
|
||||
fu_plugin_set_usb_context (plugin, priv->usb_ctx);
|
||||
fu_plugin_set_hwids (plugin, priv->hwids);
|
||||
g_debug ("adding plugin %s", filename);
|
||||
if (!fu_plugin_open (plugin, filename, &error_local)) {
|
||||
g_warning ("failed to open plugin %s: %s",
|
||||
@ -2818,6 +2856,8 @@ fu_main_private_free (FuMainPrivate *priv)
|
||||
g_source_remove (priv->coldplug_id);
|
||||
if (priv->plugins != NULL)
|
||||
g_ptr_array_unref (priv->plugins);
|
||||
if (priv->hwids != NULL)
|
||||
g_hash_table_unref (priv->hwids);
|
||||
if (priv->plugins_hash != NULL)
|
||||
g_hash_table_unref (priv->plugins_hash);
|
||||
g_ptr_array_unref (priv->devices);
|
||||
@ -2911,6 +2951,13 @@ main (int argc, char *argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* load the hwids */
|
||||
priv->hwids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
if (!fu_main_load_hwids (priv, &error)) {
|
||||
g_printerr ("Failed to load hwids: %s\n", error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* load plugin */
|
||||
priv->plugins = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
priv->plugins_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
|
@ -31,6 +31,8 @@ G_BEGIN_DECLS
|
||||
FuPlugin *fu_plugin_new (void);
|
||||
void fu_plugin_set_usb_context (FuPlugin *plugin,
|
||||
GUsbContext *usb_ctx);
|
||||
void fu_plugin_set_hwids (FuPlugin *plugin,
|
||||
GHashTable *hwids);
|
||||
gboolean fu_plugin_open (FuPlugin *plugin,
|
||||
const gchar *filename,
|
||||
GError **error);
|
||||
|
@ -43,6 +43,7 @@ typedef struct {
|
||||
GUsbContext *usb_ctx;
|
||||
gboolean enabled;
|
||||
gchar *name;
|
||||
GHashTable *hwids; /* hwid:1 */
|
||||
GHashTable *devices; /* platform_id:GObject */
|
||||
GHashTable *devices_delay; /* FuDevice:FuPluginHelper */
|
||||
FuPluginData *data;
|
||||
@ -484,6 +485,34 @@ fu_plugin_recoldplug (FuPlugin *plugin)
|
||||
g_signal_emit (plugin, signals[SIGNAL_RECOLDPLUG], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_plugin_check_hwid:
|
||||
* @plugin: A #FuPlugin
|
||||
* @hwid: A Hardware ID GUID, e.g. "6de5d951-d755-576b-bd09-c5cf66b27234"
|
||||
*
|
||||
* Checks to see if a specific hardware ID exists. All hardware IDs on a
|
||||
* specific system can be shown using the `fwupdmgr hwids` command.
|
||||
*
|
||||
* Since: 0.9.1
|
||||
**/
|
||||
gboolean
|
||||
fu_plugin_check_hwid (FuPlugin *plugin, const gchar *hwid)
|
||||
{
|
||||
FuPluginPrivate *priv = GET_PRIVATE (plugin);
|
||||
if (priv->hwids == NULL)
|
||||
return FALSE;
|
||||
return g_hash_table_lookup (priv->hwids, hwid) != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
fu_plugin_set_hwids (FuPlugin *plugin, GHashTable *hwids)
|
||||
{
|
||||
FuPluginPrivate *priv = GET_PRIVATE (plugin);
|
||||
if (priv->hwids != NULL)
|
||||
g_hash_table_unref (priv->hwids);
|
||||
priv->hwids = g_hash_table_ref (hwids);
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_plugin_set_coldplug_delay:
|
||||
* @plugin: A #FuPlugin
|
||||
@ -1086,6 +1115,8 @@ fu_plugin_finalize (GObject *object)
|
||||
|
||||
if (priv->usb_ctx != NULL)
|
||||
g_object_unref (priv->usb_ctx);
|
||||
if (priv->hwids != NULL)
|
||||
g_hash_table_unref (priv->hwids);
|
||||
#ifndef RUNNING_ON_VALGRIND
|
||||
if (priv->module != NULL)
|
||||
g_module_close (priv->module);
|
||||
|
@ -92,6 +92,8 @@ void fu_plugin_cache_remove (FuPlugin *plugin,
|
||||
void fu_plugin_cache_add (FuPlugin *plugin,
|
||||
const gchar *id,
|
||||
gpointer dev);
|
||||
gboolean fu_plugin_check_hwid (FuPlugin *plugin,
|
||||
const gchar *hwid);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -30,8 +30,71 @@
|
||||
#include "fu-keyring.h"
|
||||
#include "fu-pending.h"
|
||||
#include "fu-plugin-private.h"
|
||||
#include "fu-hwids.h"
|
||||
#include "fu-test.h"
|
||||
|
||||
static void
|
||||
fu_hwids_func (void)
|
||||
{
|
||||
g_autoptr(FuHwids) hwids = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree gchar *guid = NULL;
|
||||
g_autofree gchar *testdir = NULL;
|
||||
const gchar *sysfsdir;
|
||||
gboolean ret;
|
||||
|
||||
struct {
|
||||
const gchar *key;
|
||||
const gchar *value;
|
||||
} guids[] = {
|
||||
{ "Manufacturer", "11b4a036-3b64-5421-a372-22c07df10a4d" },
|
||||
{ "HardwareID-14", "11b4a036-3b64-5421-a372-22c07df10a4d" },
|
||||
{ "HardwareID-13", "7ccbb6f1-9641-5f84-b00d-51ff218a4066" },
|
||||
{ "HardwareID-12", "482f3f58-6045-593a-9be4-611717ce4770" },
|
||||
{ "HardwareID-11", "6525c6e5-28e9-5f9c-abe4-20fd82504002" },
|
||||
{ "HardwareID-10", "c00fe015-014c-5301-90d1-b5c8ab037eb4" },
|
||||
{ "HardwareID-9", "6525c6e5-28e9-5f9c-abe4-20fd82504002" },
|
||||
{ "HardwareID-8", "c00fe015-014c-5301-90d1-b5c8ab037eb4" },
|
||||
{ "HardwareID-7", "5a127cba-be28-5d3b-84f0-0e450d266d97" },
|
||||
{ "HardwareID-6", "2c2d02cc-357e-539d-a44d-d10e902391dd" },
|
||||
{ "HardwareID-5", "7ccbb6f1-9641-5f84-b00d-51ff218a4066" },
|
||||
{ "HardwareID-4", "d78b474d-dee0-5412-bc9d-e9f7d7783df2" },
|
||||
{ "HardwareID-3", "a2f225b3-f4f0-5590-8973-08dd81602d69" },
|
||||
{ "HardwareID-2", "2e7c87e3-a52c-537f-a5f6-907110143cf7" },
|
||||
{ "HardwareID-1", "6453b900-1fd8-55fb-a936-7fca22823bcc" },
|
||||
{ "HardwareID-0", "d777e0a5-4db6-51b4-a927-86d4ccdc5c0d" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
sysfsdir = fu_test_get_filename (TESTDATADIR, "hwids");
|
||||
g_assert (sysfsdir != NULL);
|
||||
|
||||
hwids = fu_hwids_new ();
|
||||
ret = fu_hwids_setup (hwids, sysfsdir, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_MANUFACTURER), ==,
|
||||
"To be filled by O.E.M.");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_ENCLOSURE_KIND), ==,
|
||||
"3");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_FAMILY), ==,
|
||||
"To be filled by O.E.M.");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_PRODUCT_NAME), ==,
|
||||
"To be filled by O.E.M.");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_BIOS_VENDOR), ==,
|
||||
"American Megatrends Inc.");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_BIOS_VERSION), ==, "1201");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_BIOS_MAJOR_RELEASE), ==, "4");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_BIOS_MINOR_RELEASE), ==, "6");
|
||||
g_assert_cmpstr (fu_hwids_get_value (hwids, FU_HWIDS_KEY_PRODUCT_SKU), ==, "SKU");
|
||||
for (guint i = 0; guids[i].key != NULL; i++) {
|
||||
guid = fu_hwids_get_guid (hwids, guids[i].key, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpstr (guid, ==, guids[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_plugin_status_changed_cb (FuPlugin *plugin, FwupdStatus status, gpointer user_data)
|
||||
{
|
||||
@ -347,6 +410,7 @@ main (int argc, char **argv)
|
||||
g_assert_cmpint (g_mkdir_with_parents ("/tmp/fwupd-self-test/var/lib/fwupd", 0755), ==, 0);
|
||||
|
||||
/* tests go here */
|
||||
g_test_add_func ("/fwupd/hwids", fu_hwids_func);
|
||||
g_test_add_func ("/fwupd/pending", fu_pending_func);
|
||||
g_test_add_func ("/fwupd/plugin{delay}", fu_plugin_delay_func);
|
||||
g_test_add_func ("/fwupd/plugin{module}", fu_plugin_module_func);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2015-2016 Richard Hughes <richard@hughsie.com>
|
||||
* Copyright (C) 2015-2017 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* Licensed under the GNU General Public License Version 2
|
||||
*
|
||||
@ -36,6 +36,7 @@
|
||||
#include <libsoup/soup.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fu-hwids.h"
|
||||
#include "fu-pending.h"
|
||||
#include "fu-plugin-private.h"
|
||||
|
||||
@ -1074,6 +1075,67 @@ fu_util_update (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_hwids (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
g_autoptr(FuHwids) hwids = fu_hwids_new ();
|
||||
const gchar *hwid_keys[] = {
|
||||
FU_HWIDS_KEY_BIOS_VENDOR,
|
||||
FU_HWIDS_KEY_BIOS_VERSION,
|
||||
FU_HWIDS_KEY_BIOS_MAJOR_RELEASE,
|
||||
FU_HWIDS_KEY_BIOS_MINOR_RELEASE,
|
||||
FU_HWIDS_KEY_MANUFACTURER,
|
||||
FU_HWIDS_KEY_FAMILY,
|
||||
FU_HWIDS_KEY_PRODUCT_NAME,
|
||||
FU_HWIDS_KEY_PRODUCT_SKU,
|
||||
FU_HWIDS_KEY_ENCLOSURE_KIND,
|
||||
FU_HWIDS_KEY_BASEBOARD_MANUFACTURER,
|
||||
FU_HWIDS_KEY_BASEBOARD_PRODUCT,
|
||||
NULL };
|
||||
|
||||
/* read files in /sys */
|
||||
if (!fu_hwids_setup (hwids, g_getenv ("SYSFSPATH"), error))
|
||||
return FALSE;
|
||||
|
||||
/* show debug output */
|
||||
g_print ("Computer Information\n");
|
||||
g_print ("--------------------\n");
|
||||
for (guint i = 0; hwid_keys[i] != NULL; i++) {
|
||||
const gchar *tmp = fu_hwids_get_value (hwids, hwid_keys[i]);
|
||||
if (tmp == NULL)
|
||||
continue;
|
||||
g_print ("%s: %s\n", hwid_keys[i], tmp);
|
||||
}
|
||||
|
||||
/* show GUIDs */
|
||||
g_print ("\nHardware IDs\n");
|
||||
g_print ("------------\n");
|
||||
for (guint i = 0; i < 15; i++) {
|
||||
const gchar *keys = NULL;
|
||||
g_autofree gchar *guid = NULL;
|
||||
g_autofree gchar *key = NULL;
|
||||
g_autofree gchar *keys_str = NULL;
|
||||
g_auto(GStrv) keysv = NULL;
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
|
||||
/* get the GUID */
|
||||
key = g_strdup_printf ("HardwareID-%u", i);
|
||||
keys = fu_hwids_get_replace_keys (hwids, key);
|
||||
guid = fu_hwids_get_guid (hwids, key, &error_local);
|
||||
if (guid == NULL) {
|
||||
g_print ("%s\n", error_local->message);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* show what makes up the GUID */
|
||||
keysv = g_strsplit (keys, "&", -1);
|
||||
keys_str = g_strjoinv (" + ", keysv);
|
||||
g_print ("{%s} <- %s\n", guid, keys_str);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fu_util_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *message, gpointer user_data)
|
||||
@ -1156,6 +1218,12 @@ main (int argc, char *argv[])
|
||||
/* TRANSLATORS: command description */
|
||||
_("Get all devices that support firmware updates"),
|
||||
fu_util_get_devices);
|
||||
fu_util_add (priv->cmd_array,
|
||||
"hwids",
|
||||
NULL,
|
||||
/* TRANSLATORS: command description */
|
||||
_("Return all the hardare IDs for the machine"),
|
||||
fu_util_hwids);
|
||||
fu_util_add (priv->cmd_array,
|
||||
"install-prepared",
|
||||
NULL,
|
||||
|
@ -9,6 +9,7 @@ executable(
|
||||
sources : [
|
||||
'fu-device.c',
|
||||
'fu-pending.c',
|
||||
'fu-hwids.c',
|
||||
'fu-util.c',
|
||||
],
|
||||
include_directories : [
|
||||
@ -46,6 +47,7 @@ executable(
|
||||
resources_src,
|
||||
sources : [
|
||||
'fu-main.c',
|
||||
'fu-hwids.c',
|
||||
'fu-debug.c',
|
||||
'fu-device.c',
|
||||
'fu-keyring.c',
|
||||
@ -88,6 +90,7 @@ if get_option('enable-tests')
|
||||
colorhug_test_firmware,
|
||||
sources : [
|
||||
'fu-self-test.c',
|
||||
'fu-hwids.c',
|
||||
'fu-device.c',
|
||||
'fu-pending.c',
|
||||
'fu-keyring.c',
|
||||
|
Loading…
Reference in New Issue
Block a user