flashrom: add lspcon-i2c-spi programmer support

Created lspcon-i2c-spi flashrom device that uses udev to detect i2c
devices that can be updated with the lspcon-i2c-spi flashrom programmer.

This change implements the logic from crrev.com/c/2792124 adapted to the
upstream flashrom plugin.
This commit is contained in:
Daniel Campello 2021-04-06 10:17:38 -06:00 committed by Daniel Campello
parent 0b9b7ecc84
commit fe073a304d
6 changed files with 163 additions and 4 deletions

View File

@ -39,7 +39,7 @@ The coreboot DMI version string always starts with `CBET`.
GUID Generation
---------------
These device uses hardware ID values which are derived from SMBIOS.
Internal device uses hardware ID values which are derived from SMBIOS.
* HardwareID-3
* HardwareID-4
@ -47,9 +47,12 @@ These device uses hardware ID values which are derived from SMBIOS.
* HardwareID-6
* HardwareID-10
These device uses hardware ID values which are derived from SMBIOS. They should
match the values provided by `fwupdtool hwids` or the `ComputerHardwareIds.exe`
Windows utility.
They should match the values provided by `fwupdtool hwids` or the
`ComputerHardwareIds.exe` Windows utility.
lspcon-i2c-spi devices use the customized DeviceInstanceId values, e.g.
* FLASHROM-LSPCON-I2C-SPI\VEN_1AF8&DEV_0175
Update Behavior
---------------

View File

@ -32,3 +32,14 @@ VersionFormat=number
[0ee5867c-93f0-5fb4-adf1-9d686ea1183a]
Branch=coreboot
VersionFormat=number
# match all devices with this udev subsystem
[I2C]
Plugin = flashrom
# Parade PS175
[1AF80175:00]
Plugin=flashrom
FlashromProgrammer=lspcon_i2c_spi
Name=PS175
Vendor=Parade

View File

