Coverage Report

Created: 2025-11-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/plugins/synaptics-cape/fu-synaptics-cape-sngl-firmware.c
Line
Count
Source
1
/*
2
 * Copyright 2023 Synaptics Incorporated <simon.ho@synaptics.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <string.h>
10
11
#include "fu-synaptics-cape-sngl-firmware.h"
12
#include "fu-synaptics-cape-struct.h"
13
14
struct _FuSynapticsCapeSnglFirmware {
15
  FuSynapticsCapeFirmware parent_instance;
16
};
17
18
0
G_DEFINE_TYPE(FuSynapticsCapeSnglFirmware,
19
0
        fu_synaptics_cape_sngl_firmware,
20
0
        FU_TYPE_SYNAPTICS_CAPE_FIRMWARE)
21
0
22
0
static gboolean
23
0
fu_synaptics_cape_sngl_firmware_parse(FuFirmware *firmware,
24
0
              GInputStream *stream,
25
0
              FuFirmwareParseFlags flags,
26
0
              GError **error)
27
0
{
28
0
  FuSynapticsCapeSnglFirmware *self = FU_SYNAPTICS_CAPE_SNGL_FIRMWARE(firmware);
29
0
  gsize streamsz = 0;
30
0
  guint16 num_fw_file;
31
0
  g_autoptr(FuStructSynapticsCapeSnglHdr) st = NULL;
32
0
  g_autofree gchar *version_str = NULL;
33
34
  /* sanity check */
35
0
  if (!fu_input_stream_size(stream, &streamsz, error))
36
0
    return FALSE;
37
0
  if ((guint32)streamsz % 4 != 0) {
38
0
    g_set_error_literal(error,
39
0
            FWUPD_ERROR,
40
0
            FWUPD_ERROR_INVALID_FILE,
41
0
            "data not aligned to 32 bits");
42
0
    return FALSE;
43
0
  }
44
0
  if (streamsz < 8) {
45
0
    g_set_error_literal(error,
46
0
            FWUPD_ERROR,
47
0
            FWUPD_ERROR_INVALID_FILE,
48
0
            "image is too small");
49
0
    return FALSE;
50
0
  }
51
52
  /* unpack */
53
0
  st = fu_struct_synaptics_cape_sngl_hdr_parse_stream(stream, 0x0, error);
54
0
  if (st == NULL)
55
0
    return FALSE;
56
0
  if (fu_struct_synaptics_cape_sngl_hdr_get_file_size(st) != streamsz) {
57
0
    g_set_error_literal(error,
58
0
            FWUPD_ERROR,
59
0
            FWUPD_ERROR_INVALID_FILE,
60
0
            "file size is incorrect");
61
0
    return FALSE;
62
0
  }
63
64
  /* check CRC */
65
0
  if ((flags & FU_FIRMWARE_PARSE_FLAG_IGNORE_CHECKSUM) == 0) {
66
0
    guint32 crc_calc = 0xFFFFFFFF;
67
0
    g_autoptr(GInputStream) stream_tmp = NULL;
68
69
0
    stream_tmp = fu_partial_input_stream_new(stream, 8, G_MAXSIZE, error);
70
0
    if (stream_tmp == NULL)
71
0
      return FALSE;
72
0
    if (!fu_input_stream_compute_crc32(stream_tmp,
73
0
               FU_CRC_KIND_B32_STANDARD,
74
0
               &crc_calc,
75
0
               error))
76
0
      return FALSE;
77
0
    if (crc_calc != fu_struct_synaptics_cape_sngl_hdr_get_file_crc(st)) {
78
0
      g_set_error(error,
79
0
            FWUPD_ERROR,
80
0
            FWUPD_ERROR_INVALID_DATA,
81
0
            "CRC did not match, got 0x%x, expected 0x%x",
82
0
            fu_struct_synaptics_cape_sngl_hdr_get_file_crc(st),
83
0
            crc_calc);
84
0
      return FALSE;
85
0
    }
86
0
  }
87
88
0
  fu_synaptics_cape_firmware_set_vid(FU_SYNAPTICS_CAPE_FIRMWARE(self),
89
0
             fu_struct_synaptics_cape_sngl_hdr_get_vid(st));
90
0
  fu_synaptics_cape_firmware_set_pid(FU_SYNAPTICS_CAPE_FIRMWARE(self),
91
0
             fu_struct_synaptics_cape_sngl_hdr_get_pid(st));
92
0
  version_str = fu_version_from_uint32(fu_struct_synaptics_cape_sngl_hdr_get_fw_version(st),
93
0
               FWUPD_VERSION_FORMAT_QUAD);
94
0
  fu_firmware_set_version(FU_FIRMWARE(self), version_str);
95
96
  /* add each file */
97
0
  num_fw_file = fu_struct_synaptics_cape_sngl_hdr_get_fw_file_num(st);
98
0
  if (num_fw_file == 0) {
99
0
    g_set_error_literal(error,
100
0
            FWUPD_ERROR,
101
0
            FWUPD_ERROR_INVALID_DATA,
102
0
            "no image files found");
103
0
    return FALSE;
104
0
  }
105
106
  /* success */
107
0
  return TRUE;
108
0
}
109
110
static GByteArray *
111
fu_synaptics_cape_sngl_firmware_write(FuFirmware *firmware, GError **error)
112
0
{
113
0
  FuSynapticsCapeSnglFirmware *self = FU_SYNAPTICS_CAPE_SNGL_FIRMWARE(firmware);
114
0
  g_autoptr(FuStructSynapticsCapeSnglHdr) st = fu_struct_synaptics_cape_sngl_hdr_new();
115
116
  /* pack */
117
0
  fu_struct_synaptics_cape_sngl_hdr_set_vid(
118
0
      st,
119
0
      fu_synaptics_cape_firmware_get_vid(FU_SYNAPTICS_CAPE_FIRMWARE(self)));
120
0
  fu_struct_synaptics_cape_sngl_hdr_set_pid(
121
0
      st,
122
0
      fu_synaptics_cape_firmware_get_pid(FU_SYNAPTICS_CAPE_FIRMWARE(self)));
123
124
  /* success */
125
0
  return g_steal_pointer(&st->buf);
126
0
}
127
128
static void
129
fu_synaptics_cape_sngl_firmware_init(FuSynapticsCapeSnglFirmware *self)
130
0
{
131
0
  fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
132
0
}
133
134
static void
135
fu_synaptics_cape_sngl_firmware_class_init(FuSynapticsCapeSnglFirmwareClass *klass)
136
0
{
137
0
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
138
0
  firmware_class->parse = fu_synaptics_cape_sngl_firmware_parse;
139
0
  firmware_class->write = fu_synaptics_cape_sngl_firmware_write;
140
0
}