Coverage Report

Created: 2026-05-30 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/plugins/bcm57xx/fu-bcm57xx-dict-image.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
#include "config.h"
8
9
#include "fu-bcm57xx-common.h"
10
#include "fu-bcm57xx-dict-image.h"
11
12
struct _FuBcm57xxDictImage {
13
  FuFirmware parent_instance;
14
  guint8 target;
15
  guint8 kind;
16
};
17
18
8.00k
G_DEFINE_TYPE(FuBcm57xxDictImage, fu_bcm57xx_dict_image, FU_TYPE_FIRMWARE)
19
8.00k
20
8.00k
static void
21
8.00k
fu_bcm57xx_dict_image_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
22
8.00k
{
23
0
  FuBcm57xxDictImage *self = FU_BCM57XX_DICT_IMAGE(firmware);
24
0
  if (self->target != 0xff)
25
0
    fu_xmlb_builder_insert_kx(bn, "target", self->target);
26
0
  if (self->kind != 0xff)
27
0
    fu_xmlb_builder_insert_kx(bn, "kind", self->kind);
28
0
}
29
30
static gboolean
31
fu_bcm57xx_dict_image_parse(FuFirmware *firmware,
32
          GInputStream *stream,
33
          FuFirmwareParseFlags flags,
34
          GError **error)
35
855
{
36
855
  g_autoptr(GInputStream) stream_nocrc = NULL;
37
855
  gsize streamsz = 0;
38
39
855
  if (!fu_input_stream_size(stream, &streamsz, error))
40
0
    return FALSE;
41
855
  if (streamsz < sizeof(guint32)) {
42
0
    g_set_error_literal(error,
43
0
            FWUPD_ERROR,
44
0
            FWUPD_ERROR_INVALID_DATA,
45
0
            "dict image is too small");
46
0
    return FALSE;
47
0
  }
48
855
  if ((flags & FU_FIRMWARE_PARSE_FLAG_IGNORE_CHECKSUM) == 0) {
49
0
    if (!fu_bcm57xx_verify_crc(stream, error))
50
0
      return FALSE;
51
0
  }
52
855
  stream_nocrc = fu_partial_input_stream_new(stream, 0x0, streamsz - sizeof(guint32), error);
53
855
  if (stream_nocrc == NULL)
54
0
    return FALSE;
55
855
  return fu_firmware_set_stream(firmware, stream_nocrc, error);
56
855
}
57
58
static GByteArray *
59
fu_bcm57xx_dict_image_write(FuFirmware *firmware, GError **error)
60
633
{
61
633
  guint32 crc;
62
633
  g_autoptr(GByteArray) blob = NULL;
63
633
  g_autoptr(GBytes) fw_nocrc = NULL;
64
65
  /* get the CRC-less data */
66
633
  fw_nocrc = fu_firmware_get_bytes(firmware, error);
67
633
  if (fw_nocrc == NULL)
68
28
    return NULL;
69
70
  /* add to a mutable buffer */
71
605
  blob = g_byte_array_sized_new(g_bytes_get_size(fw_nocrc) + sizeof(guint32));
72
605
  fu_byte_array_append_bytes(blob, fw_nocrc);
73
74
  /* add CRC */
75
605
  crc = fu_crc32_bytes(FU_CRC_KIND_B32_STANDARD, fw_nocrc);
76
605
  fu_byte_array_append_uint32(blob, crc, G_LITTLE_ENDIAN);
77
605
  return g_steal_pointer(&blob);
78
633
}
79
80
static gboolean
81
fu_bcm57xx_dict_image_build(FuFirmware *firmware, XbNode *n, GError **error)
82
0
{
83
0
  FuBcm57xxDictImage *self = FU_BCM57XX_DICT_IMAGE(firmware);
84
0
  guint64 tmp;
85
86
  /* two simple properties */
87
0
  tmp = xb_node_query_text_as_uint(n, "kind", NULL);
88
0
  if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT8)
89
0
    fu_bcm57xx_dict_image_set_kind(self, tmp);
90
0
  tmp = xb_node_query_text_as_uint(n, "target", NULL);
