mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-05 08:47:39 +00:00
superio: Add support for reading the device checksum
This commit is contained in:
parent
4702dfe0a7
commit
0573febb0b
@ -105,3 +105,51 @@ fu_plugin_coldplug (FuPlugin *plugin, GError **error)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
fu_plugin_verify_attach (FuPlugin *plugin, FuDevice *device, GError **error)
|
||||
{
|
||||
g_autoptr(FuDeviceLocker) locker = NULL;
|
||||
locker = fu_device_locker_new (device, error);
|
||||
if (locker == NULL)
|
||||
return FALSE;
|
||||
return fu_device_attach (device, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
fu_plugin_verify_detach (FuPlugin *plugin, FuDevice *device, GError **error)
|
||||
{
|
||||
g_autoptr(FuDeviceLocker) locker = NULL;
|
||||
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_IS_BOOTLOADER))
|
||||
return TRUE;
|
||||
locker = fu_device_locker_new (device, error);
|
||||
if (locker == NULL)
|
||||
return FALSE;
|
||||
return fu_device_detach (device, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
fu_plugin_verify (FuPlugin *plugin, FuDevice *device,
|
||||
FuPluginVerifyFlags flags, GError **error)
|
||||
{
|
||||
g_autoptr(GBytes) fw = NULL;
|
||||
g_autoptr(FuDeviceLocker) locker = NULL;
|
||||
GChecksumType checksum_types[] = {
|
||||
G_CHECKSUM_SHA1,
|
||||
G_CHECKSUM_SHA256,
|
||||
0 };
|
||||
|
||||
/* get data */
|
||||
locker = fu_device_locker_new (device, error);
|
||||
if (locker == NULL)
|
||||
return FALSE;
|
||||
fw = fu_device_read_firmware (device, error);
|
||||
if (fw == NULL)
|
||||
return FALSE;
|
||||
for (guint i = 0; checksum_types[i] != 0; i++) {
|
||||
g_autofree gchar *hash = NULL;
|
||||
hash = g_compute_checksum_for_bytes (checksum_types[i], fw);
|
||||
fu_device_add_checksum (device, hash);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -35,6 +35,27 @@ G_BEGIN_DECLS
|
||||
#define SIO_DEPTH2_I2EC_ADDRH 0x11
|
||||
#define SIO_DEPTH2_I2EC_DATA 0x12
|
||||
|
||||
/*
|
||||
* The PMC is a communication channel used between the host and the EC.
|
||||
* Compatible mode uses four registers:
|
||||
*
|
||||
* Name | EC | HOST | ADDR
|
||||
* _____________________|_______________|_______________|______
|
||||
* PMDIR | RO | WO | 0x62
|
||||
* PMDOR | WO | RO | 0x62
|
||||
* PMCMDR | RO | RO | 0x66
|
||||
* PMSTR | RO | RO | 0x66
|
||||
*/
|
||||
#define SIO_EC_PMC_PM1STS 0x00
|
||||
#define SIO_EC_PMC_PM1DO 0x01
|
||||
#define SIO_EC_PMC_PM1DOSCI 0x02
|
||||
#define SIO_EC_PMC_PM1DOCMI 0x03
|
||||
#define SIO_EC_PMC_PM1DI 0x04
|
||||
#define SIO_EC_PMC_PM1DISCI 0x05
|
||||
#define SIO_EC_PMC_PM1CTL 0x06
|
||||
#define SIO_EC_PMC_PM1IC 0x07
|
||||
#define SIO_EC_PMC_PM1IE 0x08
|
||||
|
||||
/* SPI commands */
|
||||
#define SIO_SPI_CMD_READ 0x03
|
||||
#define SIO_SPI_CMD_HS_READ 0x0b
|
||||
|
@ -121,6 +121,122 @@ fu_superio_it89_device_setup (FuSuperioDevice *self, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_superio_it89_device_ec_pm1do_sci (FuSuperioDevice *self, guint8 val, GError **error)
|
||||
{
|
||||
if (!fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DOSCI, error))
|
||||
return FALSE;
|
||||
if (!fu_superio_device_ec_write1 (self, val, error))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_superio_it89_device_ec_pm1do_smi (FuSuperioDevice *self, guint8 val, GError **error)
|
||||
{
|
||||
if (!fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DOCMI, error))
|
||||
return FALSE;
|
||||
if (!fu_superio_device_ec_write1 (self, val, error))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_superio_device_ec_read_status (FuSuperioDevice *self, GError **error)
|
||||
{
|
||||
guint8 tmp = 0x00;
|
||||
|
||||
/* read status register */
|
||||
if (!fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DO, error))
|
||||
return FALSE;
|
||||
if (!fu_superio_it89_device_ec_pm1do_sci (self, SIO_SPI_CMD_RDSR, error))
|
||||
return FALSE;
|
||||
|
||||
/* wait for write */
|
||||
do {
|
||||
if (!fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DI, error))
|
||||
return FALSE;
|
||||
if (!fu_superio_device_ec_read (self, &tmp, error))
|
||||
return FALSE;
|
||||
} while ((tmp & SIO_STATUS_EC_OBF) != 0);
|
||||
|
||||
/* watch SCI events */
|
||||
return fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DISCI, error);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
fu_superio_it89_device_read_addr (FuSuperioDevice *self,
|
||||
guint32 addr,
|
||||
guint size,
|
||||
GFileProgressCallback progress_cb,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree guint8 *buf = NULL;
|
||||
|
||||
/* check... */
|
||||
if (!fu_superio_device_ec_read_status (self, error))
|
||||
return NULL;
|
||||
|
||||
/* high speed read */
|
||||
if (!fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DO, error))
|
||||
return NULL;
|
||||
if (!fu_superio_it89_device_ec_pm1do_sci (self, SIO_SPI_CMD_HS_READ, error))
|
||||
return NULL;
|
||||
|
||||
/* set address, MSB, MID, LSB */
|
||||
if (!fu_superio_it89_device_ec_pm1do_smi (self, addr >> 16, error))
|
||||
return NULL;
|
||||
if (!fu_superio_it89_device_ec_pm1do_smi (self, addr >> 8, error))
|
||||
return NULL;
|
||||
if (!fu_superio_it89_device_ec_pm1do_smi (self, addr & 0xff, error))
|
||||
return NULL;
|
||||
|
||||
/* padding for HS? */
|
||||
if (!fu_superio_it89_device_ec_pm1do_smi (self, 0x0, error))
|
||||
return NULL;
|
||||
|
||||
/* read out data */
|
||||
buf = g_malloc0 (size);
|
||||
for (guint i = 0; i < size; i++) {
|
||||
if (!fu_superio_device_ec_write1 (self, SIO_EC_PMC_PM1DI, error))
|
||||
return NULL;
|
||||
if (!fu_superio_device_ec_read (self, &buf[i], error))
|
||||
return NULL;
|
||||
|
||||
/* update progress */
|
||||
if (progress_cb != NULL)
|
||||
progress_cb ((goffset) i, (goffset) size, self);
|
||||
}
|
||||
|
||||
/* check again... */
|
||||
if (!fu_superio_device_ec_read_status (self, error))
|
||||
return NULL;
|
||||
|
||||
/* success */
|
||||
return g_bytes_new_take (g_steal_pointer (&buf), size);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_superio_it89_device_progress_cb (goffset current, goffset total, gpointer user_data)
|
||||
{
|
||||
FuDevice *device = FU_DEVICE (user_data);
|
||||
fu_device_set_progress_full (device, (gsize) current, (gsize) total);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
fu_superio_it89_device_read_firmware (FuDevice *device, GError **error)
|
||||
{
|
||||
FuSuperioDevice *self = FU_SUPERIO_DEVICE (device);
|
||||
guint64 fwsize = fu_device_get_firmware_size_min (device);
|
||||
g_autoptr(GBytes) blob = NULL;
|
||||
|
||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_READ);
|
||||
blob = fu_superio_it89_device_read_addr (self, 0x0, fwsize,
|
||||
fu_superio_it89_device_progress_cb,
|
||||
error);
|
||||
return g_steal_pointer (&blob);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_superio_it89_device_attach (FuDevice *device, GError **error)
|
||||
{
|
||||
@ -172,5 +288,6 @@ fu_superio_it89_device_class_init (FuSuperioIt89DeviceClass *klass)
|
||||
FuSuperioDeviceClass *klass_superio_device = FU_SUPERIO_DEVICE_CLASS (klass);
|
||||
klass_device->attach = fu_superio_it89_device_attach;
|
||||
klass_device->detach = fu_superio_it89_device_detach;
|
||||
klass_device->read_firmware = fu_superio_it89_device_read_firmware;
|
||||
klass_superio_device->setup = fu_superio_it89_device_setup;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user