/src/fwupd/plugins/bcm57xx/fu-bcm57xx-common.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2018 Evan Lojewski |
3 | | * Copyright 2020 Richard Hughes <richard@hughsie.com> |
4 | | * |
5 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
6 | | */ |
7 | | |
8 | | #include "config.h" |
9 | | |
10 | | #include <string.h> |
11 | | |
12 | | #include "fu-bcm57xx-common.h" |
13 | | |
14 | | gboolean |
15 | | fu_bcm57xx_verify_crc(GInputStream *stream, GError **error) |
16 | 3.09k | { |
17 | 3.09k | guint32 crc_actual = 0xFFFFFFFF; |
18 | 3.09k | guint32 crc_file = 0; |
19 | 3.09k | gsize streamsz = 0; |
20 | 3.09k | g_autoptr(GInputStream) stream_tmp = NULL; |
21 | | |
22 | | /* expected */ |
23 | 3.09k | if (!fu_input_stream_size(stream, &streamsz, error)) |
24 | 0 | return FALSE; |
25 | 3.09k | if (streamsz < sizeof(guint32)) { |
26 | 2 | g_set_error_literal(error, |
27 | 2 | FWUPD_ERROR, |
28 | 2 | FWUPD_ERROR_INVALID_DATA, |
29 | 2 | "image is too small for CRC"); |
30 | 2 | return FALSE; |
31 | 2 | } |
32 | 3.09k | if (!fu_input_stream_read_u32(stream, |
33 | 3.09k | streamsz - sizeof(guint32), |
34 | 3.09k | &crc_file, |
35 | 3.09k | G_LITTLE_ENDIAN, |
36 | 3.09k | error)) |
37 | 0 | return FALSE; |
38 | | |
39 | | /* reality */ |
40 | 3.09k | stream_tmp = fu_partial_input_stream_new(stream, 0, streamsz - sizeof(guint32), error); |
41 | 3.09k | if (stream_tmp == NULL) |
42 | 0 | return FALSE; |
43 | 3.09k | if (!fu_input_stream_compute_crc32(stream_tmp, |
44 | 3.09k | FU_CRC_KIND_B32_STANDARD, |
45 | 3.09k | &crc_actual, |
46 | 3.09k | error)) |
47 | 0 | return FALSE; |
48 | 3.09k | if (crc_actual != crc_file) { |
49 | 724 | g_set_error(error, |
50 | 724 | FWUPD_ERROR, |
51 | 724 | FWUPD_ERROR_NOT_SUPPORTED, |
52 | 724 | "invalid CRC, expected 0x%08x got: 0x%08x", |
53 | 724 | (guint)crc_file, |
54 | 724 | (guint)crc_actual); |
55 | 724 | return FALSE; |
56 | 724 | } |
57 | | |
58 | | /* success */ |
59 | 2.37k | return TRUE; |
60 | 3.09k | } |
61 | | |
62 | | gboolean |
63 | | fu_bcm57xx_verify_magic(GInputStream *stream, gsize offset, GError **error) |
64 | 2.57k | { |
65 | 2.57k | guint32 magic = 0; |
66 | | |
67 | | /* hardcoded value */ |
68 | 2.57k | if (!fu_input_stream_read_u32(stream, offset, &magic, G_BIG_ENDIAN, error)) |
69 | 118 | return FALSE; |
70 | 2.45k | if (magic != BCM_NVRAM_MAGIC) { |
71 | 62 | g_set_error(error, |
72 | 62 | FWUPD_ERROR, |
73 | 62 | FWUPD_ERROR_NOT_SUPPORTED, |
74 | 62 | "invalid magic, got: 0x%x", |
75 | 62 | (guint)magic); |
76 | 62 | return FALSE; |
77 | 62 | } |
78 | | |
79 | | /* success */ |
80 | 2.39k | return TRUE; |
81 | 2.45k | } |
82 | | |
83 | | void |
84 | | fu_bcm57xx_veritem_free(FuBcm57xxVeritem *veritem) |
85 | 74 | { |
86 | 74 | g_free(veritem->branch); |
87 | 74 | g_free(veritem->version); |
88 | 74 | g_free(veritem); |
89 | 74 | } |
90 | | |
91 | | FuBcm57xxVeritem * |
92 | | fu_bcm57xx_veritem_new(const guint8 *buf, gsize bufsz) |
93 | 74 | { |
94 | 74 | g_autofree gchar *tmp = NULL; |
95 | 74 | g_autoptr(FuBcm57xxVeritem) veritem = g_new0(FuBcm57xxVeritem, 1); |
96 | 74 | struct { |
97 | 74 | const gchar *prefix; |
98 | 74 | const gchar *branch; |
99 | 74 | FwupdVersionFormat verfmt; |
100 | 74 | } data[] = {{"5719-v", BCM_FW_BRANCH_UNKNOWN, FWUPD_VERSION_FORMAT_PAIR}, |
101 | 74 | {"stage1-", BCM_FW_BRANCH_OSS_FIRMWARE, FWUPD_VERSION_FORMAT_TRIPLET}, |
102 | 74 | {NULL, NULL, 0}}; |
103 | | |
104 | | /* do not assume this is NUL terminated */ |
105 | 74 | tmp = g_strndup((const gchar *)buf, bufsz); |
106 | 74 | if (tmp == NULL || tmp[0] == '\0') |
107 | 3 | return NULL; |
108 | | |
109 | | /* use prefix to define object */ |
110 | 198 | for (guint i = 0; data[i].prefix != NULL; i++) { |
111 | 136 | if (g_str_has_prefix(tmp, data[i].prefix)) { |
112 | 9 | veritem->version = g_strdup(tmp + strlen(data[i].prefix)); |
113 | 9 | veritem->branch = g_strdup(data[i].branch); |
114 | 9 | veritem->verfmt = data[i].verfmt; |
115 | 9 | return g_steal_pointer(&veritem); |
116 | 9 | } |
117 | 136 | } |
118 | 62 | veritem->verfmt = FWUPD_VERSION_FORMAT_UNKNOWN; |
119 | 62 | veritem->version = g_strdup(tmp); |
120 | 62 | return g_steal_pointer(&veritem); |
121 | 71 | } |