Coverage Report

Created: 2025-11-11 06:44

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