From 91e27e145a1f7cb97ec78875d08f1b9a9496dadf Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Sun, 21 Jun 2020 16:25:24 -0500 Subject: [PATCH] Add a new plugin for legacy BIOS This plugin is only enabled when coreboot isn't detected. It intentionally does not check for EFI to be disabled at startup since it can also notify the user that UEFI capsule updates are disabled on the system even if running in UEFI mode. --- contrib/fwupd.spec.in | 1 + plugins/bios/fu-plugin-bios.c | 98 +++++++++++++++++++++++++ plugins/bios/meson.build | 23 ++++++ plugins/dell-esrt/fu-plugin-dell-esrt.c | 4 +- plugins/meson.build | 1 + plugins/uefi/fu-plugin-uefi.c | 53 ++----------- 6 files changed, 131 insertions(+), 49 deletions(-) create mode 100644 plugins/bios/fu-plugin-bios.c create mode 100644 plugins/bios/meson.build diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in index e4695afad..64465edd7 100644 --- a/contrib/fwupd.spec.in +++ b/contrib/fwupd.spec.in @@ -333,6 +333,7 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg %{_libdir}/fwupd-plugins-3/libfu_plugin_altos.so %{_libdir}/fwupd-plugins-3/libfu_plugin_amt.so %{_libdir}/fwupd-plugins-3/libfu_plugin_ata.so +%{_libdir}/fwupd-plugins-3/libfu_plugin_bios.so %{_libdir}/fwupd-plugins-3/libfu_plugin_ccgx.so %{_libdir}/fwupd-plugins-3/libfu_plugin_colorhug.so %{_libdir}/fwupd-plugins-3/libfu_plugin_coreboot.so diff --git a/plugins/bios/fu-plugin-bios.c b/plugins/bios/fu-plugin-bios.c new file mode 100644 index 000000000..7b643a46b --- /dev/null +++ b/plugins/bios/fu-plugin-bios.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2020 Mario Limonciello + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include "fu-efivar.h" +#include "fu-plugin-vfuncs.h" +#include "fu-hash.h" + +void +fu_plugin_init (FuPlugin *plugin) +{ + fu_plugin_set_build_hash (plugin, FU_BUILD_HASH); +} + + +gboolean +fu_plugin_startup (FuPlugin *plugin, GError **error) +{ + const gchar *vendor; + + vendor = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VENDOR); + if (g_strcmp0 (vendor, "coreboot") == 0) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_NOT_FOUND, + "system uses coreboot"); + return FALSE; + } + + return TRUE; +} + + +static gboolean +fu_plugin_bios_create_dummy (FuPlugin *plugin, const gchar *reason, GError **error) +{ + const gchar *key; + g_autoptr(FuDevice) dev = fu_device_new (); + + fu_device_set_version_format (dev, FWUPD_VERSION_FORMAT_PLAIN); + key = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER); + if (key != NULL) + fu_device_set_vendor (dev, key); + key = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VENDOR); + if (key != NULL) { + g_autofree gchar *vendor_id = g_strdup_printf ("DMI:%s", key); + fu_device_set_vendor_id (FU_DEVICE (dev), vendor_id); + } + key = "System Firmware"; + fu_device_set_name (dev, key); + key = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VERSION); + if (key != NULL) + fu_device_set_version (dev, key); + fu_device_set_update_error (dev, reason); + + fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_INTERNAL); + + fu_device_add_icon (dev, "computer"); + fu_device_set_id (dev, "BIOS-dummy"); + fu_device_add_instance_id (dev, "main-system-firmware"); + if (!fu_device_setup (dev, error)) + return FALSE; + fu_plugin_device_add (plugin, dev); + + return TRUE; +} + +gboolean +fu_plugin_coldplug (FuPlugin *plugin, GError **error) +{ + g_autofree gchar *sysfsfwdir = NULL; + g_autoptr(GError) error_local = NULL; + g_autofree gchar *esrt_path = NULL; + + /* are the EFI dirs set up so we can update each device */ + if (!fu_efivar_supported (&error_local)) { + const gchar *reason = "Firmware can not be updated in legacy BIOS mode, switch to UEFI mode"; + g_warning ("%s", error_local->message); + return fu_plugin_bios_create_dummy (plugin, reason, error); + } + + /* get the directory of ESRT entries */ + sysfsfwdir = fu_common_get_path (FU_PATH_KIND_SYSFSDIR_FW); + esrt_path = g_build_filename (sysfsfwdir, "efi", "esrt", NULL); + if (!g_file_test (esrt_path, G_FILE_TEST_IS_DIR)) { + const gchar *reason = "UEFI Capsule updates not available or enabled"; + return fu_plugin_bios_create_dummy (plugin, reason, error); + } + + /* we appear to have UEFI capsule updates */ + fu_plugin_set_enabled (plugin, FALSE); + + return TRUE; +} diff --git a/plugins/bios/meson.build b/plugins/bios/meson.build new file mode 100644 index 000000000..9e7189089 --- /dev/null +++ b/plugins/bios/meson.build @@ -0,0 +1,23 @@ +cargs = ['-DG_LOG_DOMAIN="FuPluginBios"'] + +shared_module('fu_plugin_bios', + fu_hash, + sources : [ + 'fu-plugin-bios.c', + ], + include_directories : [ + root_incdir, + fwupd_incdir, + fwupdplugin_incdir, + ], + install : true, + install_dir: plugin_dir, + link_with : [ + fwupd, + fwupdplugin, + ], + c_args : cargs, + dependencies : [ + plugin_deps, + ], +) diff --git a/plugins/dell-esrt/fu-plugin-dell-esrt.c b/plugins/dell-esrt/fu-plugin-dell-esrt.c index 5f0b0b1d7..bc746d018 100644 --- a/plugins/dell-esrt/fu-plugin-dell-esrt.c +++ b/plugins/dell-esrt/fu-plugin-dell-esrt.c @@ -87,7 +87,7 @@ void fu_plugin_init (FuPlugin *plugin) { fu_plugin_set_build_hash (plugin, FU_BUILD_HASH); - fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_BETTER_THAN, "uefi"); + fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_BETTER_THAN, "bios"); } gboolean @@ -172,6 +172,8 @@ fu_plugin_coldplug (FuPlugin *plugin, GError **error) fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_LOCKED); fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT); fu_device_set_update_error (dev, "Firmware updates disabled; run 'fwupdmgr unlock' to enable"); + if (!fu_device_setup (dev, error)) + return FALSE; fu_plugin_device_add (plugin, dev); return TRUE; } diff --git a/plugins/meson.build b/plugins/meson.build index aeb1ea66a..e1ec6a612 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -1,5 +1,6 @@ subdir('acpi-dmar') subdir('acpi-facp') +subdir('bios') subdir('ccgx') subdir('cros-ec') subdir('cpu') diff --git a/plugins/uefi/fu-plugin-uefi.c b/plugins/uefi/fu-plugin-uefi.c index 2b4acde34..dc5807525 100644 --- a/plugins/uefi/fu-plugin-uefi.c +++ b/plugins/uefi/fu-plugin-uefi.c @@ -725,43 +725,6 @@ fu_plugin_unlock (FuPlugin *plugin, FuDevice *device, GError **error) return TRUE; } -static gboolean -fu_plugin_uefi_create_dummy (FuPlugin *plugin, const gchar *reason, GError **error) -{ - const gchar *key; - g_autoptr(FuDevice) dev = fu_device_new (); - - fu_device_set_version_format (dev, FWUPD_VERSION_FORMAT_PLAIN); - key = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER); - if (key != NULL) - fu_device_set_vendor (dev, key); - key = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VENDOR); - if (key != NULL) { - g_autofree gchar *vendor_id = g_strdup_printf ("DMI:%s", key); - fu_device_set_vendor_id (FU_DEVICE (dev), vendor_id); - } - key = fu_plugin_uefi_get_name_for_type (plugin, FU_UEFI_DEVICE_KIND_SYSTEM_FIRMWARE); - fu_device_set_name (dev, key); - key = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VERSION); - if (key != NULL) - fu_device_set_version (dev, key); - fu_device_set_update_error (dev, reason); - - fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_INTERNAL); - fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT); - fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_REQUIRE_AC); - fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_MD_SET_VERFMT); - - fu_device_add_icon (dev, "computer"); - fu_device_set_id (dev, "UEFI-dummy"); - fu_device_add_instance_id (dev, "main-system-firmware"); - if (!fu_device_setup (dev, error)) - return FALSE; - fu_plugin_device_add (plugin, dev); - - return TRUE; -} - gboolean fu_plugin_coldplug (FuPlugin *plugin, GError **error) { @@ -776,21 +739,15 @@ fu_plugin_coldplug (FuPlugin *plugin, GError **error) g_autoptr(GPtrArray) entries = NULL; /* are the EFI dirs set up so we can update each device */ - if (!fu_efivar_supported (&error_local)) { - const gchar *reason = "Firmware can not be updated in legacy mode, switch to UEFI mode"; - g_warning ("%s", error_local->message); - return fu_plugin_uefi_create_dummy (plugin, reason, error); - } + if (!fu_efivar_supported (error)) + return FALSE; /* get the directory of ESRT entries */ sysfsfwdir = fu_common_get_path (FU_PATH_KIND_SYSFSDIR_FW); esrt_path = g_build_filename (sysfsfwdir, "efi", "esrt", NULL); - entries = fu_uefi_get_esrt_entry_paths (esrt_path, &error_local); - if (entries == NULL) { - const gchar *reason = "UEFI Capsule updates not available or enabled"; - g_warning ("%s", error_local->message); - return fu_plugin_uefi_create_dummy (plugin, reason, error); - } + entries = fu_uefi_get_esrt_entry_paths (esrt_path, error); + if (entries == NULL) + return FALSE; /* make sure that efivarfs is rw */ if (!fu_plugin_uefi_ensure_efivarfs_rw (&error_efivarfs))