91
0
  if (tmp != G_MAXUINT64 && tmp <= G_MAXUINT8)
92
0
    fu_bcm57xx_dict_image_set_target(self, tmp);
93
94
  /* success */
95
0
  return TRUE;
96
0
}
97
98
static void
99
fu_bcm57xx_dict_image_ensure_id(FuBcm57xxDictImage *self)
100
3.63k
{
101
3.63k
  g_autofree gchar *id = NULL;
102
3.63k
  struct {
103
3.63k
    guint8 target;
104
3.63k
    guint8 kind;
105
3.63k
    const gchar *id;
106
3.63k
  } ids[] = {{0x00, 0x00, "pxe"},
107
3.63k
       {0x0D, 0x00, "ape"},
108
3.63k
       {0x09, 0x00, "iscsi1"},
109
3.63k
       {0x05, 0x00, "iscsi2"},
110
3.63k
       {0x0b, 0x00, "iscsi3"},
111
3.63k
       {0x00, 0x01, "cfg1000"},
112
3.63k
       {0x04, 0x01, "vpd2"},
113
3.63k
       {0xff, 0xff, NULL}};
114
3.63k
  if (self->target == 0xff || self->kind == 0xff)
115
1.81k
    return;
116
8.68k
  for (guint i = 0; ids[i].id != NULL; i++) {
117
7.83k
    if (self->target == ids[i].target && self->kind == ids[i].kind) {
118
972
      g_debug("using %s for %02x:%02x", ids[i].id, self->target, self->kind);
119
972
      fu_firmware_set_id(FU_FIRMWARE(self), ids[i].id);
120
972
      return;
121
972
    }
122
7.83k
  }
123
847
  id = g_strdup_printf("dict-%02x-%02x", self->target, self->kind);
124
847
  if (g_getenv("FWUPD_FUZZER_RUNNING") == NULL)
125
0
    g_warning("falling back to %s, please report", id);
126
847
  fu_firmware_set_id(FU_FIRMWARE(self), id);
127
847
}
128
129
void
130
fu_bcm57xx_dict_image_set_target(FuBcm57xxDictImage *self, guint8 target)
131
1.81k
{
132
1.81k
  self->target = target;
133
1.81k
  fu_bcm57xx_dict_image_ensure_id(self);
134
1.81k
}
135
136
guint8
137
fu_bcm57xx_dict_image_get_target(FuBcm57xxDictImage *self)
138
605
{
139
605
  return self->target;
140
605
}
141
142
void
143
fu_bcm57xx_dict_image_set_kind(FuBcm57xxDictImage *self, guint8 kind)
144
1.81k
{
145
1.81k
  self->kind = kind;
146
1.81k
  fu_bcm57xx_dict_image_ensure_id(self);
147
1.81k
}
148
149
guint8
150
fu_bcm57xx_dict_image_get_kind(FuBcm57xxDictImage *self)
151
605
{
152
605
  return self->kind;
153
605
}
154
155
static void
156
fu_bcm57xx_dict_image_init(FuBcm57xxDictImage *self)
157
2.03k
{
158
2.03k
  self->target = 0xff;
159
2.03k
  self->kind = 0xff;
160
2.03k
  fu_firmware_set_size_max(FU_FIRMWARE(self), 1 * FU_MB);
161
2.03k
}
162
163
static void
164
fu_bcm57xx_dict_image_class_init(FuBcm57xxDictImageClass *klass)
165
1
{
166
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
167
1
  firmware_class->parse = fu_bcm57xx_dict_image_parse;
168
1
  firmware_class->write = fu_bcm57xx_dict_image_write;
169
1
  firmware_class->build = fu_bcm57xx_dict_image_build;
170
1
  firmware_class->export = fu_bcm57xx_dict_image_export;
171
1
}
172
173
FuFirmware *
174
fu_bcm57xx_dict_image_new(void)
175
2.03k
{
176
2.03k
  return FU_FIRMWARE(g_object_new(FU_TYPE_BCM57XX_DICT_IMAGE, NULL));
177
2.03k
}