Coverage Report

Created: 2026-09-14 07:00

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
9.61k
#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-memory-input-stream.h"
21
#include "fu-partial-input-stream.h"
22
#include "fu-string.h"
23
24
/**
25
 * FuEfiSection:
26
 *
27
 * A UEFI firmware section.
28
 *
29
 * See also: [class@FuFirmware]
30
 */
31
32
typedef struct {
33
  guint8 type;
34
  gchar *user_interface;
35
} FuEfiSectionPrivate;
36
37
186k
G_DEFINE_TYPE_WITH_PRIVATE(FuEfiSection, fu_efi_section, FU_TYPE_FIRMWARE)
38
187k
#define GET_PRIVATE(o) (fu_efi_section_get_instance_private(o))
39
40
static void
41
fu_efi_section_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
42
0
{
43
0
  FuEfiSection *self = FU_EFI_SECTION(firmware);
44
0
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
45
46
0
  fu_xmlb_builder_insert_kx(bn, "type", priv->type);
47
0
  if (priv->user_interface != NULL)
48
0
    fu_xmlb_builder_insert_kv(bn, "user_interface", priv->user_interface);
49
0
  if (flags & FU_FIRMWARE_EXPORT_FLAG_INCLUDE_DEBUG) {
50
0
    fu_xmlb_builder_insert_kv(bn,
51
0
            "name",
52
0
            fu_efi_guid_to_name(fu_firmware_get_id(firmware)));
53
0
    fu_xmlb_builder_insert_kv(bn,
54
0
            "type_name",
55
0
            fu_efi_section_type_to_string(priv->type));
56
0
  }
57
0
}
58
59
static gboolean
60
fu_efi_section_parse_volume_image(FuEfiSection *self,
61
          FuInputStream *stream,
62
          FuFirmwareParseFlags flags,
63
          GError **error)
64
1.78k
{
65
1.78k
  g_autoptr(FuFirmware) img = fu_efi_volume_new();
66
1.78k
  if (!fu_firmware_parse_stream(img,
67
1.78k
              stream,
68
1.78k
              0x0,
69
1.78k
              flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH,
70
1.78k
              error)) {
71
1.41k
    return FALSE;
72
1.41k
  }
73
379
  return fu_firmware_add_image(FU_FIRMWARE(self), img, error);
74
1.78k
}
75
76
static gboolean
77
fu_efi_section_parse_lzma_sections(FuEfiSection *self,
78
           FuInputStream *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(FuInputStream) 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 * FU_MB, error);
91
0
  if (blob_uncomp == NULL) {
92
0
    g_prefix_error_literal(error, "failed to decompress: ");
93
0
    return FALSE;
94
0
  }
95
0
  stream_uncomp = fu_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_literal(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
            FuInputStream *stream,
106
            FuFirmwareParseFlags flags,
107
            GError **error)
108
790
{
109
790
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
110
790
  g_autoptr(GByteArray) buf = NULL;
111
112
790
  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
790
  buf = fu_input_stream_read_byte_array(stream, 0x0, G_MAXSIZE, NULL, error);
121
790
  if (buf == NULL)
122
7
    return FALSE;
123
783
  priv->user_interface = fu_utf16_to_utf8_byte_array(buf, G_LITTLE_ENDIAN, error);
124
783
  if (priv->user_interface == NULL)
125
76
    return FALSE;
126
707
  return TRUE;
127
783
}
128
129
static gboolean
130
fu_efi_section_parse_version(FuEfiSection *self,
131
           FuInputStream *stream,
132
           FuFirmwareParseFlags flags,
133
           GError **error)
