mirror of
https://git.proxmox.com/git/fwupd
synced 2025-06-06 07:46:22 +00:00

For a while we flirted with the idea of updating non-internal libflashrom-derived devices but the impedance mismatch was just too great. We removed the extra unused subclasses of FuFlashromDevice, but never removed the indirection we added for the writing. Remove the unused code now that we agree on the longer term plan.
195 lines
5.6 KiB
C
195 lines
5.6 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
|
*
|
|
* Copyright (C) 2017 Richard Hughes <richard@hughsie.com>
|
|
* Copyright (C) 2019 9elements Agency GmbH <patrick.rudolph@9elements.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <fwupdplugin.h>
|
|
|
|
#include <libflashrom.h>
|
|
#include <string.h>
|
|
|
|
#include "fu-flashrom-device.h"
|
|
|
|
#define SELFCHECK_TRUE 1
|
|
|
|
static void
|
|
fu_plugin_flashrom_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);
|
|
}
|
|
|
|
static int
|
|
fu_plugin_flashrom_debug_cb(enum flashrom_log_level lvl, const char *fmt, va_list args)
|
|
{
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
|
g_autofree gchar *tmp = g_strdup_vprintf(fmt, args);
|
|
#pragma clang diagnostic pop
|
|
g_autofree gchar *str = fu_common_strstrip(tmp);
|
|
if (g_strcmp0(str, "OK.") == 0 || g_strcmp0(str, ".") == 0)
|
|
return 0;
|
|
switch (lvl) {
|
|
case FLASHROM_MSG_ERROR:
|
|
case FLASHROM_MSG_WARN:
|
|
g_warning("%s", str);
|
|
break;
|
|
case FLASHROM_MSG_INFO:
|
|
g_debug("%s", str);
|
|
break;
|
|
case FLASHROM_MSG_DEBUG:
|
|
case FLASHROM_MSG_DEBUG2:
|
|
if (g_getenv("FWUPD_FLASHROM_VERBOSE") != NULL)
|
|
g_debug("%s", str);
|
|
break;
|
|
case FLASHROM_MSG_SPEW:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
fu_plugin_flashrom_device_set_version(FuPlugin *plugin, FuDevice *device)
|
|
{
|
|
FuContext *ctx = fu_plugin_get_context(plugin);
|
|
const gchar *version;
|
|
const gchar *version_major;
|
|
const gchar *version_minor;
|
|
|
|
/* as-is */
|
|
version = fu_context_get_hwid_value(ctx, FU_HWIDS_KEY_BIOS_VERSION);
|
|
if (version != NULL) {
|
|
/* some Lenovo hardware requires a specific prefix for the EC,
|
|
* so strip it before we use ensure-semver */
|
|
if (strlen(version) > 9 && g_str_has_prefix(version, "CBET"))
|
|
version += 9;
|
|
|
|
/* this may not "stick" if there are no numeric chars */
|
|
fu_device_set_version(device, version);
|
|
if (fu_device_get_version(device) != NULL)
|
|
return;
|
|
}
|
|
|
|
/* component parts only */
|
|
version_major = fu_context_get_hwid_value(ctx, FU_HWIDS_KEY_BIOS_MAJOR_RELEASE);
|
|
version_minor = fu_context_get_hwid_value(ctx, FU_HWIDS_KEY_BIOS_MINOR_RELEASE);
|
|
if (version_major != NULL && version_minor != NULL) {
|
|
g_autofree gchar *tmp = g_strdup_printf("%s.%s.0", version_major, version_minor);
|
|
fu_device_set_version(device, tmp);
|
|
return;
|
|
}
|
|
}
|
|
static void
|
|
fu_plugin_flashrom_device_set_bios_info(FuPlugin *plugin, FuDevice *device)
|
|
{
|
|
FuContext *ctx = fu_plugin_get_context(plugin);
|
|
const guint8 *buf;
|
|
gsize bufsz;
|
|
guint32 bios_char = 0x0;
|
|
guint8 bios_sz = 0x0;
|
|
g_autoptr(GBytes) bios_table = NULL;
|
|
|
|
/* get SMBIOS info */
|
|
bios_table = fu_context_get_smbios_data(ctx, FU_SMBIOS_STRUCTURE_TYPE_BIOS);
|
|
if (bios_table == NULL)
|
|
return;
|
|
|
|
/* ROM size */
|
|
buf = g_bytes_get_data(bios_table, &bufsz);
|
|
if (fu_common_read_uint8_safe(buf, bufsz, 0x9, &bios_sz, NULL)) {
|
|
guint64 firmware_size = (bios_sz + 1) * 64 * 1024;
|
|
fu_device_set_firmware_size_max(device, firmware_size);
|
|
}
|
|
|
|
/* BIOS characteristics */
|
|
if (fu_common_read_uint32_safe(buf, bufsz, 0xa, &bios_char, G_LITTLE_ENDIAN, NULL)) {
|
|
if ((bios_char & (1 << 11)) == 0) {
|
|
fu_device_inhibit(device,
|
|
"bios-characteristics",
|
|
"Not supported from SMBIOS");
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
fu_plugin_flashrom_device_set_hwids(FuPlugin *plugin, FuDevice *device)
|
|
{
|
|
FuContext *ctx = fu_plugin_get_context(plugin);
|
|
static const gchar *hwids[] = {
|
|
"HardwareID-3",
|
|
"HardwareID-4",
|
|
"HardwareID-5",
|
|
"HardwareID-6",
|
|
"HardwareID-10",
|
|
/* a more useful one for coreboot branch detection */
|
|
FU_HWIDS_KEY_MANUFACTURER "&" FU_HWIDS_KEY_FAMILY "&" FU_HWIDS_KEY_PRODUCT_NAME
|
|
"&" FU_HWIDS_KEY_PRODUCT_SKU "&" FU_HWIDS_KEY_BIOS_VENDOR,
|
|
};
|
|
/* don't include FU_HWIDS_KEY_BIOS_VERSION */
|
|
for (guint i = 0; i < G_N_ELEMENTS(hwids); i++) {
|
|
g_autofree gchar *str = NULL;
|
|
str = fu_context_get_hwid_replace_value(ctx, hwids[i], NULL);
|
|
if (str != NULL)
|
|
fu_device_add_instance_id(device, str);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
fu_plugin_flashrom_coldplug(FuPlugin *plugin, GError **error)
|
|
{
|
|
FuContext *ctx = fu_plugin_get_context(plugin);
|
|
const gchar *dmi_vendor;
|
|
g_autoptr(FuDevice) device = fu_flashrom_device_new(ctx);
|
|
|
|
fu_device_set_context(device, ctx);
|
|
fu_device_set_name(device, fu_context_get_hwid_value(ctx, FU_HWIDS_KEY_PRODUCT_NAME));
|
|
fu_device_set_vendor(device, fu_context_get_hwid_value(ctx, FU_HWIDS_KEY_MANUFACTURER));
|
|
|
|
/* use same VendorID logic as with UEFI */
|
|
dmi_vendor = fu_context_get_hwid_value(ctx, FU_HWIDS_KEY_BIOS_VENDOR);
|
|
if (dmi_vendor != NULL) {
|
|
g_autofree gchar *vendor_id = g_strdup_printf("DMI:%s", dmi_vendor);
|
|
fu_device_add_vendor_id(FU_DEVICE(device), vendor_id);
|
|
}
|
|
fu_plugin_flashrom_device_set_version(plugin, device);
|
|
fu_plugin_flashrom_device_set_hwids(plugin, device);
|
|
fu_plugin_flashrom_device_set_bios_info(plugin, device);
|
|
if (!fu_device_setup(device, error))
|
|
return FALSE;
|
|
|
|
/* success */
|
|
fu_plugin_device_add(plugin, device);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fu_plugin_flashrom_startup(FuPlugin *plugin, GError **error)
|
|
{
|
|
if (flashrom_init(SELFCHECK_TRUE)) {
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"flashrom initialization error");
|
|
return FALSE;
|
|
}
|
|
flashrom_set_log_callback(fu_plugin_flashrom_debug_cb);
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
fu_plugin_init_vfuncs(FuPluginVfuncs *vfuncs)
|
|
{
|
|
vfuncs->build_hash = FU_BUILD_HASH;
|
|
vfuncs->init = fu_plugin_flashrom_init;
|
|
vfuncs->startup = fu_plugin_flashrom_startup;
|
|
vfuncs->coldplug = fu_plugin_flashrom_coldplug;
|
|
}
|