mirror of
https://git.proxmox.com/git/fwupd
synced 2025-04-29 22:08:11 +00:00

We now have two plugins getting the ESP values, and we only allow hardcoding the ESP in uefi_capsule.conf. Make all this a lot simpler by moving the ESP+BDP code to `FuContext`, which also means we can handle the override (via the config file) in the engine, and the override (in the command line tools) using the same mechanism. Also, automate the migration of the `OverrideESPMountPoint` -> `EspLocation` when loading the engine. Fixes https://github.com/fwupd/fwupd/issues/5042
179 lines
5.7 KiB
C
179 lines
5.7 KiB
C
/*
|
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <fwupdplugin.h>
|
|
|
|
#include "fu-uefi-dbx-common.h"
|
|
#include "fu-uefi-dbx-device.h"
|
|
|
|
struct _FuUefiDbxDevice {
|
|
FuDevice parent_instance;
|
|
};
|
|
|
|
G_DEFINE_TYPE(FuUefiDbxDevice, fu_uefi_dbx_device, FU_TYPE_DEVICE)
|
|
|
|
static gboolean
|
|
fu_uefi_dbx_device_write_firmware(FuDevice *device,
|
|
FuFirmware *firmware,
|
|
FuProgress *progress,
|
|
FwupdInstallFlags install_flags,
|
|
GError **error)
|
|
{
|
|
const guint8 *buf;
|
|
gsize bufsz = 0;
|
|
g_autoptr(GBytes) fw = NULL;
|
|
|
|
/* get default image */
|
|
fw = fu_firmware_get_bytes(firmware, error);
|
|
if (fw == NULL)
|
|
return FALSE;
|
|
|
|
/* write entire chunk to efivarfs */
|
|
fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_WRITE);
|
|
buf = g_bytes_get_data(fw, &bufsz);
|
|
if (!fu_efivar_set_data(FU_EFIVAR_GUID_SECURITY_DATABASE,
|
|
"dbx",
|
|
buf,
|
|
bufsz,
|
|
FU_EFIVAR_ATTR_APPEND_WRITE |
|
|
FU_EFIVAR_ATTR_TIME_BASED_AUTHENTICATED_WRITE_ACCESS |
|
|
FU_EFIVAR_ATTR_RUNTIME_ACCESS |
|
|
FU_EFIVAR_ATTR_BOOTSERVICE_ACCESS | FU_EFIVAR_ATTR_NON_VOLATILE,
|
|
error)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* success! */
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fu_uefi_dbx_device_set_version_number(FuDevice *device, GError **error)
|
|
{
|
|
g_autoptr(GBytes) dbx_blob = NULL;
|
|
g_autoptr(FuFirmware) dbx = fu_efi_signature_list_new();
|
|
|
|
/* use the number of checksums in the dbx as a version number, ignoring
|
|
* some owners that do not make sense */
|
|
dbx_blob = fu_efivar_get_data_bytes(FU_EFIVAR_GUID_SECURITY_DATABASE, "dbx", NULL, error);
|
|
if (dbx_blob == NULL)
|
|
return FALSE;
|
|
if (!fu_firmware_parse(dbx, dbx_blob, FWUPD_INSTALL_FLAG_NO_SEARCH, error))
|
|
return FALSE;
|
|
fu_device_set_version(device, fu_firmware_get_version(dbx));
|
|
fu_device_set_version_lowest(device, fu_firmware_get_version(dbx));
|
|
return TRUE;
|
|
}
|
|
|
|
static FuFirmware *
|
|
fu_uefi_dbx_prepare_firmware(FuDevice *device, GBytes *fw, FwupdInstallFlags flags, GError **error)
|
|
{
|
|
FuContext *ctx = fu_device_get_context(device);
|
|
g_autoptr(FuFirmware) siglist = fu_efi_signature_list_new();
|
|
|
|
/* parse dbx */
|
|
if (!fu_firmware_parse(siglist, fw, flags, error))
|
|
return NULL;
|
|
|
|
/* validate this is safe to apply */
|
|
if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
|
|
// fu_progress_set_status(progress, FWUPD_STATUS_DEVICE_VERIFY);
|
|
if (!fu_uefi_dbx_signature_list_validate(ctx,
|
|
FU_EFI_SIGNATURE_LIST(siglist),
|
|
error)) {
|
|
g_prefix_error(error,
|
|
"Blocked executable in the ESP, "
|
|
"ensure grub and shim are up to date: ");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* default blob */
|
|
return fu_firmware_new_from_bytes(fw);
|
|
}
|
|
|
|
static gboolean
|
|
fu_uefi_dbx_device_probe(FuDevice *device, GError **error)
|
|
{
|
|
g_autoptr(FuFirmware) kek = fu_efi_signature_list_new();
|
|
g_autoptr(GBytes) kek_blob = NULL;
|
|
g_autoptr(GPtrArray) sigs = NULL;
|
|
|
|
/* use each of the certificates in the KEK to generate the GUIDs */
|
|
kek_blob = fu_efivar_get_data_bytes(FU_EFIVAR_GUID_EFI_GLOBAL, "KEK", NULL, error);
|
|
if (kek_blob == NULL)
|
|
return FALSE;
|
|
if (!fu_firmware_parse(kek, kek_blob, FWUPD_INSTALL_FLAG_NONE, error))
|
|
return FALSE;
|
|
fu_device_add_instance_strup(device, "ARCH", EFI_MACHINE_TYPE_NAME);
|
|
|
|
sigs = fu_firmware_get_images(kek);
|
|
for (guint j = 0; j < sigs->len; j++) {
|
|
FuEfiSignature *sig = g_ptr_array_index(sigs, j);
|
|
g_autofree gchar *checksum = NULL;
|
|
|
|
checksum = fu_firmware_get_checksum(FU_FIRMWARE(sig), G_CHECKSUM_SHA256, error);
|
|
if (checksum == NULL)
|
|
return FALSE;
|
|
fu_device_add_instance_strup(device, "CRT", checksum);
|
|
fu_device_build_instance_id(device, NULL, "UEFI", "CRT", NULL);
|
|
fu_device_build_instance_id(device, NULL, "UEFI", "CRT", "ARCH", NULL);
|
|
}
|
|
return fu_uefi_dbx_device_set_version_number(device, error);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_dbx_device_set_progress(FuDevice *self, FuProgress *progress)
|
|
{
|
|
fu_progress_set_id(progress, G_STRLOC);
|
|
fu_progress_add_flag(progress, FU_PROGRESS_FLAG_GUESSED);
|
|
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0, "detach");
|
|
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_WRITE, 98, "write");
|
|
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_RESTART, 0, "attach");
|
|
fu_progress_add_step(progress, FWUPD_STATUS_DEVICE_BUSY, 2, "reload");
|
|
}
|
|
|
|
static void
|
|
fu_uefi_dbx_device_init(FuUefiDbxDevice *self)
|
|
{
|
|
fu_device_set_physical_id(FU_DEVICE(self), "dbx");
|
|
fu_device_set_name(FU_DEVICE(self), "UEFI dbx");
|
|
fu_device_set_summary(FU_DEVICE(self), "UEFI revocation database");
|
|
fu_device_add_vendor_id(FU_DEVICE(self), "UEFI:Linux Foundation");
|
|
fu_device_add_protocol(FU_DEVICE(self), "org.uefi.dbx");
|
|
fu_device_set_version_format(FU_DEVICE(self), FWUPD_VERSION_FORMAT_NUMBER);
|
|
fu_device_set_install_duration(FU_DEVICE(self), 1);
|
|
fu_device_add_icon(FU_DEVICE(self), "computer");
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_INTERNAL);
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_NEEDS_REBOOT);
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_ONLY_VERSION_UPGRADE);
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_SIGNED_PAYLOAD);
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_USABLE_DURING_UPDATE);
|
|
fu_device_add_parent_guid(FU_DEVICE(self), "main-system-firmware");
|
|
if (!fu_common_is_live_media())
|
|
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_dbx_device_class_init(FuUefiDbxDeviceClass *klass)
|
|
{
|
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS(klass);
|
|
klass_device->probe = fu_uefi_dbx_device_probe;
|
|
klass_device->write_firmware = fu_uefi_dbx_device_write_firmware;
|
|
klass_device->prepare_firmware = fu_uefi_dbx_prepare_firmware;
|
|
klass_device->set_progress = fu_uefi_dbx_device_set_progress;
|
|
}
|
|
|
|
FuUefiDbxDevice *
|
|
fu_uefi_dbx_device_new(FuContext *ctx)
|
|
{
|
|
FuUefiDbxDevice *self;
|
|
self = g_object_new(FU_TYPE_UEFI_DBX_DEVICE, "context", ctx, NULL);
|
|
return self;
|
|
}
|