@ -0,0 +1,126 @@
/*
* Copyright (C) 2021 Daniel Campello <campello@chromium.org>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-flashrom-device.h"
#include "fu-flashrom-lspcon-i2c-spi-device.h"
#include <libflashrom.h>
#define I2C_PATH_REGEX "/i2c-([0-9]+)/"
#define HID_LENGTH 8
#define DEVICE_GUID_FORMAT "FLASHROM-LSPCON-I2C-SPI\\VEN_%s&DEV_%s"
struct _FuFlashromLspconI2cSpiDevice {
FuFlashromDevice parent_instance;
gint bus_number;
};
G_DEFINE_TYPE (FuFlashromLspconI2cSpiDevice, fu_flashrom_lspcon_i2c_spi_device,
FU_TYPE_FLASHROM_DEVICE)
static void
fu_flashrom_lspcon_i2c_spi_device_init (FuFlashromLspconI2cSpiDevice *self)
{
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_UPDATABLE);
fu_device_set_version_format (FU_DEVICE (self), FWUPD_VERSION_FORMAT_PAIR);
}
static gboolean
fu_flashrom_lspcon_i2c_spi_device_probe (FuDevice *device, GError **error)
{
FuFlashromLspconI2cSpiDevice *self = FU_FLASHROM_LSPCON_I2C_SPI_DEVICE (device);
FuFlashromDevice *flashrom_device = FU_FLASHROM_DEVICE (device);
FuDeviceClass *klass =
FU_DEVICE_CLASS (fu_flashrom_lspcon_i2c_spi_device_parent_class);
g_autoptr(GRegex) regex = NULL;
g_autoptr(GMatchInfo) info = NULL;
const gchar *path = NULL;
/* FuFlashromDevice->probe */
if (!klass->probe (device, error))
return FALSE;
if (g_strcmp0 (fu_flashrom_device_get_programmer_name (flashrom_device),
"lspcon_i2c_spi") != 0) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"invalid programmer");
return FALSE;
}
/* get bus number out of sysfs path */
path = fu_udev_device_get_sysfs_path (FU_UDEV_DEVICE (device));
regex = g_regex_new (I2C_PATH_REGEX, 0, 0, error);
if (regex && g_regex_match_full (regex, path, -1, 0, 0, &info, error)) {
self->bus_number = g_ascii_strtoll ( g_match_info_fetch (info, 1),
NULL, 10);
return TRUE;
}
return FALSE;
}
static gboolean
fu_flashrom_lspcon_i2c_spi_device_open (FuDevice *device,
GError **error)
{
FuFlashromLspconI2cSpiDevice *self = FU_FLASHROM_LSPCON_I2C_SPI_DEVICE (device);
FuFlashromDevice *flashrom_device = FU_FLASHROM_DEVICE (device);
FuDeviceClass *klass =
FU_DEVICE_CLASS (fu_flashrom_lspcon_i2c_spi_device_parent_class);
g_autofree gchar *temp = NULL;
/* flashrom_programmer_init() mutates the programmer_args string. */
temp = g_strdup_printf ("bus=%d", self->bus_number);
fu_flashrom_device_set_programmer_args (flashrom_device, temp);
return klass->open (device, error);
}
static gboolean
fu_flashrom_lspcon_i2c_spi_device_setup (FuDevice *device, GError **error)
{
const gchar *hw_id = NULL;
g_autofree gchar *vid = NULL;
g_autofree gchar *pid = NULL;
g_autofree gchar *vendor_id = NULL;
g_autofree gchar *temp = NULL;
g_autofree gchar *guid = NULL;
hw_id = fu_udev_device_get_sysfs_attr (FU_UDEV_DEVICE (device), "name", error);
if (hw_id == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"HID not found");
return FALSE;
}
vid = g_strndup (hw_id, HID_LENGTH / 2);
pid = g_strndup (&hw_id[HID_LENGTH / 2], HID_LENGTH / 2);
vendor_id = g_strdup_printf ("I2C:%s", vid);
fu_device_add_vendor_id (device, vendor_id);
temp = g_strdup_printf (DEVICE_GUID_FORMAT, vid, pid);
fu_device_add_instance_id (device, temp);
guid = fwupd_guid_hash_string (temp);
fu_device_add_guid (device, guid);
/* TODO: Get the real version number. */
fu_device_set_version (device, "0.0");
return TRUE;
}
static void
fu_flashrom_lspcon_i2c_spi_device_class_init (FuFlashromLspconI2cSpiDeviceClass *klass)
{
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
klass_device->probe = fu_flashrom_lspcon_i2c_spi_device_probe;
klass_device->open = fu_flashrom_lspcon_i2c_spi_device_open;
klass_device->setup = fu_flashrom_lspcon_i2c_spi_device_setup;
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2021 Daniel Campello <campello@chromium.org>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include "fu-flashrom-device.h"
#define FU_TYPE_FLASHROM_LSPCON_I2C_SPI_DEVICE \
(fu_flashrom_lspcon_i2c_spi_device_get_type ())
G_DECLARE_FINAL_TYPE (FuFlashromLspconI2cSpiDevice,
fu_flashrom_lspcon_i2c_spi_device, FU,
FLASHROM_LSPCON_I2C_SPI_DEVICE, FuFlashromDevice)

View File

@ -26,6 +26,7 @@
#include "fu-plugin-vfuncs.h"
#include "fu-flashrom-internal-device.h"
#include "fu-flashrom-lspcon-i2c-spi-device.h"
#include <libflashrom.h>
@ -40,6 +41,8 @@ fu_plugin_init (FuPlugin *plugin)
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_METADATA_SOURCE, "linux_lockdown");
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_CONFLICTS, "coreboot"); /* obsoleted */
fu_plugin_add_flag (plugin, FWUPD_PLUGIN_FLAG_REQUIRE_HWID);
fu_plugin_set_device_gtype (plugin, FU_TYPE_FLASHROM_LSPCON_I2C_SPI_DEVICE);
fu_context_add_udev_subsystem (ctx, "i2c");
fu_context_add_quirk_key (ctx, "FlashromProgrammer");
}

View File

@ -10,6 +10,7 @@ shared_module('fu_plugin_flashrom',
sources : [
'fu-flashrom-device.c',
'fu-flashrom-internal-device.c',
'fu-flashrom-lspcon-i2c-spi-device.c',
'fu-plugin-flashrom.c',
],
include_directories : [