mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-23 21:26:58 +00:00
188 lines
3.9 KiB
C
188 lines
3.9 KiB
C
/*
|
|
* Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
|
|
* Copyright (C) 2021 Norbert Kamiński <norbert.kaminski@3mdeb.com>
|
|
* Copyright (C) 2021 Michał Kopeć <michal.kopec@3mdeb.com>
|
|
* Copyright (C) 2021 Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <efivar.h>
|
|
|
|
#include "fwupd-error.h"
|
|
|
|
#include "fu-common.h"
|
|
#include "fu-efivar-impl.h"
|
|
|
|
gboolean
|
|
fu_efivar_supported_impl(GError **error)
|
|
{
|
|
if (efi_variables_supported() == 0) {
|
|
g_set_error(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"kernel efivars support missing");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
fu_efivar_delete_impl(const gchar *guid, const gchar *name, GError **error)
|
|
{
|
|
efi_guid_t guidt;
|
|
efi_str_to_guid(guid, &guidt);
|
|
|
|
if (efi_del_variable(guidt, name) == 0)
|
|
return TRUE;
|
|
|
|
g_set_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "failed to delete efivar %s", name);
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
fu_efivar_delete_with_glob_impl(const gchar *guid, const gchar *name_glob, GError **error)
|
|
{
|
|
efi_guid_t *guidt = NULL;
|
|
gchar *name = NULL;
|
|
gboolean rv = FALSE;
|
|
efi_guid_t guid_to_delete;
|
|
|
|
efi_str_to_guid(guid, &guid_to_delete);
|
|
|
|
while (efi_get_next_variable_name(&guidt, &name)) {
|
|
if (memcmp(&guid_to_delete, guidt, sizeof(guid_to_delete)) != 0)
|
|
continue;
|
|
if (!fu_common_fnmatch(name, name_glob))
|
|
continue;
|
|
rv = fu_efivar_delete(guid, name, error);
|
|
if (!rv)
|
|
break;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
static gboolean
|
|
fu_efivar_exists_guid(const gchar *guid)
|
|
{
|
|
efi_guid_t *guidt = NULL;
|
|
gchar *name = NULL;
|
|
efi_guid_t test;
|
|
|
|
efi_str_to_guid(guid, &test);
|
|
while (efi_get_next_variable_name(&guidt, &name)) {
|
|
if (memcmp(&test, guidt, sizeof(test)) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
fu_efivar_exists_impl(const gchar *guid, const gchar *name)
|
|
{
|
|
/* any name */
|
|
if (name == NULL)
|
|
return fu_efivar_exists_guid(guid);
|
|
|
|
return fu_efivar_get_data(guid, name, NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
gboolean
|
|
fu_efivar_get_data_impl(const gchar *guid,
|
|
const gchar *name,
|
|
guint8 **data,
|
|
gsize *data_sz,
|
|
guint32 *attr,
|
|
GError **error)
|
|
{
|
|
efi_guid_t guidt;
|
|
efi_str_to_guid(guid, &guidt);
|
|
return (efi_get_variable(guidt, name, data, data_sz, attr) != 0);
|
|
}
|
|
|
|
GPtrArray *
|
|
fu_efivar_get_names_impl(const gchar *guid, GError **error)
|
|
{
|
|
g_autoptr(GPtrArray) names = g_ptr_array_new_with_free_func(g_free);
|
|
efi_guid_t *guidt = NULL;
|
|
gchar *name = NULL;
|
|
efi_guid_t test;
|
|
efi_str_to_guid(guid, &test);
|
|
|
|
/* find names with matching GUID */
|
|
while (efi_get_next_variable_name(&guidt, &name)) {
|
|
if (memcmp(&test, guidt, sizeof(test)) == 0) {
|
|
g_ptr_array_add(names, g_strdup(name));
|
|
}
|
|
}
|
|
|
|
/* nothing found */
|
|
if (names->len == 0) {
|
|
g_set_error(error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "no names for GUID %s", guid);
|
|
return NULL;
|
|
}
|
|
|
|
/* success */
|
|
return g_steal_pointer(&names);
|
|
}
|
|
|
|
GFileMonitor *
|
|
fu_efivar_get_monitor_impl(const gchar *guid, const gchar *name, GError **error)
|
|
{
|
|
g_set_error_literal(error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"efivarfs monitoring not supported on FreeBSD");
|
|
return NULL;
|
|
}
|
|
|
|
guint64
|
|
fu_efivar_space_used_impl(GError **error)
|
|
{
|
|
guint64 total = 0;
|
|
efi_guid_t *guidt = NULL;
|
|
char *name = NULL;
|
|
|
|
while (efi_get_next_variable_name(&guidt, &name)) {
|
|
size_t size = 0;
|
|
if (efi_get_variable_size(*guidt, name, &size) < 0) {
|
|
g_set_error(error,
|
|
G_IO_ERROR,
|
|
G_IO_ERROR_FAILED,
|
|
"failed to get efivar size");
|
|
return G_MAXUINT64;
|
|
}
|
|
total += size;
|
|
}
|
|
|
|
/* success */
|
|
return total;
|
|
}
|
|
|
|
gboolean
|
|
fu_efivar_set_data_impl(const gchar *guid,
|
|
const gchar *name,
|
|
const guint8 *data,
|
|
gsize sz,
|
|
guint32 attr,
|
|
GError **error)
|
|
{
|
|
efi_guid_t guidt;
|
|
efi_str_to_guid(guid, &guidt);
|
|
|
|
if (efi_set_variable(guidt, name, (guint8 *)data, sz, attr) != 0) {
|
|
g_set_error(error,
|
|
G_IO_ERROR,
|
|
G_IO_ERROR_FAILED,
|
|
"failed to write data to efivar %s",
|
|
name);
|
|
return FALSE;
|
|
}
|
|
|
|
/* success */
|
|
return TRUE;
|
|
}
|