134
1.58k
{
135
1.58k
  guint16 version_raw = 0;
136
1.58k
  g_autofree gchar *version = NULL;
137
1.58k
  g_autoptr(GByteArray) buf = NULL;
138
139
1.58k
  if (!fu_input_stream_read_u16(stream, 0x0, &version_raw, G_LITTLE_ENDIAN, error)) {
140
8
    g_prefix_error_literal(error, "failed to read raw version: ");
141
8
    return FALSE;
142
8
  }
143
1.57k
  fu_firmware_set_version_raw(FU_FIRMWARE(self), version_raw);
144
1.57k
  buf = fu_input_stream_read_byte_array(stream, sizeof(guint16), G_MAXSIZE, NULL, error);
145
1.57k
  if (buf == NULL) {
146
4
    g_prefix_error_literal(error, "failed to read version buffer: ");
147
4
    return FALSE;
148
4
  }
149
1.57k
  version = fu_utf16_to_utf8_byte_array(buf, G_LITTLE_ENDIAN, error);
150
1.57k
  if (version == NULL) {
151
43
    g_prefix_error_literal(error, "failed to convert to UTF-16: ");
152
43
    return FALSE;
153
43
  }
154
1.52k
  fu_firmware_set_version(FU_FIRMWARE(self), version); /* nocheck:set-version */
155
1.52k
  return TRUE;
156
1.57k
}
157
158
static gboolean
159
fu_efi_section_parse_compression_sections(FuEfiSection *self,
160
            FuInputStream *stream,
161
            FuFirmwareParseFlags flags,
162
            GError **error)
163
3.62k
{
164
3.62k
  g_autoptr(FuStructEfiSectionCompression) st = NULL;
165
3.62k
  st = fu_struct_efi_section_compression_parse_stream(stream, 0x0, error);
166
3.62k
  if (st == NULL)
167
24
    return FALSE;
168
3.60k
  if (fu_struct_efi_section_compression_get_compression_type(st) ==
169
3.60k
      FU_EFI_COMPRESSION_TYPE_NOT_COMPRESSED) {
170
717
    if (!fu_efi_parse_sections(FU_FIRMWARE(self), stream, st->buf->len, flags, error)) {
171
64
      g_prefix_error_literal(error, "failed to parse sections: ");
172
64
      return FALSE;
173
64
    }
174
2.88k
  } else {
175
2.88k
    g_autoptr(FuFirmware) lz77_decompressor = fu_efi_lz77_decompressor_new();
176
2.88k
    g_autoptr(FuInputStream) lz77_stream = NULL;
177
2.88k
    if (!fu_firmware_parse_stream(lz77_decompressor,
178
2.88k
                stream,
179
2.88k
                st->buf->len,
180
2.88k
                flags,
181
2.88k
                error))
182
1.48k
      return FALSE;
183
1.40k
    lz77_stream = fu_firmware_get_stream(lz77_decompressor, error);
184
1.40k
    if (lz77_stream == NULL)
185
0
      return FALSE;
186
1.40k
    if (!fu_efi_parse_sections(FU_FIRMWARE(self), lz77_stream, 0, flags, error)) {
187
463
      g_prefix_error_literal(error, "failed to parse sections: ");
188
463
      return FALSE;
189
463
    }
190
1.40k
  }
191
1.59k
  return TRUE;
192
3.60k
}
193
194
static const gchar *
195
fu_efi_section_freeform_subtype_guid_to_string(const gchar *guid)
196
514
{
197
514
  struct {
198
514
    const gchar *guid;
199
514
    const gchar *str;
200
514
  } freeform_guids[] = {
201
514
      {"00781ca1-5de3-405f-abb8-379c3c076984", "AmiRomLayoutGuid"},
202
514
      {"20feebde-e739-420e-ae31-77e2876508c0", "IntelRstOprom"},
203
514
      {"224d6eb4-307f-45ba-9dc3-fe9fc6b38148", "IntelEntRaidController"},
204
514
      {"2ebe0275-6458-4af9-91ed-d3f4edb100aa", "SignOn"},
205
514
      {"380b6b4f-1454-41f2-a6d3-61d1333e8cb4", "IntelGop"},
206
514
      {"50339d20-c90a-4bb2-9aff-d8a11b23bc15", "I219?Oprom"},
207
514
      {"88a15a4f-977d-4682-b17c-da1f316c1f32", "RomLayout"},
208
514
      {"9bec7109-6d7a-413a-8e4b-019ced0503e1", "AmiBoardInfoSectionGuid"},
209
514
      {"ab56dc60-0057-11da-a8db-000102eee626", "?BuildData"},
210
514
      {"c5a4306e-e247-4ecd-a9d8-5b1985d3dcda", "?Oprom"},
211
514
      {"c9352cc3-a354-44e5-8776-b2ed8dd781ec", "IntelEntRaidController"},
212
514
      {"d46346ca-82a1-4cde-9546-77c86f893888", "?Oprom"},
213
514
      {"e095affe-d4cd-4289-9b48-28f64e3d781d", "IntelRstOprom"},
214
514
      {"fe612b72-203c-47b1-8560-a66d946eb371", "setupdata"},
215
514
      {NULL, NULL},
216
514
  };
217
7.71k
  for (guint i = 0; freeform_guids[i].guid != NULL; i++) {
218
7.19k
    if (g_strcmp0(guid, freeform_guids[i].guid) == 0)
219
0
      return freeform_guids[i].str;
220
7.19k
  }
221
514
  return NULL;
222
514
}
223
224
static gboolean
225
fu_efi_section_parse_freeform_subtype_guid(FuEfiSection *self,
226
             FuInputStream *stream,
227
             FuFirmwareParseFlags flags,
228
             GError **error)
