/src/fwupd/libfwupdplugin/fu-crc.c
Line | Count | Source |
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 <zlib.h> |
12 | | |
13 | | #include "fu-common.h" |
14 | | #include "fu-crc-private.h" |
15 | | #include "fu-mem.h" |
16 | | |
17 | | const struct { |
18 | | FuCrcKind kind; |
19 | | guint bitwidth; |
20 | | guint32 poly; |
21 | | guint32 init; |
22 | | gboolean reflected; |
23 | | guint32 xorout; |
24 | | } crc_map[] = { |
25 | | {FU_CRC_KIND_UNKNOWN, 32, 0x00000000, 0x00000000, TRUE, 0xFFFFFFFF}, |
26 | | {FU_CRC_KIND_B32_STANDARD, 32, 0x04C11DB7, 0xFFFFFFFF, TRUE, 0xFFFFFFFF}, |
27 | | {FU_CRC_KIND_B32_BZIP2, 32, 0x04C11DB7, 0xFFFFFFFF, FALSE, 0xFFFFFFFF}, |
28 | | {FU_CRC_KIND_B32_JAMCRC, 32, 0x04C11DB7, 0xFFFFFFFF, TRUE, 0x00000000}, |
29 | | {FU_CRC_KIND_B32_MPEG2, 32, 0x04C11DB7, 0xFFFFFFFF, FALSE, 0x00000000}, |
30 | | {FU_CRC_KIND_B32_POSIX, 32, 0x04C11DB7, 0x00000000, FALSE, 0xFFFFFFFF}, |
31 | | {FU_CRC_KIND_B32_SATA, 32, 0x04C11DB7, 0x52325032, FALSE, 0x00000000}, |
32 | | {FU_CRC_KIND_B32_XFER, 32, 0x000000AF, 0x00000000, FALSE, 0x00000000}, |
33 | | {FU_CRC_KIND_B32C, 32, 0x1EDC6F41, 0xFFFFFFFF, TRUE, 0xFFFFFFFF}, |
34 | | {FU_CRC_KIND_B32D, 32, 0xA833982B, 0xFFFFFFFF, TRUE, 0xFFFFFFFF}, |
35 | | {FU_CRC_KIND_B32Q, 32, 0x814141AB, 0x00000000, FALSE, 0x00000000}, |
36 | | {FU_CRC_KIND_B16_XMODEM, 16, 0x1021, 0x0000, FALSE, 0x0000}, |
37 | | {FU_CRC_KIND_B16_KERMIT, 16, 0x1021, 0x0000, TRUE, 0x0000}, |
38 | | {FU_CRC_KIND_B16_USB, 16, 0x8005, 0xFFFF, TRUE, 0xFFFF}, |
39 | | {FU_CRC_KIND_B16_UMTS, 16, 0x8005, 0x0000, FALSE, 0x0000}, |
40 | | {FU_CRC_KIND_B16_TMS37157, 16, 0x1021, 0x89ec, TRUE, 0x0000}, |
41 | | {FU_CRC_KIND_B16_BNR, 16, 0x8005, 0xFFFF, FALSE, 0x0000}, |
42 | | {FU_CRC_KIND_B8_WCDMA, 8, 0x9B, 0x00, TRUE, 0x00}, |
43 | | {FU_CRC_KIND_B8_TECH3250, 8, 0x1D, 0xFF, TRUE, 0x00}, |
44 | | {FU_CRC_KIND_B8_STANDARD, 8, 0x07, 0x00, FALSE, 0x00}, |
45 | | {FU_CRC_KIND_B8_SAE_J1850, 8, 0x1D, 0xFF, FALSE, 0xFF}, |
46 | | {FU_CRC_KIND_B8_ROHC, 8, 0x07, 0xFF, TRUE, 0x00}, |
47 | | {FU_CRC_KIND_B8_OPENSAFETY, 8, 0x2F, 0x00, FALSE, 0x00}, |
48 | | {FU_CRC_KIND_B8_NRSC5, 8, 0x31, 0xFF, FALSE, 0x00}, |
49 | | {FU_CRC_KIND_B8_MIFARE_MAD, 8, 0x1D, 0xC7, FALSE, 0x00}, |
50 | | {FU_CRC_KIND_B8_MAXIM_DOW, 8, 0x31, 0x00, TRUE, 0x00}, |
51 | | {FU_CRC_KIND_B8_LTE, 8, 0x9B, 0x00, FALSE, 0x00}, |
52 | | {FU_CRC_KIND_B8_I_CODE, 8, 0x1D, 0xFD, FALSE, 0x00}, |
53 | | {FU_CRC_KIND_B8_ITU, 8, 0x07, 0x00, FALSE, 0x55}, |
54 | | {FU_CRC_KIND_B8_HITAG, 8, 0x1D, 0xFF, FALSE, 0x00}, |
55 | | {FU_CRC_KIND_B8_GSM_B, 8, 0x49, 0x00, FALSE, 0xFF}, |
56 | | {FU_CRC_KIND_B8_GSM_A, 8, 0x1D, 0x00, FALSE, 0x00}, |
57 | | {FU_CRC_KIND_B8_DVB_S2, 8, 0xD5, 0x00, FALSE, 0x00}, |
58 | | {FU_CRC_KIND_B8_DARC, 8, 0x39, 0x00, TRUE, 0x00}, |
59 | | {FU_CRC_KIND_B8_CDMA2000, 8, 0x9B, 0xFF, FALSE, 0x00}, |
60 | | {FU_CRC_KIND_B8_BLUETOOTH, 8, 0xA7, 0x00, TRUE, 0x00}, |
61 | | {FU_CRC_KIND_B8_AUTOSAR, 8, 0x2F, 0xFF, FALSE, 0xFF}, |
62 | | }; |
63 | | |
64 | | static guint8 |
65 | | fu_crc_reflect8(guint8 data) |
66 | 11.5M | { |
67 | 11.5M | guint8 val = 0; |
68 | 103M | for (guint8 bit = 0; bit < 8; bit++) { |
69 | 92.2M | if (data & 0x01) |
70 | 16.4M | FU_BIT_SET(val, 7 - bit); |
71 | 92.2M | data = (data >> 1); |
72 | 92.2M | } |
73 | 11.5M | return val; |
74 | 11.5M | } |
75 | | |
76 | | static guint32 |
77 | | fu_crc_reflect(guint32 data, guint bitwidth) |
78 | 624 | { |
79 | 624 | guint32 val = 0; |
80 | 20.5k | for (guint bit = 0; bit < bitwidth; bit++) { |
81 | 19.9k | if (data & 0x01) |
82 | 10.0k | val |= 1ul << ((bitwidth - 1) - bit); /* nocheck:blocked */ |
83 | 19.9k | data = (data >> 1); |
84 | 19.9k | } |
85 | 624 | return val; |
86 | 624 | } |
87 | | |
88 | | /** |
89 | | * fu_crc_size: |
90 | | * @kind: a #FuCrcKind |
91 | | * |
92 | | * Returns the size of the CRC in bits. |
93 | | * |
94 | | * Returns: integer, or 0 on error |
95 | | * |
96 | | * Since: 2.0.19 |
97 | | **/ |
98 | | guint |
99 | | fu_crc_size(FuCrcKind kind) |
100 | 0 | { |
101 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
102 | 0 | return crc_map[kind].bitwidth; |
103 | 0 | } |
104 | | |
105 | | /** |
106 | | * fu_crc8_step: |
107 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B8_MAXIM_DOW |
108 | | * @buf: memory buffer |
109 | | * @bufsz: size of @buf |
110 | | * @crc: initial CRC value |
111 | | * |
112 | | * Computes the cyclic redundancy check section value for the given memory buffer. |
113 | | * |
114 | | * NOTE: When all data has been added, you should call fu_crc8_done() to return the final value. |
115 | | * |
116 | | * Returns: CRC value |
117 | | * |
118 | | * Since: 2.0.0 |
119 | | **/ |
120 | | guint8 |
121 | | fu_crc8_step(FuCrcKind kind, const guint8 *buf, gsize bufsz, guint8 crc) |
122 | 0 | { |
123 | 0 | const guint bitwidth = sizeof(crc) * 8; |
124 | |
|
125 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
126 | 0 | g_return_val_if_fail(crc_map[kind].bitwidth == 8, 0x0); |
127 | | |
128 | 0 | for (gsize i = 0; i < bufsz; ++i) { |
129 | 0 | crc ^= crc_map[kind].reflected ? fu_crc_reflect8(buf[i]) : buf[i]; |
130 | 0 | for (guint8 bit = 0; bit < 8; bit++) { |
131 | 0 | if (crc & (1ul << (bitwidth - 1))) { |
132 | 0 | crc = (crc << 1) ^ crc_map[kind].poly; |
133 | 0 | } else { |
134 | 0 | crc = (crc << 1); |
135 | 0 | } |
136 | 0 | } |
137 | 0 | } |
138 | 0 | return crc; |
139 | 0 | } |
140 | | |
141 | | /** |
142 | | * fu_crc8_done: |
143 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B8_MAXIM_DOW |
144 | | * @crc: initial CRC value |
145 | | * |
146 | | * Returns the finished cyclic redundancy check value. |
147 | | * |
148 | | * Returns: CRC value |
149 | | * |
150 | | * Since: 2.0.0 |
151 | | **/ |
152 | | guint8 |
153 | | fu_crc8_done(FuCrcKind kind, guint8 crc) |
154 | 0 | { |
155 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
156 | 0 | g_return_val_if_fail(crc_map[kind].bitwidth == 8, 0x0); |
157 | 0 | crc = crc_map[kind].reflected ? fu_crc_reflect(crc, crc_map[kind].bitwidth) : crc; |
158 | 0 | return crc ^ crc_map[kind].xorout; |
159 | 0 | } |
160 | | |
161 | | /** |
162 | | * fu_crc8: |
163 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B8_MAXIM_DOW |
164 | | * @buf: memory buffer |
165 | | * @bufsz: size of @buf |
166 | | * |
167 | | * Returns the cyclic redundancy check value for the given memory buffer. |
168 | | * |
169 | | * Returns: CRC value |
170 | | * |
171 | | * Since: 2.0.0 |
172 | | **/ |
173 | | guint8 |
174 | | fu_crc8(FuCrcKind kind, const guint8 *buf, gsize bufsz) |
175 | 0 | { |
176 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
177 | 0 | g_return_val_if_fail(crc_map[kind].bitwidth == 8, 0x0); |
178 | 0 | return fu_crc8_done(kind, fu_crc8_step(kind, buf, bufsz, crc_map[kind].init)); |
179 | 0 | } |
180 | | |
181 | | /** |
182 | | * fu_crc8_bytes: |
183 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B8_MAXIM_DOW |
184 | | * @blob: a #GBytes |
185 | | * |
186 | | * Returns the cyclic redundancy check value for the given memory buffer. |
187 | | * |
188 | | * Returns: CRC value |
189 | | * |
190 | | * Since: 2.0.2 |
191 | | **/ |
192 | | guint8 |
193 | | fu_crc8_bytes(FuCrcKind kind, GBytes *blob) |
194 | 0 | { |
195 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
196 | 0 | g_return_val_if_fail(blob != NULL, 0x0); |
197 | 0 | return fu_crc8(kind, g_bytes_get_data(blob, NULL), g_bytes_get_size(blob)); |
198 | 0 | } |
199 | | |
200 | | /** |
201 | | * fu_crc16_step: |
202 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B16_XMODEM |
203 | | * @buf: memory buffer |
204 | | * @bufsz: size of @buf |
205 | | * @crc: initial CRC value |
206 | | * |
207 | | * Computes the cyclic redundancy check section value for the given memory buffer. |
208 | | * |
209 | | * NOTE: When all data has been added, you should call fu_crc16_done() to return the final value. |
210 | | * |
211 | | * Returns: CRC value |
212 | | * |
213 | | * Since: 2.0.0 |
214 | | **/ |
215 | | guint16 |
216 | | fu_crc16_step(FuCrcKind kind, const guint8 *buf, gsize bufsz, guint16 crc) |
217 | 0 | { |
218 | 0 | const guint bitwidth = sizeof(crc) * 8; |
219 | |
|
220 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
221 | 0 | g_return_val_if_fail(crc_map[kind].bitwidth == 16, 0x0); |
222 | | |
223 | 0 | for (gsize i = 0; i < bufsz; ++i) { |
224 | 0 | guint16 tmp = crc_map[kind].reflected ? fu_crc_reflect8(buf[i]) : buf[i]; |
225 | 0 | crc ^= tmp << (bitwidth - 8); |
226 | 0 | for (guint8 bit = 0; bit < 8; bit++) { |
227 | 0 | if (crc & (1ul << (bitwidth - 1))) { |
228 | 0 | crc = (crc << 1) ^ crc_map[kind].poly; |
229 | 0 | } else { |
230 | 0 | crc = (crc << 1); |
231 | 0 | } |
232 | 0 | } |
233 | 0 | } |
234 | 0 | return crc; |
235 | 0 | } |
236 | | |
237 | | /** |
238 | | * fu_crc16_done: |
239 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B16_XMODEM |
240 | | * @crc: initial CRC value |
241 | | * |
242 | | * Returns the finished cyclic redundancy check value. |
243 | | * |
244 | | * Returns: CRC value |
245 | | * |
246 | | * Since: 2.0.0 |
247 | | **/ |
248 | | guint16 |
249 | | fu_crc16_done(FuCrcKind kind, guint16 crc) |
250 | 0 | { |
251 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
252 | 0 | g_return_val_if_fail(crc_map[kind].bitwidth == 16, 0x0); |
253 | 0 | crc = crc_map[kind].reflected ? fu_crc_reflect(crc, crc_map[kind].bitwidth) : crc; |
254 | 0 | return crc ^ crc_map[kind].xorout; |
255 | 0 | } |
256 | | |
257 | | /** |
258 | | * fu_crc16: |
259 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B16_XMODEM |
260 | | * @buf: memory buffer |
261 | | * @bufsz: size of @buf |
262 | | * |
263 | | * Returns the cyclic redundancy check value for the given memory buffer. |
264 | | * |
265 | | * Returns: CRC value |
266 | | * |
267 | | * Since: 2.0.0 |
268 | | **/ |
269 | | guint16 |
270 | | fu_crc16(FuCrcKind kind, const guint8 *buf, gsize bufsz) |
271 | 0 | { |
272 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
273 | 0 | g_return_val_if_fail(crc_map[kind].bitwidth == 16, 0x0); |
274 | 0 | return fu_crc16_done(kind, fu_crc16_step(kind, buf, bufsz, crc_map[kind].init)); |
275 | 0 | } |
276 | | |
277 | | /** |
278 | | * fu_crc16_bytes: |
279 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B16_XMODEM |
280 | | * @blob: a #GBytes |
281 | | * |
282 | | * Returns the cyclic redundancy check value for the given memory buffer. |
283 | | * |
284 | | * Returns: CRC value |
285 | | * |
286 | | * Since: 2.0.2 |
287 | | **/ |
288 | | guint16 |
289 | | fu_crc16_bytes(FuCrcKind kind, GBytes *blob) |
290 | 0 | { |
291 | 0 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
292 | 0 | g_return_val_if_fail(blob != NULL, 0x0); |
293 | 0 | return fu_crc16(kind, g_bytes_get_data(blob, NULL), g_bytes_get_size(blob)); |
294 | 0 | } |
295 | | |
296 | | /** |
297 | | * fu_crc32_step: |
298 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B32_STANDARD |
299 | | * @buf: memory buffer |
300 | | * @bufsz: size of @buf |
301 | | * @crc: initial CRC value |
302 | | * |
303 | | * Computes the cyclic redundancy check section value for the given memory buffer. |
304 | | * |
305 | | * NOTE: When all data has been added, you should call fu_crc32_done() to return the final value. |
306 | | * |
307 | | * Returns: CRC value |
308 | | * |
309 | | * Since: 2.0.0 |
310 | | **/ |
311 | | guint32 |
312 | | fu_crc32_step(FuCrcKind kind, const guint8 *buf, gsize bufsz, guint32 crc) |
313 | 3.88k | { |
314 | 3.88k | const guint bitwidth = sizeof(crc) * 8; |
315 | | |
316 | 3.88k | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
317 | 3.88k | g_return_val_if_fail(crc_map[kind].bitwidth == 32, 0x0); |
318 | | |
319 | | /* use hand-crafted assembly with pre-computed table for raw speed */ |
320 | 3.88k | if (kind == FU_CRC_KIND_B32_STANDARD) |
321 | 3.25k | return crc32_z(crc, buf, bufsz); |
322 | | |
323 | 11.5M | for (gsize i = 0; i < bufsz; ++i) { |
324 | 11.5M | guint32 tmp = crc_map[kind].reflected ? fu_crc_reflect8(buf[i]) : buf[i]; |
325 | 11.5M | crc ^= tmp << (bitwidth - 8); |
326 | 103M | for (guint8 bit = 0; bit < 8; bit++) { |
327 | 92.2M | if (crc & (1ul << (bitwidth - 1))) { |
328 | 46.1M | crc = (crc << 1) ^ crc_map[kind].poly; |
329 | 46.1M | } else { |
330 | 46.1M | crc = (crc << 1); |
331 | 46.1M | } |
332 | 92.2M | } |
333 | 11.5M | } |
334 | 624 | return crc; |
335 | 3.88k | } |
336 | | |
337 | | /** |
338 | | * fu_crc32_done: |
339 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B32_STANDARD |
340 | | * @crc: initial CRC value |
341 | | * |
342 | | * Returns the finished cyclic redundancy check value. |
343 | | * |
344 | | * Returns: CRC value |
345 | | * |
346 | | * Since: 2.0.0 |
347 | | **/ |
348 | | guint32 |
349 | | fu_crc32_done(FuCrcKind kind, guint32 crc) |
350 | 3.54k | { |
351 | 3.54k | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
352 | 3.54k | g_return_val_if_fail(crc_map[kind].bitwidth == 32, 0x0); |
353 | 3.54k | if (kind == FU_CRC_KIND_B32_STANDARD) |
354 | 2.92k | return crc; |
355 | 624 | crc = crc_map[kind].reflected ? fu_crc_reflect(crc, crc_map[kind].bitwidth) : crc; |
356 | 624 | return crc ^ crc_map[kind].xorout; |
357 | 3.54k | } |
358 | | |
359 | | /** |
360 | | * fu_crc32: |
361 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B32_STANDARD |
362 | | * @buf: memory buffer |
363 | | * @bufsz: size of @buf |
364 | | * |
365 | | * Returns the cyclic redundancy check value for the given memory buffer. |
366 | | * |
367 | | * Returns: CRC value |
368 | | * |
369 | | * Since: 2.0.0 |
370 | | **/ |
371 | | guint32 |
372 | | fu_crc32(FuCrcKind kind, const guint8 *buf, gsize bufsz) |
373 | 2.37k | { |
374 | 2.37k | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
375 | 2.37k | g_return_val_if_fail(crc_map[kind].bitwidth == 32, 0x0); |
376 | | |
377 | | /* use hand-crafted assembly with pre-computed table for raw speed */ |
378 | 2.37k | if (kind == FU_CRC_KIND_B32_STANDARD) |
379 | 1.75k | return crc32_z(0, buf, bufsz); |
380 | | |
381 | 624 | return fu_crc32_done(kind, fu_crc32_step(kind, buf, bufsz, crc_map[kind].init)); |
382 | 2.37k | } |
383 | | |
384 | | /** |
385 | | * fu_crc32_bytes: |
386 | | * @kind: a #FuCrcKind, typically %FU_CRC_KIND_B32_STANDARD |
387 | | * @blob: a #GBytes |
388 | | * |
389 | | * Returns the cyclic redundancy check value for the given memory buffer. |
390 | | * |
391 | | * Returns: CRC value |
392 | | * |
393 | | * Since: 2.0.2 |
394 | | **/ |
395 | | guint32 |
396 | | fu_crc32_bytes(FuCrcKind kind, GBytes *blob) |
397 | 746 | { |
398 | 746 | g_return_val_if_fail(kind < FU_CRC_KIND_LAST, 0x0); |
399 | 746 | g_return_val_if_fail(blob != NULL, 0x0); |
400 | 746 | return fu_crc32(kind, g_bytes_get_data(blob, NULL), g_bytes_get_size(blob)); |
401 | 746 | } |
402 | | |
403 | | /** |
404 | | * fu_crc_find: |
405 | | * @buf: memory buffer |
406 | | * @bufsz: size of @buf |
407 | | * @crc_target: "correct" CRC value |
408 | | * |
409 | | * Returns the cyclic redundancy kind for the given memory buffer and target CRC. |
410 | | * |
411 | | * You can use a very simple buffer to discover most types of standard CRC-32: |
412 | | * |
413 | | * guint8 buf[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
414 | | * g_info("CRC:%u", fu_crc_find(buf, sizeof(buf), _custom_crc(buf, sizeof(buf)))); |
415 | | * |
416 | | * Returns: a #FuCrcKind, or %FU_CRC_KIND_UNKNOWN on error |
417 | | * |
418 | | * Since: 2.0.0 |
419 | | **/ |
420 | | FuCrcKind |
421 | | fu_crc_find(const guint8 *buf, gsize bufsz, guint32 crc_target) |
422 | 0 | { |
423 | 0 | for (guint i = 0; i < G_N_ELEMENTS(crc_map); i++) { |
424 | 0 | if (crc_map[i].bitwidth == 32) { |
425 | 0 | if (crc_target == fu_crc32(crc_map[i].kind, buf, bufsz)) |
426 | 0 | return crc_map[i].kind; |
427 | 0 | } |
428 | 0 | if (crc_target <= G_MAXUINT16 && crc_map[i].bitwidth == 16) { |
429 | 0 | if ((guint16)crc_target == fu_crc16(crc_map[i].kind, buf, bufsz)) |
430 | 0 | return crc_map[i].kind; |
431 | 0 | } |
432 | 0 | if (crc_target <= G_MAXUINT8 && crc_map[i].bitwidth == 8) { |
433 | 0 | if ((guint8)crc_target == fu_crc8(crc_map[i].kind, buf, bufsz)) |
434 | 0 | return crc_map[i].kind; |
435 | 0 | } |
436 | 0 | } |
437 | 0 | return FU_CRC_KIND_UNKNOWN; |
438 | 0 | } |
439 | | |
440 | | static guint16 |
441 | | fu_crc_misr16_step(guint16 cur, guint16 new) |
442 | 0 | { |
443 | 0 | guint16 bit0; |
444 | 0 | guint16 res; |
445 | |
|
446 | 0 | bit0 = cur ^ (new & 1); |
447 | 0 | bit0 ^= cur >> 1; |
448 | 0 | bit0 ^= cur >> 2; |
449 | 0 | bit0 ^= cur >> 4; |
450 | 0 | bit0 ^= cur >> 5; |
451 | 0 | bit0 ^= cur >> 7; |
452 | 0 | bit0 ^= cur >> 11; |
453 | 0 | bit0 ^= cur >> 15; |
454 | 0 | res = (cur << 1) ^ new; |
455 | 0 | res = (res & ~1) | (bit0 & 1); |
456 | 0 | return res; |
457 | 0 | } |
458 | | |
459 | | /** |
460 | | * fu_crc_misr16: |
461 | | * @buf: memory buffer |
462 | | * @bufsz: size of @buf |
463 | | * @init: initial value, typically 0x0 |
464 | | * |
465 | | * Returns the MISR check value for the given memory buffer. |
466 | | * |
467 | | * Returns: value |
468 | | * |
469 | | * Since: 1.9.17 |
470 | | **/ |
471 | | guint16 |
472 | | fu_crc_misr16(guint16 init, const guint8 *buf, gsize bufsz) |
473 | 0 | { |
474 | 0 | g_return_val_if_fail(buf != NULL, G_MAXUINT16); |
475 | 0 | g_return_val_if_fail(bufsz % 2 == 0, G_MAXUINT16); |
476 | | |
477 | 0 | for (gsize i = 0; i < bufsz; i += 2) |
478 | 0 | init = fu_crc_misr16_step(init, fu_memread_uint16(buf + i, G_LITTLE_ENDIAN)); |
479 | 0 | return init; |
480 | 0 | } |