/src/fwupd/libfwupdplugin/fu-byte-array.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2017 Richard Hughes <richard@hughsie.com> |
3 | | * |
4 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
5 | | */ |
6 | | |
7 | 0 | #define G_LOG_DOMAIN "FuCommon" |
8 | | |
9 | | #include "config.h" |
10 | | |
11 | | #include "fu-byte-array.h" |
12 | | #include "fu-common.h" |
13 | | #include "fu-firmware-common.h" |
14 | | #include "fu-mem.h" |
15 | | |
16 | | /** |
17 | | * fu_byte_array_to_string: |
18 | | * @array: a #GByteArray |
19 | | * |
20 | | * Converts the byte array to a lowercase hex string. |
21 | | * |
22 | | * Returns: (transfer full): a string, which may be zero length |
23 | | * |
24 | | * Since: 1.8.9 |
25 | | **/ |
26 | | gchar * |
27 | | fu_byte_array_to_string(GByteArray *array) |
28 | 0 | { |
29 | 0 | g_autoptr(GString) str = g_string_new(NULL); |
30 | 0 | g_return_val_if_fail(array != NULL, NULL); |
31 | 0 | for (guint i = 0; i < array->len; i++) |
32 | 0 | g_string_append_printf(str, "%02x", array->data[i]); |
33 | 0 | return g_string_free(g_steal_pointer(&str), FALSE); |
34 | 0 | } |
35 | | |
36 | | /** |
37 | | * fu_byte_array_from_string: |
38 | | * @str: a hex string |
39 | | * @error: (nullable): optional return location for an error |
40 | | * |
41 | | * Converts a lowercase hex string to a byte array. |
42 | | * |
43 | | * Returns: (transfer full): a #GByteArray, or %NULL on error |
44 | | * |
45 | | * Since: 1.9.6 |
46 | | **/ |
47 | | GByteArray * |
48 | | fu_byte_array_from_string(const gchar *str, GError **error) |
49 | 0 | { |
50 | 0 | gsize strsz; |
51 | 0 | g_autoptr(GByteArray) buf = g_byte_array_new(); |
52 | |
|
53 | 0 | g_return_val_if_fail(str != NULL, NULL); |
54 | 0 | g_return_val_if_fail(error == NULL || *error == NULL, NULL); |
55 | | |
56 | 0 | strsz = strlen(str); |
57 | 0 | for (guint i = 0; i < strsz; i += 2) { |
58 | 0 | guint8 value = 0; |
59 | 0 | if (!fu_firmware_strparse_uint8_safe(str, strsz, i, &value, error)) |
60 | 0 | return NULL; |
61 | 0 | fu_byte_array_append_uint8(buf, value); |
62 | 0 | } |
63 | 0 | return g_steal_pointer(&buf); |
64 | 0 | } |
65 | | |
66 | | /** |
67 | | * fu_byte_array_append_uint8: |
68 | | * @array: a #GByteArray |
69 | | * @data: value |
70 | | * |
71 | | * Adds a 8 bit integer to a byte array. |
72 | | * |
73 | | * Since: 1.3.1 |
74 | | **/ |
75 | | void |
76 | | fu_byte_array_append_uint8(GByteArray *array, guint8 data) |
77 | 178M | { |
78 | 178M | g_byte_array_append(array, &data, sizeof(data)); |
79 | 178M | } |
80 | | |
81 | | /** |
82 | | * fu_byte_array_append_uint16: |
83 | | * @array: a #GByteArray |
84 | | * @data: value |
85 | | * @endian: endian type, e.g. #G_LITTLE_ENDIAN |
86 | | * |
87 | | * Adds a 16 bit integer to a byte array. |
88 | | * |
89 | | * Since: 1.3.1 |
90 | | **/ |
91 | | void |
92 | | fu_byte_array_append_uint16(GByteArray *array, guint16 data, FuEndianType endian) |
93 | 719k | { |
94 | 719k | guint8 buf[2]; |
95 | 719k | fu_memwrite_uint16(buf, data, endian); |
96 | 719k | g_byte_array_append(array, buf, sizeof(buf)); |
97 | 719k | } |
98 | | |
99 | | /** |
100 | | * fu_byte_array_append_uint24: |
101 | | * @array: a #GByteArray |
102 | | * @data: value |
103 | | * @endian: endian type, e.g. #G_LITTLE_ENDIAN |
104 | | * |
105 | | * Adds a 24 bit integer to a byte array. |
106 | | * |
107 | | * Since: 1.8.13 |
108 | | **/ |
109 | | void |
110 | | fu_byte_array_append_uint24(GByteArray *array, guint32 data, FuEndianType endian) |
111 | 0 | { |
112 | 0 | guint8 buf[3]; |
113 | 0 | fu_memwrite_uint24(buf, data, endian); |
114 | 0 | g_byte_array_append(array, buf, sizeof(buf)); |
115 | 0 | } |
116 | | |
117 | | /** |
118 | | * fu_byte_array_append_uint32: |
119 | | * @array: a #GByteArray |
120 | | * @data: value |
121 | | * @endian: endian type, e.g. #G_LITTLE_ENDIAN |
122 | | * |
123 | | * Adds a 32 bit integer to a byte array. |
124 | | * |
125 | | * Since: 1.3.1 |
126 | | **/ |
127 | | void |
128 | | fu_byte_array_append_uint32(GByteArray *array, guint32 data, FuEndianType endian) |
129 | 196k | { |
130 | 196k | guint8 buf[4]; |
131 | 196k | fu_memwrite_uint32(buf, data, endian); |
132 | 196k | g_byte_array_append(array, buf, sizeof(buf)); |
133 | 196k | } |
134 | | |
135 | | /** |
136 | | * fu_byte_array_append_uint64: |
137 | | * @array: a #GByteArray |
138 | | * @data: value |
139 | | * @endian: endian type, e.g. #G_LITTLE_ENDIAN |
140 | | * |
141 | | * Adds a 64 bit integer to a byte array. |
142 | | * |
143 | | * Since: 1.5.8 |
144 | | **/ |
145 | | void |
146 | | fu_byte_array_append_uint64(GByteArray *array, guint64 data, FuEndianType endian) |
147 | 0 | { |
148 | 0 | guint8 buf[8]; |
149 | 0 | fu_memwrite_uint64(buf, data, endian); |
150 | 0 | g_byte_array_append(array, buf, sizeof(buf)); |
151 | 0 | } |
152 | | |
153 | | /** |
154 | | * fu_byte_array_append_bytes: |
155 | | * @array: a #GByteArray |
156 | | * @bytes: data blob |
157 | | * |
158 | | * Adds the contents of a GBytes to a byte array. |
159 | | * |
160 | | * Since: 1.5.8 |
161 | | **/ |
162 | | void |
163 | | fu_byte_array_append_bytes(GByteArray *array, GBytes *bytes) |
164 | 262k | { |
165 | 262k | g_byte_array_append(array, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes)); |
166 | 262k | } |
167 | | |
168 | | /** |
169 | | * fu_byte_array_set_size: |
170 | | * @array: a #GByteArray |
171 | | * @length: the new size of the GByteArray |
172 | | * @data: the byte used to pad the array |
173 | | * |
174 | | * Sets the size of the GByteArray, expanding with @data as required. |
175 | | * |
176 | | * Since: 1.8.2 |
177 | | **/ |
178 | | void |
179 | | fu_byte_array_set_size(GByteArray *array, gsize length, guint8 data) |
180 | 170k | { |
181 | 170k | guint oldlength = array->len; |
182 | 170k | g_return_if_fail(array != NULL); |
183 | 170k | g_return_if_fail(length < G_MAXUINT); |
184 | 170k | g_byte_array_set_size(array, length); |
185 | 170k | if (length > oldlength) |
186 | 145k | memset(array->data + oldlength, data, length - oldlength); |
187 | 170k | } |
188 | | |
189 | | /** |
190 | | * fu_byte_array_align_up: |
191 | | * @array: a #GByteArray |
192 | | * @alignment: align to this power of 2 |
193 | | * @data: the byte used to pad the array |
194 | | * |
195 | | * Align a byte array length to a power of 2 boundary, where @alignment is the |
196 | | * bit position to align to. If @alignment is zero then @array is unchanged. |
197 | | * |
198 | | * Since: 1.6.0 |
199 | | **/ |
200 | | void |
201 | | fu_byte_array_align_up(GByteArray *array, guint8 alignment, guint8 data) |
202 | 45.2k | { |
203 | 45.2k | fu_byte_array_set_size(array, fu_common_align_up(array->len, alignment), data); |
204 | 45.2k | } |
205 | | |
206 | | /** |
207 | | * fu_byte_array_compare: |
208 | | * @buf1: a data blob |
209 | | * @buf2: another #GByteArray |
210 | | * @error: (nullable): optional return location for an error |
211 | | * |
212 | | * Compares two buffers for equality. |
213 | | * |
214 | | * Returns: %TRUE if @buf1 and @buf2 are identical |
215 | | * |
216 | | * Since: 1.8.0 |
217 | | **/ |
218 | | gboolean |
219 | | fu_byte_array_compare(GByteArray *buf1, GByteArray *buf2, GError **error) |
220 | 0 | { |
221 | 0 | g_return_val_if_fail(buf1 != NULL, FALSE); |
222 | 0 | g_return_val_if_fail(buf2 != NULL, FALSE); |
223 | 0 | g_return_val_if_fail(error == NULL || *error == NULL, FALSE); |
224 | 0 | return fu_memcmp_safe(buf1->data, |
225 | 0 | buf1->len, |
226 | 0 | 0x0, |
227 | 0 | buf2->data, |
228 | 0 | buf2->len, |
229 | 0 | 0x0, |
230 | 0 | MAX(buf1->len, buf2->len), |
231 | 0 | error); |
232 | 0 | } |