229
527
{
230
527
  const gchar *guid_ui;
231
527
  g_autofree gchar *guid_str = NULL;
232
527
  g_autoptr(FuStructEfiSectionFreeformSubtypeGuid) st = NULL;
233
234
527
  st = fu_struct_efi_section_freeform_subtype_guid_parse_stream(stream, 0x0, error);
235
527
  if (st == NULL)
236
13
    return FALSE;
237
238
  /* no idea */
239
514
  guid_str = fwupd_guid_to_string(fu_struct_efi_section_freeform_subtype_guid_get_guid(st),
240
514
          FWUPD_GUID_FLAG_MIXED_ENDIAN);
241
514
  guid_ui = fu_efi_section_freeform_subtype_guid_to_string(guid_str);
242
514
  if (guid_ui != NULL) {
243
0
    g_debug("ignoring FREEFORM_SUBTYPE_GUID %s [%s]", guid_str, guid_ui);
244
0
    return TRUE;
245
0
  }
246
514
  g_debug("unknown FREEFORM_SUBTYPE_GUID %s", guid_str);
247
514
  return TRUE;
248
514
}
249
250
static gboolean
251
fu_efi_section_parse(FuFirmware *firmware,
252
         FuInputStream *stream,
253
         FuFirmwareParseFlags flags,
254
         GError **error)
