Coverage Report

Created: 2025-10-13 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-dummy-efivars.c
Line
Count
Source
1
/*
2
 * Copyright 2021 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#define G_LOG_DOMAIN "FuDummyEfivars"
8
9
#include "config.h"
10
11
#include "fu-dummy-efivars.h"
12
13
typedef struct {
14
  gchar *guid;
15
  gchar *name;
16
  guint32 attr;
17
  GByteArray *buf;
18
} FuDummyEfivarsKey;
19
20
struct _FuDummyEfivars {
21
  FuEfivars parent_instance;
22
  GPtrArray *keys; /* of FuDummyEfivarsKey */
23
};
24
25
0
G_DEFINE_TYPE(FuDummyEfivars, fu_dummy_efivars, FU_TYPE_EFIVARS)
26
0
27
0
#define FU_DUMMY_EFIVARS_NVRAM_SIZE 10240 /* bytes */
28
29
static void
30
fu_dummy_efivars_key_free(FuDummyEfivarsKey *key)
31
0
{
32
0
  g_free(key->guid);
33
0
  g_free(key->name);
34
0
  g_byte_array_unref(key->buf);
35
0
  g_free(key);
36
0
}
37
38
static gboolean
39
fu_dummy_efivars_supported(FuEfivars *efivars, GError **error)
40
0
{
41
0
  return TRUE;
42
0
}
43
44
static FuDummyEfivarsKey *
45
fu_dummy_efivars_find_by_guid_name(FuDummyEfivars *self, const gchar *guid, const gchar *name)
46
0
{
47
0
  for (guint i = 0; i < self->keys->len; i++) {
48
0
    FuDummyEfivarsKey *key = g_ptr_array_index(self->keys, i);
49
0
    if (g_strcmp0(guid, key->guid) == 0 && g_strcmp0(name, key->name) == 0)
50
0
      return key;
51
0
  }
52
0
  return NULL;
53
0
}
54
55
static gboolean
56
fu_dummy_efivars_delete(FuEfivars *efivars, const gchar *guid, const gchar *name, GError **error)
57
0
{
58
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
59
0
  FuDummyEfivarsKey *key = fu_dummy_efivars_find_by_guid_name(self, guid, name);
60
0
  if (key == NULL) {
61
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOT_FOUND, "no key to delete");
62
0
    return FALSE;
63
0
  }
64
0
  g_ptr_array_remove(self->keys, key);
65
0
  return TRUE;
66
0
}
67
68
static gboolean
69
fu_dummy_efivars_delete_with_glob(FuEfivars *efivars,
70
          const gchar *guid,
71
          const gchar *name_glob,
72
          GError **error)
73
0
{
74
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
75
0
  g_autoptr(GPtrArray) keys_tmp = g_ptr_array_new();
76
0
  for (guint i = 0; i < self->keys->len; i++) {
77
0
    FuDummyEfivarsKey *key = g_ptr_array_index(self->keys, i);
78
0
    if (g_pattern_match_simple(name_glob, key->name))
79
0
      g_ptr_array_add(keys_tmp, key);
80
0
  }
81
0
  for (guint i = 0; i < keys_tmp->len; i++) {
82
0
    FuDummyEfivarsKey *key = g_ptr_array_index(keys_tmp, i);
83
0
    g_ptr_array_remove(self->keys, key);
84
0
  }
85
0
  return TRUE;
86
0
}
87
88
static gboolean
89
fu_dummy_efivars_exists_guid(FuDummyEfivars *self, const gchar *guid)
90
0
{
91
0
  for (guint i = 0; i < self->keys->len; i++) {
92
0
    FuDummyEfivarsKey *key = g_ptr_array_index(self->keys, i);
93
0
    if (g_strcmp0(guid, key->guid) == 0)
94
0
      return TRUE;
95
0
  }
96
0
  return FALSE;
97
0
}
98
99
static gboolean
100
fu_dummy_efivars_exists(FuEfivars *efivars, const gchar *guid, const gchar *name)
101
0
{
102
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
103
0
  if (name == NULL)
104
0
    return fu_dummy_efivars_exists_guid(self, guid);
105
0
  return fu_dummy_efivars_find_by_guid_name(self, guid, name) != NULL;
106
0
}
107
108
static gboolean
109
fu_dummy_efivars_get_data(FuEfivars *efivars,
110
        const gchar *guid,
111
        const gchar *name,
112
        guint8 **data,
113
        gsize *data_sz,
114
        guint32 *attr,
115
        GError **error)
