Coverage Report

Created: 2026-08-13 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-intel-thunderbolt-firmware.c
Line
Count
Source
1
/*
2
 * Copyright 2021 Dell Inc.
3
 * Copyright 2020 Richard Hughes <richard@hughsie.com>
4
 * Copyright 2020 Mario Limonciello <mario.limonciello@dell.com>
5
 * Copyright 2017 Intel Corporation.
6
 *
7
 * SPDX-License-Identifier: LGPL-2.1-or-later
8
 */
9
10
514
#define G_LOG_DOMAIN "FuFirmware"
11
12
#include "config.h"
13
14
#include "fu-byte-array.h"
15
#include "fu-common.h"
16
#include "fu-input-stream.h"
17
#include "fu-intel-thunderbolt-firmware.h"
18
#include "fu-partial-input-stream.h"
19
20
/**
21
 * FuIntelThunderboltFirmware:
22
 *
23
 * The Non-Volatile-Memory file-format specification. This is what you would find as the update
24
 * payload.
25
 *
26
 * See also: [class@FuFirmware]
27
 */
28
29
528
G_DEFINE_TYPE(FuIntelThunderboltFirmware,
30
528
        fu_intel_thunderbolt_firmware,
31
528
        FU_TYPE_INTEL_THUNDERBOLT_NVM)
32
528
33
528
static gboolean
34
528
fu_intel_thunderbolt_firmware_nvm_valid_farb_pointer(guint32 pointer)
35
534
{
36
534
  return pointer != 0 && pointer != 0xFFFFFF;
37
534
}
38
39
static gboolean
40
fu_intel_thunderbolt_firmware_parse(FuFirmware *firmware,
41
            FuInputStream *stream,
42
            FuFirmwareParseFlags flags,
43
            GError **error)
44
526
{
45
526
  const guint32 farb_offsets[] = {0x0, 0x1000};
46
526
  gboolean valid = FALSE;
47
526
  guint32 farb_pointer = 0x0;
48
526
  g_autoptr(FuInputStream) partial_stream = NULL;
49
50
  /* get header offset */
51
546
  for (guint i = 0; i < G_N_ELEMENTS(farb_offsets); i++) {
52
544
    if (!fu_input_stream_read_u24(stream,
53
544
                farb_offsets[i],
54
544
                &farb_pointer,
55
544
                G_LITTLE_ENDIAN,
56
544
                error))
57
10
      return FALSE;
58
534
    if (fu_intel_thunderbolt_firmware_nvm_valid_farb_pointer(farb_pointer)) {
59
514
      valid = TRUE;
60
514
      break;
61
514
    }
62
534
  }
63
516
  if (!valid) {
64
2
    g_set_error_literal(error,
65
2
            FWUPD_ERROR,
66
2
            FWUPD_ERROR_INVALID_FILE,
67
2
            "no valid farb pointer found");
68
2
    return FALSE;
69
2
  }
70
514
  g_debug("detected digital section begins at 0x%x", farb_pointer);
71
514
  fu_firmware_set_offset(firmware, farb_pointer);
72
73
  /* FuIntelThunderboltNvm->parse */
74
514
  partial_stream = fu_partial_input_stream_new(stream, farb_pointer, G_MAXSIZE, error);
75
514
  if (partial_stream == NULL) {
76
65
    g_prefix_error_literal(error, "failed to cut from NVM: ");
77
65
    return FALSE;
78
65
  }
79
449
  return FU_FIRMWARE_CLASS(fu_intel_thunderbolt_firmware_parent_class)
80
449
      ->parse(firmware, partial_stream, flags, error);
81
514
}
82
83
static GByteArray *
84
fu_intel_thunderbolt_firmware_write(FuFirmware *firmware, GError **error)
85
249
{
86
249
  g_autoptr(GByteArray) buf = g_byte_array_new();
87
249
  g_autoptr(GByteArray) buf_nvm = NULL;
88
89
  /* sanity check */
90
249
  if (fu_firmware_get_offset(firmware) < 0x08) {
91
171
    g_set_error_literal(error,
92
171
            FWUPD_ERROR,
93
171
            FWUPD_ERROR_INVALID_FILE,
94
171
            "not valid offset");
95
171
    return NULL;
96
171
  }
97
98
  /* offset */
99
78
  fu_byte_array_append_uint32(buf, fu_firmware_get_offset(firmware), G_LITTLE_ENDIAN);
100
78
  fu_byte_array_set_size(buf, fu_firmware_get_offset(firmware), 0x00);
101
102
  /* FuIntelThunderboltNvm->write */
103
78
  buf_nvm =
104
78
      FU_FIRMWARE_CLASS(fu_intel_thunderbolt_firmware_parent_class)->write(firmware, error);
105
78
  if (buf_nvm == NULL)
106
0
    return NULL;
107
78
  g_byte_array_append(buf, buf_nvm->data, buf_nvm->len);
108
109
  /* success */
110
78
  return g_steal_pointer(&buf);
111
78
}
112
113
static void
114
fu_intel_thunderbolt_firmware_init(FuIntelThunderboltFirmware *self)
115
526
{
116
526
}
117
118
static void
119
fu_intel_thunderbolt_firmware_class_init(FuIntelThunderboltFirmwareClass *klass)
120
1
{
121
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
122
1
  fu_firmware_set_size_max(firmware_class, 32 * FU_MB);
123
1
  firmware_class->parse = fu_intel_thunderbolt_firmware_parse;
124
1
  firmware_class->write = fu_intel_thunderbolt_firmware_write;
125
1
}
126
127
/**
128
 * fu_intel_thunderbolt_firmware_new:
129
 *
130
 * Creates a new #FuFirmware of Intel NVM format
131
 *
132
 * Since: 1.8.5
133
 **/
134
FuFirmware *
135
fu_intel_thunderbolt_firmware_new(void)
136
0
{
137
0
  return FU_FIRMWARE(g_object_new(FU_TYPE_INTEL_THUNDERBOLT_FIRMWARE, NULL));
138
0
}