255
59.1k
{
256
59.1k
  FuEfiSection *self = FU_EFI_SECTION(firmware);
257
59.1k
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
258
59.1k
  gsize offset = 0;
259
59.1k
  gsize streamsz = 0;
260
59.1k
  gsize stlen = 0;
261
59.1k
  guint32 size;
262
59.1k
  g_autoptr(FuStructEfiSection) st = NULL;
263
59.1k
  g_autoptr(FuInputStream) partial_stream = NULL;
264
265
  /* parse */
266
59.1k
  st = fu_struct_efi_section_parse_stream(stream, offset, error);
267
59.1k
  if (st == NULL)
268
95
    return FALSE;
269
270
  /* use extended size */
271
59.0k
  if (fu_struct_efi_section_get_size(st) == 0xFFFFFF) {
272
117
    g_autoptr(FuStructEfiSection2) st2 = NULL;
273
117
    st2 = fu_struct_efi_section2_parse_stream(stream, offset, error);
274
117
    if (st2 == NULL)
275
19
      return FALSE;
276
98
    priv->type = fu_struct_efi_section2_get_type(st2);
277
98
    size = fu_struct_efi_section2_get_extended_size(st2);
278
98
    stlen = st2->buf->len;
279
58.9k
  } else {
280
58.9k
    priv->type = fu_struct_efi_section_get_type(st);
281
58.9k
    size = fu_struct_efi_section_get_size(st);
282
58.9k
    stlen = st->buf->len;
283
58.9k
  }
284
59.0k
  if (size < stlen) {
285
304
    g_set_error(error,
286
304
          FWUPD_ERROR,
287
304
          FWUPD_ERROR_INTERNAL,
288
304
          "invalid section size, got 0x%x",
289
304
          (guint)size);
290
304
    return FALSE;
291
304
  }
292
293
  /* sanity check */
294
58.7k
  if (!fu_input_stream_size(stream, &streamsz, error))
295
0
    return FALSE;
296
58.7k
  if (size > streamsz) {
297
489
    g_set_error(error,
298
489
          FWUPD_ERROR,
299
489
          FWUPD_ERROR_INTERNAL,
300
489
          "invalid section size, got 0x%x from stream of size 0x%x",
301
489
          (guint)size,
302
489
          (guint)streamsz);
303
489
    return FALSE;
304
489
  }
305
306
  /* name */
307
58.2k
  if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED) {
308
3.87k
    gsize offset_delta;
309
3.87k
    g_autofree gchar *guid_str = NULL;
310
3.87k
    g_autoptr(FuStructEfiSectionGuidDefined) st_def = NULL;
311
3.87k
    st_def = fu_struct_efi_section_guid_defined_parse_stream(stream, stlen, error);
312
3.87k
    if (st_def == NULL)
313
14
      return FALSE;
314
3.85k
    guid_str = fwupd_guid_to_string(fu_struct_efi_section_guid_defined_get_name(st_def),
315
3.85k
            FWUPD_GUID_FLAG_MIXED_ENDIAN);
316
3.85k
    fu_firmware_set_id(firmware, guid_str);
317
3.85k
    if (fu_struct_efi_section_guid_defined_get_offset(st_def) < st_def->buf->len) {
318
23
      g_set_error(error,
319
23
            FWUPD_ERROR,
320
23
            FWUPD_ERROR_INTERNAL,
321
23
            "invalid section size, got 0x%x",
322
23
            (guint)fu_struct_efi_section_guid_defined_get_offset(st_def));
323
23
      return FALSE;
324
23
    }
325
3.83k
    if (fu_struct_efi_section_guid_defined_get_offset(st_def) > size) {
326
76
      g_set_error(error,
327
76
            FWUPD_ERROR,
328
76
            FWUPD_ERROR_INTERNAL,
329
76
            "invalid section offset 0x%x, greater than size 0x%x",
330
76
            (guint)fu_struct_efi_section_guid_defined_get_offset(st_def),
331
76
            (guint)size);
332
76
      return FALSE;
333
76
    }
334
3.75k
    offset_delta = fu_struct_efi_section_guid_defined_get_offset(st_def) - stlen;
335
3.75k
    if (!fu_size_checked_inc(&offset, offset_delta, error)) {
336
0
      g_prefix_error_literal(error, "section offset overflow: ");
337
0
      return FALSE;
338
0
    }
339
3.75k
  }
340
341
  /* create blob */
342
58.1k
  if (!fu_size_checked_inc(&offset, stlen, error)) {
343
0
    g_prefix_error_literal(error, "section offset overflow: ");
344
0
    return FALSE;
345
0
  }
346
58.1k
  partial_stream = fu_partial_input_stream_new(stream, offset, size - offset, error);
347
58.1k
  if (partial_stream == NULL) {
348
0
    g_prefix_error_literal(error, "failed to cut data: ");
349
0
    return FALSE;
350
0
  }
351
58.1k
  fu_firmware_set_offset(firmware, offset);
352
58.1k
  fu_firmware_set_size(firmware, size);
353
58.1k
  if (!fu_firmware_set_stream(firmware, partial_stream, error))
354
0
    return FALSE;
355
356
  /* nested volume */
357
58.1k
  if (priv->type == FU_EFI_SECTION_TYPE_VOLUME_IMAGE) {
358
1.78k
    if (!fu_efi_section_parse_volume_image(self, partial_stream, flags, error)) {
359
1.41k
      g_prefix_error_literal(error, "failed to parse nested volume: ");
360
1.41k
      return FALSE;
361
1.41k
    }
362
56.3k
  } else if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED &&
363
3.75k
       g_strcmp0(fu_firmware_get_id(firmware), FU_EFI_SECTION_GUID_LZMA_COMPRESS) ==
364
3.75k
           0) {
365
0
    if (!fu_efi_section_parse_lzma_sections(self, partial_stream, flags, error)) {
366
0
      g_prefix_error_literal(error, "failed to parse lzma section: ");
367
0
      return FALSE;
368
0
    }
369
56.3k
  } else if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED &&
