Coverage Report

Created: 2025-08-03 06:57

/src/fwupd/plugins/bcm57xx/fu-bcm57xx-dict-image.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
#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
G_DEFINE_TYPE(FuBcm57xxDictImage, fu_bcm57xx_dict_image, FU_TYPE_FIRMWARE)
19
20
static void
21
fu_bcm57xx_dict_image_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
22
0
{
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
1.42k
{
36
1.42k
  g_autoptr(GInputStream) stream_nocrc = NULL;
37
1.42k
  gsize streamsz = 0;
38
39
1.42k
  if (!fu_input_stream_size(stream, &streamsz, error))
40
0
    return FALSE;
41
1.42k
  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
1.42k
  if ((flags & FU_FIRMWARE_PARSE_FLAG_IGNORE_CHECKSUM) == 0) {
49
427
    if (!fu_bcm57xx_verify_crc(stream, error))
50
130
      return FALSE;
51
427
  }
52
1.29k
  stream_nocrc = fu_partial_input_stream_new(stream, 0x0, streamsz - sizeof(guint32), error);
53
1.29k
  if (stream_nocrc == NULL)
54
0
    return FALSE;
55
1.29k
  return fu_firmware_set_stream(firmware, stream_nocrc, error);
56
1.29k
}
57
58
static GByteArray *
59
fu_bcm57xx_dict_image_write(FuFirmware *firmware, GError **error)
60
499
{
61
499
  guint32 crc;
62
499
  g_autoptr(GByteArray) blob = NULL;
63
499
  g_autoptr(GBytes) fw_nocrc = NULL;
64
65
  /* get the CRC-less data */
66
499
  fw_nocrc = fu_firmware_get_bytes(firmware, error);
67
499
  if (fw_nocrc == NULL)
68
19
    return NULL;
69
70
  /* add to a mutable buffer */
71
480
  blob = g_byte_array_sized_new(g_bytes_get_size(fw_nocrc) + sizeof(guint32));
72
480
  fu_byte_array_append_bytes(blob, fw_nocrc);
73
74
  /* add CRC */
75
480
  crc = fu_crc32_bytes(FU_CRC_KIND_B32_STANDARD, fw_nocrc);
76
480
  fu_byte_array_append_uint32(blob, crc, G_LITTLE_ENDIAN);
77
480
  return g_steal_pointer(&blob);
78
499
}
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
5.50k
{
101
5.50k
  g_autofree gchar *id = NULL;
102
5.50k
  struct {
103
5.50k
    guint8 target;
104
5.50k
    guint8 kind;
105
5.50k
    const gchar *id;
106
5.50k
  } ids[] = {{0x00, 0x00, "pxe"},
107
5.50k
       {0x0D, 0x00, "ape"},
108
5.50k
       {0x09, 0x00, "iscsi1"},
109
5.50k
       {0x05, 0x00, "iscsi2"},
110
5.50k
       {0x0b, 0x00, "iscsi3"},
111
5.50k
       {0x00, 0x01, "cfg1000"},
112
5.50k
       {0x04, 0x01, "vpd2"},
113
5.50k
       {0xff, 0xff, NULL}};
114
5.50k
  if (self->target == 0xff || self->kind == 0xff)
115
2.75k
    return;
116
12.9k
  for (guint i = 0; ids[i].id != NULL; i++) {
117
11.6k
    if (self->target == ids[i].target && self->kind == ids[i].kind) {
118
1.44k
      g_debug("using %s for %02x:%02x", ids[i].id, self->target, self->kind);
119
1.44k
      fu_firmware_set_id(FU_FIRMWARE(self), ids[i].id);
120
1.44k
      return;
121
1.44k
    }
122
11.6k
  }
123
1.30k
  id = g_strdup_printf("dict-%02x-%02x", self->target, self->kind);
124
1.30k
  if (g_getenv("FWUPD_FUZZER_RUNNING") == NULL)
125
0
    g_warning("falling back to %s, please report", id);
126
1.30k
  fu_firmware_set_id(FU_FIRMWARE(self), id);
127
1.30k
}
128
129
void
130
fu_bcm57xx_dict_image_set_target(FuBcm57xxDictImage *self, guint8 target)
131
2.75k
{
132
2.75k
  self->target = target;
133
2.75k
  fu_bcm57xx_dict_image_ensure_id(self);
134
2.75k
}
135
136
guint8
137
fu_bcm57xx_dict_image_get_target(FuBcm57xxDictImage *self)
138
480
{
139
480
  return self->target;
140
480
}
141
142
void
143
fu_bcm57xx_dict_image_set_kind(FuBcm57xxDictImage *self, guint8 kind)
144
2.75k
{
145
2.75k
  self->kind = kind;
146
2.75k
  fu_bcm57xx_dict_image_ensure_id(self);
147
2.75k
}
148
149
guint8
150
fu_bcm57xx_dict_image_get_kind(FuBcm57xxDictImage *self)
151
480
{
152
480
  return self->kind;
153
480
}
154
155
static void
156
fu_bcm57xx_dict_image_init(FuBcm57xxDictImage *self)
157
2.96k
{
158
2.96k
  self->target = 0xff;
159
2.96k
  self->kind = 0xff;
160
2.96k
}
161
162
static void
163
fu_bcm57xx_dict_image_class_init(FuBcm57xxDictImageClass *klass)
164
1
{
165
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
166
1
  firmware_class->parse = fu_bcm57xx_dict_image_parse;
167
1
  firmware_class->write = fu_bcm57xx_dict_image_write;
168
1
  firmware_class->build = fu_bcm57xx_dict_image_build;
169
1
  firmware_class->export = fu_bcm57xx_dict_image_export;
170
1
}
171
172
FuFirmware *
173
fu_bcm57xx_dict_image_new(void)
174
2.96k
{
175
2.96k
  return FU_FIRMWARE(g_object_new(FU_TYPE_BCM57XX_DICT_IMAGE, NULL));
176
2.96k
}