diff --git a/plugins/superio/fu-plugin-superio.c b/plugins/superio/fu-plugin-superio.c index 2af14b5d7..a03cc6482 100644 --- a/plugins/superio/fu-plugin-superio.c +++ b/plugins/superio/fu-plugin-superio.c @@ -8,7 +8,7 @@ #include "fu-plugin-vfuncs.h" -#include "fu-superio-device.h" +#include "fu-superio-it85-device.h" #define FU_QUIRKS_SUPERIO_CHIPSETS "SuperioChipsets" @@ -41,12 +41,26 @@ fu_plugin_superio_coldplug_chipset (FuPlugin *plugin, const gchar *chipset, GErr return FALSE; } - /* create IT8xxx */ - dev = g_object_new (FU_TYPE_SUPERIO_DEVICE, - "chipset", chipset, - "id", id, - "port", port, - NULL); + /* create IT89xx or IT89xx */ + if (id >> 8 == 0x85) { + dev = g_object_new (FU_TYPE_SUPERIO_IT85_DEVICE, + "chipset", chipset, + "id", id, + "port", port, + NULL); + } else if (id >> 8 == 0x89) { + dev = g_object_new (FU_TYPE_SUPERIO_DEVICE, + "chipset", chipset, + "id", id, + "port", port, + NULL); + } else { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "SuperIO chip %s has unsupported Id", chipset); + return FALSE; + } /* unlock */ locker = fu_device_locker_new (dev, error); diff --git a/plugins/superio/fu-superio-device.c b/plugins/superio/fu-superio-device.c index 2a9e6d892..e7f203b4c 100644 --- a/plugins/superio/fu-superio-device.c +++ b/plugins/superio/fu-superio-device.c @@ -17,10 +17,6 @@ #define FU_PLUGIN_SUPERIO_TIMEOUT 0.25 /* s */ -/* unknown source, IT87 only */ -#define SIO_CMD_EC_GET_NAME_STR 0x92 -#define SIO_CMD_EC_GET_VERSION_STR 0x93 - typedef struct { gint fd; @@ -206,7 +202,7 @@ fu_superio_device_ec_write1 (FuSuperioDevice *self, guint8 data, GError **error) return fu_superio_outb (priv->fd, priv->pm1_iobad1, data, error); } -static gboolean +gboolean fu_superio_device_ec_flush (FuSuperioDevice *self, GError **error) { FuSuperioDevicePrivate *priv = GET_PRIVATE (self); @@ -231,7 +227,7 @@ fu_superio_device_ec_flush (FuSuperioDevice *self, GError **error) return TRUE; } -static gboolean +gboolean fu_superio_device_ec_get_param (FuSuperioDevice *self, guint8 param, guint8 *data, GError **error) { if (!fu_superio_device_ec_write1 (self, SIO_CMD_EC_READ, error)) @@ -253,23 +249,6 @@ fu_superio_device_ec_set_param (FuSuperioDevice *self, guint8 param, guint8 data } #endif -static gchar * -fu_superio_device_ec_get_str (FuSuperioDevice *self, guint8 idx, GError **error) -{ - GString *str = g_string_new (NULL); - if (!fu_superio_device_ec_write1 (self, idx, error)) - return NULL; - for (guint i = 0; i < 0xff; i++) { - guint8 c = 0; - if (!fu_superio_device_ec_read (self, &c, error)) - return NULL; - if (c == '$') - break; - g_string_append_c (str, c); - } - return g_string_free (str, FALSE); -} - static gboolean fu_superio_device_open (FuDevice *device, GError **error) { @@ -306,40 +285,6 @@ fu_superio_device_probe (FuDevice *device, GError **error) return TRUE; } -static gboolean -fu_superio_device_setup_it85xx (FuSuperioDevice *self, GError **error) -{ - guint8 size_tmp = 0; - g_autofree gchar *name = NULL; - g_autofree gchar *version = NULL; - - /* get EC size */ - if (!fu_superio_device_ec_flush (self, error)) { - g_prefix_error (error, "failed to flush: "); - return FALSE; - } - if (!fu_superio_device_ec_get_param (self, 0xe5, &size_tmp, error)) { - g_prefix_error (error, "failed to get EC size: "); - return FALSE; - } - fu_device_set_firmware_size (FU_DEVICE (self), ((guint32) size_tmp) << 10); - - /* get EC strings */ - name = fu_superio_device_ec_get_str (self, SIO_CMD_EC_GET_NAME_STR, error); - if (name == NULL) { - g_prefix_error (error, "failed to get EC name: "); - return FALSE; - } - fu_device_set_name (FU_DEVICE (self), name); - version = fu_superio_device_ec_get_str (self, SIO_CMD_EC_GET_VERSION_STR, error); - if (version == NULL) { - g_prefix_error (error, "failed to get EC version: "); - return FALSE; - } - fu_device_set_version (FU_DEVICE (self), version); - return TRUE; -} - static gboolean fu_superio_device_it89xx_read_ec_register (FuSuperioDevice *self, guint16 addr, @@ -450,6 +395,7 @@ fu_superio_device_setup_it89xx (FuSuperioDevice *self, GError **error) static gboolean fu_superio_device_setup (FuDevice *device, GError **error) { + FuSuperioDeviceClass *klass = FU_SUPERIO_DEVICE_GET_CLASS (device); FuSuperioDevice *self = FU_SUPERIO_DEVICE (device); FuSuperioDevicePrivate *priv = GET_PRIVATE (self); guint8 tmp = 0x0; @@ -506,11 +452,9 @@ fu_superio_device_setup (FuDevice *device, GError **error) fu_common_dump_raw (G_LOG_DOMAIN, "EC Registers", buf, 0x100); } - /* IT85xx */ - if (priv->id >> 8 == 0x85) { - if (!fu_superio_device_setup_it85xx (self, error)) - return FALSE; - } + /* subclassed setup */ + if (klass->setup != NULL) + return klass->setup (self, error); /* IT89xx */ if (priv->id >> 8 == 0x89) { diff --git a/plugins/superio/fu-superio-device.h b/plugins/superio/fu-superio-device.h index e3992302a..38023cf97 100644 --- a/plugins/superio/fu-superio-device.h +++ b/plugins/superio/fu-superio-device.h @@ -16,8 +16,12 @@ G_DECLARE_DERIVABLE_TYPE (FuSuperioDevice, fu_superio_device, FU, SUPERIO_DEVICE struct _FuSuperioDeviceClass { FuDeviceClass parent_class; + gboolean (*setup) (FuSuperioDevice *self, + GError **error); }; +gboolean fu_superio_device_ec_flush (FuSuperioDevice *self, + GError **error); gboolean fu_superio_device_ec_read (FuSuperioDevice *self, guint8 *data, GError **error); @@ -27,6 +31,10 @@ gboolean fu_superio_device_ec_write0 (FuSuperioDevice *self, gboolean fu_superio_device_ec_write1 (FuSuperioDevice *self, guint8 data, GError **error); +gboolean fu_superio_device_ec_get_param (FuSuperioDevice *self, + guint8 param, + guint8 *data, + GError **error); gboolean fu_superio_device_regval (FuSuperioDevice *self, guint8 addr, guint8 *data, diff --git a/plugins/superio/fu-superio-it85-device.c b/plugins/superio/fu-superio-it85-device.c new file mode 100644 index 000000000..33372175a --- /dev/null +++ b/plugins/superio/fu-superio-it85-device.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018-2019 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include "fu-chunk.h" +#include "fu-superio-common.h" +#include "fu-superio-it85-device.h" + +struct _FuSuperioIt85Device { + FuSuperioDevice parent_instance; +}; + +G_DEFINE_TYPE (FuSuperioIt85Device, fu_superio_it85_device, FU_TYPE_SUPERIO_DEVICE) + +static gchar * +fu_superio_it85_device_get_str (FuSuperioDevice *self, guint8 idx, GError **error) +{ + GString *str = g_string_new (NULL); + if (!fu_superio_device_ec_write1 (self, idx, error)) + return NULL; + for (guint i = 0; i < 0xff; i++) { + guint8 c = 0; + if (!fu_superio_device_ec_read (self, &c, error)) + return NULL; + if (c == '$') + break; + g_string_append_c (str, c); + } + return g_string_free (str, FALSE); +} + +static gboolean +fu_superio_it85_device_setup (FuSuperioDevice *self, GError **error) +{ + guint8 size_tmp = 0; + g_autofree gchar *name = NULL; + g_autofree gchar *version = NULL; + + /* get EC size */ + if (!fu_superio_device_ec_flush (self, error)) { + g_prefix_error (error, "failed to flush: "); + return FALSE; + } + if (!fu_superio_device_ec_get_param (self, 0xe5, &size_tmp, error)) { + g_prefix_error (error, "failed to get EC size: "); + return FALSE; + } + fu_device_set_firmware_size (FU_DEVICE (self), ((guint32) size_tmp) << 10); + + /* get EC strings */ + name = fu_superio_it85_device_get_str (self, SIO_CMD_EC_GET_NAME_STR, error); + if (name == NULL) { + g_prefix_error (error, "failed to get EC name: "); + return FALSE; + } + fu_device_set_name (FU_DEVICE (self), name); + version = fu_superio_it85_device_get_str (self, SIO_CMD_EC_GET_VERSION_STR, error); + if (version == NULL) { + g_prefix_error (error, "failed to get EC version: "); + return FALSE; + } + fu_device_set_version (FU_DEVICE (self), version); + return TRUE; +} + +static void +fu_superio_it85_device_init (FuSuperioIt85Device *self) +{ +} + +static void +fu_superio_it85_device_class_init (FuSuperioIt85DeviceClass *klass) +{ + FuSuperioDeviceClass *klass_superio_device = FU_SUPERIO_DEVICE_CLASS (klass); + klass_superio_device->setup = fu_superio_it85_device_setup; +} diff --git a/plugins/superio/fu-superio-it85-device.h b/plugins/superio/fu-superio-it85-device.h new file mode 100644 index 000000000..36443a8ad --- /dev/null +++ b/plugins/superio/fu-superio-it85-device.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2018-2019 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#pragma once + +#include "fu-superio-device.h" + +G_BEGIN_DECLS + +#define FU_TYPE_SUPERIO_IT85_DEVICE (fu_superio_it85_device_get_type ()) +G_DECLARE_FINAL_TYPE (FuSuperioIt85Device, fu_superio_it85_device, FU, SUPERIO_IT85_DEVICE, FuSuperioDevice) + +G_END_DECLS diff --git a/plugins/superio/meson.build b/plugins/superio/meson.build index 06b094342..1c424aad7 100644 --- a/plugins/superio/meson.build +++ b/plugins/superio/meson.build @@ -9,6 +9,7 @@ shared_module('fu_plugin_superio', sources : [ 'fu-plugin-superio.c', 'fu-superio-device.c', + 'fu-superio-it85-device.c', 'fu-superio-common.c', ], include_directories : [