370
3.75k
       g_strcmp0(fu_firmware_get_id(firmware),
371
3.75k
           "ced4eac6-49f3-4c12-a597-fc8c33447691") == 0) {
372
34
    g_debug("ignoring %s [0x%x] EFI section as self test",
373
34
      fu_efi_section_type_to_string(priv->type),
374
34
      priv->type);
375
56.2k
  } else if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED) {
376
#ifndef HAVE_FUZZER
377
    g_warning("no idea how to decompress encapsulation section of type %s",
378
        fu_firmware_get_id(firmware));
379
#endif
380
52.5k
  } else if (priv->type == FU_EFI_SECTION_TYPE_USER_INTERFACE) {
381
790
    if (!fu_efi_section_parse_user_interface(self, partial_stream, flags, error)) {
382
83
      g_prefix_error_literal(error, "failed to parse user interface: ");
383
83
      return FALSE;
384
83
    }
385
51.7k
  } else if (priv->type == FU_EFI_SECTION_TYPE_VERSION) {
386
1.58k
    if (!fu_efi_section_parse_version(self, partial_stream, flags, error)) {
387
55
      g_prefix_error_literal(error, "failed to parse version: ");
388
55
      return FALSE;
389
55
    }
390
50.1k
  } else if (priv->type == FU_EFI_SECTION_TYPE_COMPRESSION) {
391
3.62k
    if (!fu_efi_section_parse_compression_sections(self,
392
3.62k
                     partial_stream,
393
3.62k
                     flags,
394
3.62k
                     error)) {
395
2.03k
      g_prefix_error_literal(error, "failed to parse compression: ");
396
2.03k
      return FALSE;
397
2.03k
    }
398
46.5k
  } else if (priv->type == FU_EFI_SECTION_TYPE_FREEFORM_SUBTYPE_GUID) {
399
527
    if (!fu_efi_section_parse_freeform_subtype_guid(self,
400
527
                partial_stream,
401
527
                flags,
402
527
                error)) {
403
13
      g_prefix_error_literal(error, "failed to parse compression: ");
404
13
      return FALSE;
405
13
    }
406
46.0k
  } else if (priv->type == FU_EFI_SECTION_TYPE_PEI_DEPEX ||
407
44.9k
       priv->type == FU_EFI_SECTION_TYPE_DXE_DEPEX ||
408
44.3k
       priv->type == FU_EFI_SECTION_TYPE_MM_DEPEX ||
409
43.3k
       priv->type == FU_EFI_SECTION_TYPE_PE32 || priv->type == FU_EFI_SECTION_TYPE_TE ||
410
41.7k
       priv->type == FU_EFI_SECTION_TYPE_RAW) {
411
9.07k
    g_debug("ignoring %s [0x%x] EFI section",
412
9.07k
      fu_efi_section_type_to_string(priv->type),
413
9.07k
      priv->type);
414
36.9k
  } else {
415
#ifndef HAVE_FUZZER
416
    g_warning("no idea how to parse %s [0x%x] EFI section",
417
        fu_efi_section_type_to_string(priv->type),
418
        priv->type);
419
#endif
420
36.9k
  }
421
422
  /* success */
423
54.5k
  return TRUE;