116
0
{
117
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
118
0
  FuDummyEfivarsKey *key = fu_dummy_efivars_find_by_guid_name(self, guid, name);
119
0
  if (key == NULL) {
120
0
    g_set_error(error,
121
0
          FWUPD_ERROR,
122
0
          FWUPD_ERROR_NOT_FOUND,
123
0
          "%s-%s not found",
124
0
          guid,
125
0
          name);
126
0
    return FALSE;
127
0
  }
128
0
  if (data != NULL)
129
0
    *data = g_memdup2(key->buf->data, key->buf->len);
130
0
  if (data_sz != NULL)
131
0
    *data_sz = key->buf->len;
132
0
  if (attr != NULL)
133
0
    *attr = key->attr;
134
0
  return TRUE;
135
0
}
136
137
static GPtrArray *
138
fu_dummy_efivars_get_names(FuEfivars *efivars, const gchar *guid, GError **error)
139
0
{
140
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
141
0
  g_autoptr(GPtrArray) names = g_ptr_array_new_with_free_func(g_free);
142
0
  for (guint i = 0; i < self->keys->len; i++) {
143
0
    FuDummyEfivarsKey *key = g_ptr_array_index(self->keys, i);
144
0
    if (g_strcmp0(guid, key->guid) == 0)
145
0
      g_ptr_array_add(names, g_strdup(key->name));
146
0
  }
147
0
  return g_steal_pointer(&names);
148
0
}
149
150
static guint64
151
fu_dummy_efivars_space_used(FuEfivars *efivars, GError **error)
152
0
{
153
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
154
0
  guint64 total = 0;
155
0
  for (guint i = 0; i < self->keys->len; i++) {
156
0
    FuDummyEfivarsKey *key = g_ptr_array_index(self->keys, i);
157
0
    total += 0x20 + strlen(key->name) + key->buf->len;
158
0
  }
159
0
  return total;
160
0
}
161
162
static guint64
163
fu_dummy_efivars_space_free(FuEfivars *efivars, GError **error)
164
0
{
165
0
  guint64 total;
166
167
0
  total = fu_dummy_efivars_space_used(efivars, error);
168
0
  if (total == G_MAXUINT64)
169
0
    return G_MAXUINT64;
170
0
  return FU_DUMMY_EFIVARS_NVRAM_SIZE - total;
171
0
}
172
173
static gboolean
174
fu_dummy_efivars_set_data(FuEfivars *efivars,
175
        const gchar *guid,
176
        const gchar *name,
177
        const guint8 *data,
178
        gsize sz,
179
        guint32 attr,
180
        GError **error)
181
0
{
182
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(efivars);
183
0
  FuDummyEfivarsKey *key = fu_dummy_efivars_find_by_guid_name(self, guid, name);
184
0
  if (key == NULL) {
185
0
    key = g_new0(FuDummyEfivarsKey, 1);
186
0
    key->guid = g_strdup(guid);
187
0
    key->name = g_strdup(name);
188
0
    key->buf = g_byte_array_new();
189
0
    g_ptr_array_add(self->keys, key);
190
0
  }
191
0
  key->attr = attr;
192
0
  g_byte_array_set_size(key->buf, 0);
193
0
  g_byte_array_append(key->buf, data, sz);
194
0
  return TRUE;
195
0
}
196
197
static void
198
fu_dummy_efivars_init(FuDummyEfivars *self)
199
0
{
200
0
  self->keys = g_ptr_array_new_with_free_func((GDestroyNotify)fu_dummy_efivars_key_free);
201
0
}
202
203
static void
204
fu_dummy_efivars_finalize(GObject *object)
205
0
{
206
0
  FuDummyEfivars *self = FU_DUMMY_EFIVARS(object);
207
0
  g_ptr_array_unref(self->keys);
208
0
  G_OBJECT_CLASS(fu_dummy_efivars_parent_class)->finalize(object);
209
0
}
210
211
static void
212
fu_dummy_efivars_class_init(FuDummyEfivarsClass *klass)
213
0
{
214
0
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
215
0
  FuEfivarsClass *efivars_class = FU_EFIVARS_CLASS(klass);
216
0
  efivars_class->supported = fu_dummy_efivars_supported;
217
0
  efivars_class->space_used = fu_dummy_efivars_space_used;
218
0
  efivars_class->space_free = fu_dummy_efivars_space_free;
219
0
  efivars_class->exists = fu_dummy_efivars_exists;
220
0
  efivars_class->get_data = fu_dummy_efivars_get_data;
221
0
  efivars_class->set_data = fu_dummy_efivars_set_data;
222
0
  efivars_class->delete = fu_dummy_efivars_delete;
223
0
  efivars_class->delete_with_glob = fu_dummy_efivars_delete_with_glob;
224
0
  efivars_class->get_names = fu_dummy_efivars_get_names;
225
0
  object_class->finalize = fu_dummy_efivars_finalize;
226
0
}
227
228
FuEfivars *
229
fu_dummy_efivars_new(void)
230
0
{
231
0
  return FU_EFIVARS(g_object_new(FU_TYPE_DUMMY_EFIVARS, NULL));
232
0
}