Coverage Report

Created: 2025-11-09 07:06

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