/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 | } |