/src/fwupd/libfwupdplugin/fu-efi-section.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2020 Richard Hughes <richard@hughsie.com> |
3 | | * |
4 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
5 | | */ |
6 | | |
7 | 40.1k | #define G_LOG_DOMAIN "FuEfiSection" |
8 | | |
9 | | #include "config.h" |
10 | | |
11 | | #include "fu-byte-array.h" |
12 | | #include "fu-common.h" |
13 | | #include "fu-efi-common.h" |
14 | | #include "fu-efi-lz77-decompressor.h" |
15 | | #include "fu-efi-section.h" |
16 | | #include "fu-efi-struct.h" |
17 | | #include "fu-efi-volume.h" |
18 | | #include "fu-input-stream.h" |
19 | | #include "fu-lzma-common.h" |
20 | | #include "fu-partial-input-stream.h" |
21 | | #include "fu-string.h" |
22 | | |
23 | | /** |
24 | | * FuEfiSection: |
25 | | * |
26 | | * A UEFI firmware section. |
27 | | * |
28 | | * See also: [class@FuFirmware] |
29 | | */ |
30 | | |
31 | | typedef struct { |
32 | | guint8 type; |
33 | | gchar *user_interface; |
34 | | } FuEfiSectionPrivate; |
35 | | |
36 | | G_DEFINE_TYPE_WITH_PRIVATE(FuEfiSection, fu_efi_section, FU_TYPE_FIRMWARE) |
37 | 155k | #define GET_PRIVATE(o) (fu_efi_section_get_instance_private(o)) |
38 | | |
39 | | static void |
40 | | fu_efi_section_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn) |
41 | 0 | { |
42 | 0 | FuEfiSection *self = FU_EFI_SECTION(firmware); |
43 | 0 | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
44 | |
|
45 | 0 | fu_xmlb_builder_insert_kx(bn, "type", priv->type); |
46 | 0 | if (priv->user_interface != NULL) |
47 | 0 | fu_xmlb_builder_insert_kv(bn, "user_interface", priv->user_interface); |
48 | 0 | if (flags & FU_FIRMWARE_EXPORT_FLAG_INCLUDE_DEBUG) { |
49 | 0 | fu_xmlb_builder_insert_kv(bn, |
50 | 0 | "name", |
51 | 0 | fu_efi_guid_to_name(fu_firmware_get_id(firmware))); |
52 | 0 | fu_xmlb_builder_insert_kv(bn, |
53 | 0 | "type_name", |
54 | 0 | fu_efi_section_type_to_string(priv->type)); |
55 | 0 | } |
56 | 0 | } |
57 | | |
58 | | static gboolean |
59 | | fu_efi_section_parse_volume_image(FuEfiSection *self, |
60 | | GInputStream *stream, |
61 | | FuFirmwareParseFlags flags, |
62 | | GError **error) |
63 | 1.34k | { |
64 | 1.34k | g_autoptr(FuFirmware) img = fu_efi_volume_new(); |
65 | 1.34k | if (!fu_firmware_parse_stream(img, |
66 | 1.34k | stream, |
67 | 1.34k | 0x0, |
68 | 1.34k | flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH, |
69 | 1.34k | error)) { |
70 | 1.24k | return FALSE; |
71 | 1.24k | } |
72 | 98 | fu_firmware_add_image(FU_FIRMWARE(self), img); |
73 | 98 | return TRUE; |
74 | 1.34k | } |
75 | | |
76 | | static gboolean |
77 | | fu_efi_section_parse_lzma_sections(FuEfiSection *self, |
78 | | GInputStream *stream, |
79 | | FuFirmwareParseFlags flags, |
80 | | GError **error) |
81 | 0 | { |
82 | 0 | g_autoptr(GBytes) blob = NULL; |
83 | 0 | g_autoptr(GBytes) blob_uncomp = NULL; |
84 | 0 | g_autoptr(GInputStream) stream_uncomp = NULL; |
85 | | |
86 | | /* parse all sections */ |
87 | 0 | blob = fu_input_stream_read_bytes(stream, 0, G_MAXSIZE, NULL, error); |
88 | 0 | if (blob == NULL) |
89 | 0 | return FALSE; |
90 | 0 | blob_uncomp = fu_lzma_decompress_bytes(blob, 128 * 1024 * 1024, error); |
91 | 0 | if (blob_uncomp == NULL) { |
92 | 0 | g_prefix_error(error, "failed to decompress: "); |
93 | 0 | return FALSE; |
94 | 0 | } |
95 | 0 | stream_uncomp = g_memory_input_stream_new_from_bytes(blob_uncomp); |
96 | 0 | if (!fu_efi_parse_sections(FU_FIRMWARE(self), stream_uncomp, 0, flags, error)) { |
97 | 0 | g_prefix_error(error, "failed to parse sections: "); |
98 | 0 | return FALSE; |
99 | 0 | } |
100 | 0 | return TRUE; |
101 | 0 | } |
102 | | |
103 | | static gboolean |
104 | | fu_efi_section_parse_user_interface(FuEfiSection *self, |
105 | | GInputStream *stream, |
106 | | FuFirmwareParseFlags flags, |
107 | | GError **error) |
108 | 1.07k | { |
109 | 1.07k | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
110 | 1.07k | g_autoptr(GByteArray) buf = NULL; |
111 | | |
112 | 1.07k | if (priv->user_interface != NULL) { |
113 | 0 | g_set_error(error, |
114 | 0 | FWUPD_ERROR, |
115 | 0 | FWUPD_ERROR_INTERNAL, |
116 | 0 | "UI already set as %s for section", |
117 | 0 | priv->user_interface); |
118 | 0 | return FALSE; |
119 | 0 | } |
120 | 1.07k | buf = fu_input_stream_read_byte_array(stream, 0x0, G_MAXSIZE, NULL, error); |
121 | 1.07k | if (buf == NULL) |
122 | 6 | return FALSE; |
123 | 1.06k | priv->user_interface = fu_utf16_to_utf8_byte_array(buf, G_LITTLE_ENDIAN, error); |
124 | 1.06k | if (priv->user_interface == NULL) |
125 | 69 | return FALSE; |
126 | 998 | return TRUE; |
127 | 1.06k | } |
128 | | |
129 | | static gboolean |
130 | | fu_efi_section_parse_version(FuEfiSection *self, |
131 | | GInputStream *stream, |
132 | | FuFirmwareParseFlags flags, |
133 | | GError **error) |
134 | 1.36k | { |
135 | 1.36k | guint16 version_raw = 0; |
136 | 1.36k | g_autofree gchar *version = NULL; |
137 | 1.36k | g_autoptr(GByteArray) buf = NULL; |
138 | | |
139 | 1.36k | if (!fu_input_stream_read_u16(stream, 0x0, &version_raw, G_LITTLE_ENDIAN, error)) { |
140 | 7 | g_prefix_error(error, "failed to read raw version: "); |
141 | 7 | return FALSE; |
142 | 7 | } |
143 | 1.35k | fu_firmware_set_version_raw(FU_FIRMWARE(self), version_raw); |
144 | 1.35k | buf = fu_input_stream_read_byte_array(stream, sizeof(guint16), G_MAXSIZE, NULL, error); |
145 | 1.35k | if (buf == NULL) { |
146 | 13 | g_prefix_error(error, "failed to read version buffer: "); |
147 | 13 | return FALSE; |
148 | 13 | } |
149 | 1.34k | version = fu_utf16_to_utf8_byte_array(buf, G_LITTLE_ENDIAN, error); |
150 | 1.34k | if (version == NULL) { |
151 | 23 | g_prefix_error(error, "failed to convert to UTF-16: "); |
152 | 23 | return FALSE; |
153 | 23 | } |
154 | 1.32k | fu_firmware_set_version(FU_FIRMWARE(self), version); /* nocheck:set-version */ |
155 | 1.32k | return TRUE; |
156 | 1.34k | } |
157 | | |
158 | | static gboolean |
159 | | fu_efi_section_parse_compression_sections(FuEfiSection *self, |
160 | | GInputStream *stream, |
161 | | FuFirmwareParseFlags flags, |
162 | | GError **error) |
163 | 3.46k | { |
164 | 3.46k | g_autoptr(GByteArray) st = NULL; |
165 | 3.46k | st = fu_struct_efi_section_compression_parse_stream(stream, 0x0, error); |
166 | 3.46k | if (st == NULL) |
167 | 27 | return FALSE; |
168 | 3.43k | if (fu_struct_efi_section_compression_get_compression_type(st) == |
169 | 3.43k | FU_EFI_COMPRESSION_TYPE_NOT_COMPRESSED) { |
170 | 679 | if (!fu_efi_parse_sections(FU_FIRMWARE(self), stream, st->len, flags, error)) { |
171 | 378 | g_prefix_error(error, "failed to parse sections: "); |
172 | 378 | return FALSE; |
173 | 378 | } |
174 | 2.75k | } else { |
175 | 2.75k | g_autoptr(FuFirmware) lz77_decompressor = fu_efi_lz77_decompressor_new(); |
176 | 2.75k | g_autoptr(GInputStream) lz77_stream = NULL; |
177 | 2.75k | if (!fu_firmware_parse_stream(lz77_decompressor, stream, st->len, flags, error)) |
178 | 1.27k | return FALSE; |
179 | 1.48k | lz77_stream = fu_firmware_get_stream(lz77_decompressor, error); |
180 | 1.48k | if (lz77_stream == NULL) |
181 | 0 | return FALSE; |
182 | 1.48k | if (!fu_efi_parse_sections(FU_FIRMWARE(self), lz77_stream, 0, flags, error)) { |
183 | 643 | g_prefix_error(error, "failed to parse sections: "); |
184 | 643 | return FALSE; |
185 | 643 | } |
186 | 1.48k | } |
187 | 1.14k | return TRUE; |
188 | 3.43k | } |
189 | | |
190 | | static const gchar * |
191 | | fu_efi_section_freeform_subtype_guid_to_string(const gchar *guid) |
192 | 302 | { |
193 | 302 | struct { |
194 | 302 | const gchar *guid; |
195 | 302 | const gchar *str; |
196 | 302 | } freeform_guids[] = { |
197 | 302 | {"00781ca1-5de3-405f-abb8-379c3c076984", "AmiRomLayoutGuid"}, |
198 | 302 | {"20feebde-e739-420e-ae31-77e2876508c0", "IntelRstOprom"}, |
199 | 302 | {"224d6eb4-307f-45ba-9dc3-fe9fc6b38148", "IntelEntRaidController"}, |
200 | 302 | {"2ebe0275-6458-4af9-91ed-d3f4edb100aa", "SignOn"}, |
201 | 302 | {"380b6b4f-1454-41f2-a6d3-61d1333e8cb4", "IntelGop"}, |
202 | 302 | {"50339d20-c90a-4bb2-9aff-d8a11b23bc15", "I219?Oprom"}, |
203 | 302 | {"88a15a4f-977d-4682-b17c-da1f316c1f32", "RomLayout"}, |
204 | 302 | {"9bec7109-6d7a-413a-8e4b-019ced0503e1", "AmiBoardInfoSectionGuid"}, |
205 | 302 | {"ab56dc60-0057-11da-a8db-000102eee626", "?BuildData"}, |
206 | 302 | {"c5a4306e-e247-4ecd-a9d8-5b1985d3dcda", "?Oprom"}, |
207 | 302 | {"c9352cc3-a354-44e5-8776-b2ed8dd781ec", "IntelEntRaidController"}, |
208 | 302 | {"d46346ca-82a1-4cde-9546-77c86f893888", "?Oprom"}, |
209 | 302 | {"e095affe-d4cd-4289-9b48-28f64e3d781d", "IntelRstOprom"}, |
210 | 302 | {"fe612b72-203c-47b1-8560-a66d946eb371", "setupdata"}, |
211 | 302 | {NULL, NULL}, |
212 | 302 | }; |
213 | 4.53k | for (guint i = 0; freeform_guids[i].guid != NULL; i++) { |
214 | 4.22k | if (g_strcmp0(guid, freeform_guids[i].guid) == 0) |
215 | 0 | return freeform_guids[i].str; |
216 | 4.22k | } |
217 | 302 | return NULL; |
218 | 302 | } |
219 | | |
220 | | static gboolean |
221 | | fu_efi_section_parse_freeform_subtype_guid(FuEfiSection *self, |
222 | | GInputStream *stream, |
223 | | FuFirmwareParseFlags flags, |
224 | | GError **error) |
225 | 323 | { |
226 | 323 | const gchar *guid_ui; |
227 | 323 | g_autofree gchar *guid_str = NULL; |
228 | 323 | g_autoptr(GByteArray) st = NULL; |
229 | | |
230 | 323 | st = fu_struct_efi_section_freeform_subtype_guid_parse_stream(stream, 0x0, error); |
231 | 323 | if (st == NULL) |
232 | 21 | return FALSE; |
233 | | |
234 | | /* no idea */ |
235 | 302 | guid_str = fwupd_guid_to_string(fu_struct_efi_section_freeform_subtype_guid_get_guid(st), |
236 | 302 | FWUPD_GUID_FLAG_MIXED_ENDIAN); |
237 | 302 | guid_ui = fu_efi_section_freeform_subtype_guid_to_string(guid_str); |
238 | 302 | if (guid_ui != NULL) { |
239 | 0 | g_debug("ignoring FREEFORM_SUBTYPE_GUID %s [%s]", guid_str, guid_ui); |
240 | 0 | return TRUE; |
241 | 0 | } |
242 | 302 | g_debug("unknown FREEFORM_SUBTYPE_GUID %s", guid_str); |
243 | 302 | return TRUE; |
244 | 302 | } |
245 | | |
246 | | static gboolean |
247 | | fu_efi_section_parse(FuFirmware *firmware, |
248 | | GInputStream *stream, |
249 | | FuFirmwareParseFlags flags, |
250 | | GError **error) |
251 | 48.6k | { |
252 | 48.6k | FuEfiSection *self = FU_EFI_SECTION(firmware); |
253 | 48.6k | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
254 | 48.6k | gsize offset = 0; |
255 | 48.6k | gsize streamsz = 0; |
256 | 48.6k | guint32 size; |
257 | 48.6k | g_autoptr(GByteArray) st = NULL; |
258 | 48.6k | g_autoptr(GInputStream) partial_stream = NULL; |
259 | | |
260 | | /* parse */ |
261 | 48.6k | st = fu_struct_efi_section_parse_stream(stream, offset, error); |
262 | 48.6k | if (st == NULL) |
263 | 199 | return FALSE; |
264 | | |
265 | | /* use extended size */ |
266 | 48.4k | if (fu_struct_efi_section_get_size(st) == 0xFFFFFF) { |
267 | 1.30k | fu_struct_efi_section_unref(st); |
268 | 1.30k | st = fu_struct_efi_section2_parse_stream(stream, offset, error); |
269 | 1.30k | if (st == NULL) |
270 | 23 | return FALSE; |
271 | 1.28k | size = fu_struct_efi_section2_get_extended_size(st); |
272 | 47.1k | } else { |
273 | 47.1k | size = fu_struct_efi_section_get_size(st); |
274 | 47.1k | } |
275 | 48.3k | if (size < FU_STRUCT_EFI_SECTION_SIZE) { |
276 | 432 | g_set_error(error, |
277 | 432 | FWUPD_ERROR, |
278 | 432 | FWUPD_ERROR_INTERNAL, |
279 | 432 | "invalid section size, got 0x%x", |
280 | 432 | (guint)size); |
281 | 432 | return FALSE; |
282 | 432 | } |
283 | | |
284 | | /* sanity check */ |
285 | 47.9k | if (!fu_input_stream_size(stream, &streamsz, error)) |
286 | 0 | return FALSE; |
287 | 47.9k | if (size > streamsz) { |
288 | 408 | g_set_error(error, |
289 | 408 | FWUPD_ERROR, |
290 | 408 | FWUPD_ERROR_INTERNAL, |
291 | 408 | "invalid section size, got 0x%x from stream of size 0x%x", |
292 | 408 | (guint)size, |
293 | 408 | (guint)streamsz); |
294 | 408 | return FALSE; |
295 | 408 | } |
296 | | |
297 | | /* name */ |
298 | 47.5k | priv->type = fu_struct_efi_section_get_type(st); |
299 | 47.5k | if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED) { |
300 | 7.29k | g_autofree gchar *guid_str = NULL; |
301 | 7.29k | g_autoptr(GByteArray) st_def = NULL; |
302 | 7.29k | st_def = fu_struct_efi_section_guid_defined_parse_stream(stream, st->len, error); |
303 | 7.29k | if (st_def == NULL) |
304 | 23 | return FALSE; |
305 | 7.27k | guid_str = fwupd_guid_to_string(fu_struct_efi_section_guid_defined_get_name(st_def), |
306 | 7.27k | FWUPD_GUID_FLAG_MIXED_ENDIAN); |
307 | 7.27k | fu_firmware_set_id(firmware, guid_str); |
308 | 7.27k | if (fu_struct_efi_section_guid_defined_get_offset(st_def) < st_def->len) { |
309 | 18 | g_set_error(error, |
310 | 18 | FWUPD_ERROR, |
311 | 18 | FWUPD_ERROR_INTERNAL, |
312 | 18 | "invalid section size, got 0x%x", |
313 | 18 | (guint)fu_struct_efi_section_guid_defined_get_offset(st_def)); |
314 | 18 | return FALSE; |
315 | 18 | } |
316 | 7.25k | offset += fu_struct_efi_section_guid_defined_get_offset(st_def) - st->len; |
317 | 7.25k | } |
318 | | |
319 | | /* create blob */ |
320 | 47.5k | offset += st->len; |
321 | 47.5k | partial_stream = fu_partial_input_stream_new(stream, offset, size - offset, error); |
322 | 47.5k | if (partial_stream == NULL) { |
323 | 1 | g_prefix_error(error, "failed to cut data: "); |
324 | 1 | return FALSE; |
325 | 1 | } |
326 | 47.5k | fu_firmware_set_offset(firmware, offset); |
327 | 47.5k | fu_firmware_set_size(firmware, size); |
328 | 47.5k | if (!fu_firmware_set_stream(firmware, partial_stream, error)) |
329 | 101 | return FALSE; |
330 | | |
331 | | /* nested volume */ |
332 | 47.4k | if (priv->type == FU_EFI_SECTION_TYPE_VOLUME_IMAGE) { |
333 | 1.34k | if (!fu_efi_section_parse_volume_image(self, partial_stream, flags, error)) { |
334 | 1.24k | g_prefix_error(error, "failed to parse nested volume: "); |
335 | 1.24k | return FALSE; |
336 | 1.24k | } |
337 | 46.0k | } else if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED && |
338 | 46.0k | g_strcmp0(fu_firmware_get_id(firmware), FU_EFI_SECTION_GUID_LZMA_COMPRESS) == |
339 | 7.25k | 0) { |
340 | 0 | if (!fu_efi_section_parse_lzma_sections(self, partial_stream, flags, error)) { |
341 | 0 | g_prefix_error(error, "failed to parse lzma section: "); |
342 | 0 | return FALSE; |
343 | 0 | } |
344 | 46.0k | } else if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED && |
345 | 46.0k | g_strcmp0(fu_firmware_get_id(firmware), |
346 | 7.25k | "ced4eac6-49f3-4c12-a597-fc8c33447691") == 0) { |
347 | 37 | g_debug("ignoring %s [0x%x] EFI section as self test", |
348 | 37 | fu_efi_section_type_to_string(priv->type), |
349 | 37 | priv->type); |
350 | 46.0k | } else if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED) { |
351 | 7.21k | g_warning("no idea how to decompress encapsulation section of type %s", |
352 | 7.21k | fu_firmware_get_id(firmware)); |
353 | 38.8k | } else if (priv->type == FU_EFI_SECTION_TYPE_USER_INTERFACE) { |
354 | 1.07k | if (!fu_efi_section_parse_user_interface(self, partial_stream, flags, error)) { |
355 | 75 | g_prefix_error(error, "failed to parse user interface: "); |
356 | 75 | return FALSE; |
357 | 75 | } |
358 | 37.7k | } else if (priv->type == FU_EFI_SECTION_TYPE_VERSION) { |
359 | 1.36k | if (!fu_efi_section_parse_version(self, partial_stream, flags, error)) { |
360 | 43 | g_prefix_error(error, "failed to parse version: "); |
361 | 43 | return FALSE; |
362 | 43 | } |
363 | 36.3k | } else if (priv->type == FU_EFI_SECTION_TYPE_COMPRESSION) { |
364 | 3.46k | if (!fu_efi_section_parse_compression_sections(self, |
365 | 3.46k | partial_stream, |
366 | 3.46k | flags, |
367 | 3.46k | error)) { |
368 | 2.31k | g_prefix_error(error, "failed to parse compression: "); |
369 | 2.31k | return FALSE; |
370 | 2.31k | } |
371 | 32.9k | } else if (priv->type == FU_EFI_SECTION_TYPE_FREEFORM_SUBTYPE_GUID) { |
372 | 323 | if (!fu_efi_section_parse_freeform_subtype_guid(self, |
373 | 323 | partial_stream, |
374 | 323 | flags, |
375 | 323 | error)) { |
376 | 21 | g_prefix_error(error, "failed to parse compression: "); |
377 | 21 | return FALSE; |
378 | 21 | } |
379 | 32.5k | } else if (priv->type == FU_EFI_SECTION_TYPE_PEI_DEPEX || |
380 | 32.5k | priv->type == FU_EFI_SECTION_TYPE_DXE_DEPEX || |
381 | 32.5k | priv->type == FU_EFI_SECTION_TYPE_MM_DEPEX || |
382 | 32.5k | priv->type == FU_EFI_SECTION_TYPE_PE32 || priv->type == FU_EFI_SECTION_TYPE_TE || |
383 | 32.5k | priv->type == FU_EFI_SECTION_TYPE_RAW) { |
384 | 11.0k | g_debug("ignoring %s [0x%x] EFI section", |
385 | 11.0k | fu_efi_section_type_to_string(priv->type), |
386 | 11.0k | priv->type); |
387 | 21.5k | } else { |
388 | 21.5k | g_warning("no idea how to parse %s [0x%x] EFI section", |
389 | 21.5k | fu_efi_section_type_to_string(priv->type), |
390 | 21.5k | priv->type); |
391 | 21.5k | } |
392 | | |
393 | | /* success */ |
394 | 43.6k | return TRUE; |
395 | 47.4k | } |
396 | | |
397 | | static GByteArray * |
398 | | fu_efi_section_write(FuFirmware *firmware, GError **error) |
399 | 8.24k | { |
400 | 8.24k | FuEfiSection *self = FU_EFI_SECTION(firmware); |
401 | 8.24k | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
402 | 8.24k | g_autoptr(GByteArray) buf = fu_struct_efi_section_new(); |
403 | 8.24k | g_autoptr(GBytes) blob = NULL; |
404 | | |
405 | | /* simple blob for now */ |
406 | 8.24k | blob = fu_firmware_get_bytes_with_patches(firmware, error); |
407 | 8.24k | if (blob == NULL) |
408 | 349 | return NULL; |
409 | | |
410 | | /* header */ |
411 | 7.89k | if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED) { |
412 | 1.69k | fwupd_guid_t guid = {0x0}; |
413 | 1.69k | g_autoptr(GByteArray) st_def = fu_struct_efi_section_guid_defined_new(); |
414 | 1.69k | if (!fwupd_guid_from_string(fu_firmware_get_id(firmware), |
415 | 1.69k | &guid, |
416 | 1.69k | FWUPD_GUID_FLAG_MIXED_ENDIAN, |
417 | 1.69k | error)) |
418 | 0 | return NULL; |
419 | 1.69k | fu_struct_efi_section_guid_defined_set_name(st_def, &guid); |
420 | 1.69k | fu_struct_efi_section_guid_defined_set_offset(st_def, buf->len + st_def->len); |
421 | 1.69k | g_byte_array_append(buf, st_def->data, st_def->len); |
422 | 1.69k | } |
423 | 7.89k | fu_struct_efi_section_set_type(buf, priv->type); |
424 | 7.89k | fu_struct_efi_section_set_size(buf, buf->len + g_bytes_get_size(blob)); |
425 | | |
426 | | /* blob */ |
427 | 7.89k | fu_byte_array_append_bytes(buf, blob); |
428 | 7.89k | return g_steal_pointer(&buf); |
429 | 7.89k | } |
430 | | |
431 | | static gboolean |
432 | | fu_efi_section_build(FuFirmware *firmware, XbNode *n, GError **error) |
433 | 0 | { |
434 | 0 | FuEfiSection *self = FU_EFI_SECTION(firmware); |
435 | 0 | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
436 | 0 | const gchar *str; |
437 | 0 | guint64 tmp; |
438 | | |
439 | | /* simple properties */ |
440 | 0 | tmp = xb_node_query_text_as_uint(n, "type", NULL); |
441 | 0 | if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT8) |
442 | 0 | priv->type = tmp; |
443 | 0 | str = xb_node_query_text(n, "user_interface", NULL); |
444 | 0 | if (str != NULL) { |
445 | 0 | if (priv->user_interface != NULL) { |
446 | 0 | g_set_error(error, |
447 | 0 | FWUPD_ERROR, |
448 | 0 | FWUPD_ERROR_INTERNAL, |
449 | 0 | "UI already set as %s for section", |
450 | 0 | priv->user_interface); |
451 | 0 | return FALSE; |
452 | 0 | } |
453 | 0 | priv->user_interface = g_strdup(str); |
454 | 0 | } |
455 | | |
456 | | /* success */ |
457 | 0 | return TRUE; |
458 | 0 | } |
459 | | |
460 | | static void |
461 | | fu_efi_section_init(FuEfiSection *self) |
462 | 48.6k | { |
463 | 48.6k | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
464 | 48.6k | priv->type = FU_EFI_SECTION_TYPE_RAW; |
465 | 48.6k | fu_firmware_set_images_max(FU_FIRMWARE(self), |
466 | 48.6k | g_getenv("FWUPD_FUZZER_RUNNING") != NULL ? 10 : 2000); |
467 | 48.6k | fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_NO_AUTO_DETECTION); |
468 | | // fu_firmware_set_alignment (FU_FIRMWARE (self), FU_FIRMWARE_ALIGNMENT_8); |
469 | 48.6k | g_type_ensure(FU_TYPE_EFI_VOLUME); |
470 | 48.6k | } |
471 | | |
472 | | static void |
473 | | fu_efi_section_finalize(GObject *object) |
474 | 48.6k | { |
475 | 48.6k | FuEfiSection *self = FU_EFI_SECTION(object); |
476 | 48.6k | FuEfiSectionPrivate *priv = GET_PRIVATE(self); |
477 | 48.6k | g_free(priv->user_interface); |
478 | 48.6k | G_OBJECT_CLASS(fu_efi_section_parent_class)->finalize(object); |
479 | 48.6k | } |
480 | | |
481 | | static void |
482 | | fu_efi_section_class_init(FuEfiSectionClass *klass) |
483 | 2 | { |
484 | 2 | FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass); |
485 | 2 | GObjectClass *object_class = G_OBJECT_CLASS(klass); |
486 | 2 | object_class->finalize = fu_efi_section_finalize; |
487 | 2 | firmware_class->parse = fu_efi_section_parse; |
488 | 2 | firmware_class->write = fu_efi_section_write; |
489 | 2 | firmware_class->build = fu_efi_section_build; |
490 | 2 | firmware_class->export = fu_efi_section_export; |
491 | 2 | } |
492 | | |
493 | | /** |
494 | | * fu_efi_section_new: |
495 | | * |
496 | | * Creates a new #FuFirmware |
497 | | * |
498 | | * Since: 2.0.0 |
499 | | **/ |
500 | | FuFirmware * |
501 | | fu_efi_section_new(void) |
502 | 48.6k | { |
503 | 48.6k | return FU_FIRMWARE(g_object_new(FU_TYPE_EFI_SECTION, NULL)); |
504 | 48.6k | } |