Coverage Report

Created: 2026-10-17 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-ifd-bios.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
25.9k
#define G_LOG_DOMAIN "FuIfdBios"
8
9
#include "config.h"
10
11
#include "fu-common.h"
12
#include "fu-efi-volume.h"
13
#include "fu-ifd-bios.h"
14
#include "fu-input-stream.h"
15
16
/**
17
 * FuIfdBios:
18
 *
19
 * An Intel BIOS section.
20
 *
21
 * See also: [class@FuFirmware]
22
 */
23
24
5.23k
G_DEFINE_TYPE(FuIfdBios, fu_ifd_bios, FU_TYPE_IFD_IMAGE)
25
5.23k
26
5.23k
#define FU_IFD_BIOS_FIT_SIGNATURE 0x5449465F
27
5.23k
28
5.23k
static gboolean
29
5.23k
fu_ifd_bios_parse(FuFirmware *firmware,
30
5.23k
      FuInputStream *stream,
31
5.23k
      FuFirmwareParseFlags flags,
32
5.23k
      GError **error)
33
5.23k
{
34
5.23k
  gsize offset = 0;
35
5.23k
  gsize streamsz = 0;
36
5.23k
  guint img_cnt = 0;
37
38
  /* get size */
39
5.23k
  if (!fu_input_stream_size(stream, &streamsz, error))
40
0
    return FALSE;
41
42
  /* read each volume in order */
43
35.4k
  while (offset < streamsz) {
44
31.2k
    g_autoptr(FuFirmware) firmware_tmp = fu_efi_volume_new();
45
31.2k
    g_autoptr(GError) error_local = NULL;
46
47
    /* FV */
48
31.2k
    if (!fu_firmware_parse_stream(firmware_tmp, stream, offset, flags, &error_local)) {
49
25.9k
      g_debug("failed to read volume @0x%x of 0x%x: %s",
50
25.9k
        (guint)offset,
51
25.9k
        (guint)streamsz,
52
25.9k
        error_local->message);
53
25.9k
      if (!fu_size_checked_inc(&offset, 4 * FU_KB, error)) {
54
0
        g_prefix_error_literal(error, "BIOS volume scan offset overflow: ");
55
0
        return FALSE;
56
0
      }
57
25.9k
      continue;
58
25.9k
    }
59
5.32k
    if (fu_firmware_get_size(firmware_tmp) < 0x800) {
60
1.03k
      g_set_error(error,
61
1.03k
            FWUPD_ERROR,
62
1.03k
            FWUPD_ERROR_INVALID_DATA,
63
1.03k
            "EFI_VOLUME @0x%x too small (0x%x bytes)",
64
1.03k
            (guint)offset,
65
1.03k
            (guint)fu_firmware_get_size(firmware_tmp));
66
1.03k
      return FALSE;
67
1.03k
    }
68
4.29k
    fu_firmware_set_offset(firmware_tmp, offset);
69
4.29k
    if (!fu_firmware_add_image(firmware, firmware_tmp, error))
70
29
      return FALSE;
71
72
    /* next! */
73
4.26k
    if (!fu_size_checked_inc(&offset, fu_firmware_get_size(firmware_tmp), error))
74
0
      return FALSE;
75
4.26k
    img_cnt++;
76
4.26k
  }
77
78
  /* found nothing */
79
4.17k
  if (img_cnt == 0) {
80
2.45k
    g_set_error_literal(error,
81
2.45k
            FWUPD_ERROR,
82
2.45k
            FWUPD_ERROR_INVALID_FILE,
83
2.45k
            "no EFI firmware volumes");
84
2.45k
    return FALSE;
85
2.45k
  }
86
87
  /* success */
88
1.71k
  return TRUE;
89
4.17k
}
90
91
static void
92
fu_ifd_bios_init(FuIfdBios *self)
93
5.23k
{
94
5.23k
  fu_firmware_set_alignment(FU_FIRMWARE(self), FU_FIRMWARE_ALIGNMENT_4K);
95
5.23k
}
96
97
static void
98
fu_ifd_bios_class_init(FuIfdBiosClass *klass)
99
2
{
100
2
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
101
2
  fu_firmware_add_image_gtype(firmware_class, FU_TYPE_EFI_VOLUME);
102
2
  firmware_class->parse = fu_ifd_bios_parse;
103
2
#ifdef HAVE_FUZZER
104
2
  fu_firmware_set_size_max(firmware_class, 1 * FU_MB);
105
2
  fu_firmware_set_images_max(firmware_class, 10);
106
#else
107
  fu_firmware_set_size_max(firmware_class, 1 * FU_GB);
108
  fu_firmware_set_images_max(firmware_class, 1024);
109
#endif
110
2
}
111
112
/**
113
 * fu_ifd_bios_new:
114
 *
115
 * Creates a new #FuFirmware
116
 *
117
 * Since: 1.6.2
118
 **/
119
FuFirmware *
120
fu_ifd_bios_new(void)
121
1.83k
{
122
1.83k
  return FU_FIRMWARE(g_object_new(FU_TYPE_IFD_BIOS, NULL));
123
1.83k
}