424
58.1k
}
425
426
static GByteArray *
427
fu_efi_section_write(FuFirmware *firmware, GError **error)
428
9.44k
{
429
9.44k
  FuEfiSection *self = FU_EFI_SECTION(firmware);
430
9.44k
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
431
9.44k
  g_autoptr(FuStructEfiSection) st = fu_struct_efi_section_new();
432
9.44k
  g_autoptr(GBytes) blob = NULL;
433
434
  /* simple blob for now */
435
9.44k
  blob = fu_firmware_get_bytes_with_patches(firmware, error);
436
9.44k
  if (blob == NULL)
437
149
    return NULL;
438
439
  /* header */
440
9.29k
  if (priv->type == FU_EFI_SECTION_TYPE_GUID_DEFINED) {
441
1.98k
    fwupd_guid_t guid = {0x0};
442
1.98k
    g_autoptr(FuStructEfiSectionGuidDefined) st_def =
443
1.98k
        fu_struct_efi_section_guid_defined_new();
444
1.98k
    if (!fwupd_guid_from_string(fu_firmware_get_id(firmware),
445
1.98k
              &guid,
446
1.98k
              FWUPD_GUID_FLAG_MIXED_ENDIAN,
447
1.98k
              error))
448
0
      return NULL;
449
1.98k
    fu_struct_efi_section_guid_defined_set_name(st_def, &guid);
450
1.98k
    fu_struct_efi_section_guid_defined_set_offset(st_def,
451
1.98k
                    st->buf->len + st_def->buf->len);
452
1.98k
    fu_byte_array_append_array(st->buf, st_def->buf);
453
1.98k
  }
454
9.29k
  fu_struct_efi_section_set_type(st, priv->type);
455
9.29k
  fu_struct_efi_section_set_size(st, st->buf->len + g_bytes_get_size(blob));
456
457
  /* blob */
458
9.29k
  fu_byte_array_append_bytes(st->buf, blob);
459
9.29k
  return g_steal_pointer(&st->buf);
460
9.29k
}
461
462
static gboolean
463
fu_efi_section_build(FuFirmware *firmware, XbNode *n, GError **error)
464
0
{
465
0
  FuEfiSection *self = FU_EFI_SECTION(firmware);
466
0
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
467
0
  const gchar *str;
468
0
  guint64 tmp;
469
470
  /* simple properties */
471
0
  tmp = xb_node_query_text_as_uint(n, "type", NULL);
472
0
  if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT8)
473
0
    priv->type = tmp;
474
0
  str = xb_node_query_text(n, "user_interface", NULL);
475
0
  if (str != NULL) {
476
0
    if (priv->user_interface != NULL) {
477
0
      g_set_error(error,
478
0
            FWUPD_ERROR,
479
0
            FWUPD_ERROR_INTERNAL,
480
0
            "UI already set as %s for section",
481
0
            priv->user_interface);
482
0
      return FALSE;
483
0
    }
484
0
    priv->user_interface = g_strdup(str);
485
0
  }
486
487
  /* success */
488
0
  return TRUE;
489
0
}
490
491
static void
492
fu_efi_section_init(FuEfiSection *self)
493
59.1k
{
494
59.1k
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
495
59.1k
  priv->type = FU_EFI_SECTION_TYPE_RAW;
496
59.1k
  fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_NO_AUTO_DETECTION);
497
  //  fu_firmware_set_alignment (FU_FIRMWARE (self), FU_FIRMWARE_ALIGNMENT_8);
498
59.1k
}
499
500
static void
501
fu_efi_section_finalize(GObject *object)
502
59.1k
{
503
59.1k
  FuEfiSection *self = FU_EFI_SECTION(object);
504
59.1k
  FuEfiSectionPrivate *priv = GET_PRIVATE(self);
505
59.1k
  g_free(priv->user_interface);
506
59.1k
  G_OBJECT_CLASS(fu_efi_section_parent_class)->finalize(object);
507
59.1k
}
508
509
static void
510
fu_efi_section_class_init(FuEfiSectionClass *klass)
511
3
{
512
3
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
513
3
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
514
3
  object_class->finalize = fu_efi_section_finalize;
515
3
  firmware_class->parse = fu_efi_section_parse;
516
3
  firmware_class->write = fu_efi_section_write;
517
3
  firmware_class->build = fu_efi_section_build;
518
3
  firmware_class->export = fu_efi_section_export;
519
3
  fu_firmware_add_image_gtype(firmware_class, FU_TYPE_EFI_VOLUME);
520
3
  fu_firmware_add_image_gtype(firmware_class, FU_TYPE_EFI_SECTION);
521
3
#ifdef HAVE_FUZZER
522
3
  fu_firmware_set_size_max(firmware_class, 1 * FU_MB);
523
3
  fu_firmware_set_images_max(firmware_class, 10);
524
#else
525
  fu_firmware_set_size_max(firmware_class, 1 * FU_GB);
526
  fu_firmware_set_images_max(firmware_class, 2000);
527
#endif
528
3
}
529
530
/**
531
 * fu_efi_section_new:
532
 *
533
 * Creates a new #FuFirmware
534
 *
535
 * Since: 2.0.0
536
 **/
537
FuFirmware *
538
fu_efi_section_new(void)
539
59.1k
{
540
59.1k
  return FU_FIRMWARE(g_object_new(FU_TYPE_EFI_SECTION, NULL));
541
59.1k
}