-
Notifications
You must be signed in to change notification settings - Fork 411
/
fu-intel-thunderbolt-firmware.c
129 lines (112 loc) · 3.29 KB
/
fu-intel-thunderbolt-firmware.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
* Copyright (C) 2021 Dell Inc.
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2020 Mario Limonciello <mario.limonciello@dell.com>
* Copyright (C) 2017 Intel Corporation.
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#define G_LOG_DOMAIN "FuFirmware"
#include "config.h"
#include "fu-byte-array.h"
#include "fu-intel-thunderbolt-firmware.h"
#include "fu-mem.h"
/**
* FuIntelThunderboltFirmware:
*
* The Non-Volatile-Memory file-format specification. This is what you would find as the update
* payload.
*
* See also: [class@FuFirmware]
*/
G_DEFINE_TYPE(FuIntelThunderboltFirmware,
fu_intel_thunderbolt_firmware,
FU_TYPE_INTEL_THUNDERBOLT_NVM)
static gboolean
fu_intel_thunderbolt_nvm_valid_farb_pointer(guint32 pointer)
{
return pointer != 0 && pointer != 0xFFFFFF;
}
static gboolean
fu_intel_thunderbolt_firmware_parse(FuFirmware *firmware,
GBytes *fw,
gsize offset,
FwupdInstallFlags flags,
GError **error)
{
const guint32 farb_offsets[] = {0x0, 0x1000};
gboolean valid = FALSE;
guint32 farb_pointer = 0x0;
/* get header offset */
for (guint i = 0; i < G_N_ELEMENTS(farb_offsets); i++) {
if (!fu_memread_uint24_safe(g_bytes_get_data(fw, NULL),
g_bytes_get_size(fw),
offset + farb_offsets[i],
&farb_pointer,
G_LITTLE_ENDIAN,
error))
return FALSE;
if (fu_intel_thunderbolt_nvm_valid_farb_pointer(farb_pointer)) {
valid = TRUE;
break;
}
}
if (!valid) {
g_set_error_literal(error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"no valid farb pointer found");
return FALSE;
}
g_debug("detected digital section begins at 0x%x", farb_pointer);
fu_firmware_set_offset(firmware, farb_pointer);
/* FuIntelThunderboltNvm->parse */
return FU_FIRMWARE_CLASS(fu_intel_thunderbolt_firmware_parent_class)
->parse(firmware, fw, offset + farb_pointer, flags, error);
}
static GBytes *
fu_intel_thunderbolt_firmware_write(FuFirmware *firmware, GError **error)
{
g_autoptr(GByteArray) buf = g_byte_array_new();
g_autoptr(GBytes) blob = NULL;
/* sanity check */
if (fu_firmware_get_offset(firmware) < 0x08) {
g_set_error_literal(error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"not valid offset");
return NULL;
}
/* offset */
fu_byte_array_append_uint32(buf, fu_firmware_get_offset(firmware), G_LITTLE_ENDIAN);
fu_byte_array_set_size(buf, fu_firmware_get_offset(firmware), 0x00);
/* FuIntelThunderboltNvm->write */
blob =
FU_FIRMWARE_CLASS(fu_intel_thunderbolt_firmware_parent_class)->write(firmware, error);
fu_byte_array_append_bytes(buf, blob);
/* success */
return g_byte_array_free_to_bytes(g_steal_pointer(&buf));
}
static void
fu_intel_thunderbolt_firmware_init(FuIntelThunderboltFirmware *self)
{
}
static void
fu_intel_thunderbolt_firmware_class_init(FuIntelThunderboltFirmwareClass *klass)
{
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS(klass);
klass_firmware->parse = fu_intel_thunderbolt_firmware_parse;
klass_firmware->write = fu_intel_thunderbolt_firmware_write;
}
/**
* fu_intel_thunderbolt_firmware_new:
*
* Creates a new #FuFirmware of Intel NVM format
*
* Since: 1.8.5
**/
FuFirmware *
fu_intel_thunderbolt_firmware_new(void)
{
return FU_FIRMWARE(g_object_new(FU_TYPE_INTEL_THUNDERBOLT_FIRMWARE, NULL));
}