xref: /haiku/src/add-ons/kernel/file_systems/xfs/Checksum.h (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2022, Raghav Sharma, raghavself28@gmail.com
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _XFS_CKSUM_H
6 #define _XFS_CKSUM_H
7 
8 
9 #include "CRCTable.h"
10 #include "xfs_types.h"
11 #include "system_dependencies.h"
12 
13 
14 #define XFS_CRC_SEED	(~(uint32)0)
15 
16 
17 /*
18    Calculate the intermediate checksum for a buffer that has the CRC field
19    inside it.  The offset of the 32bit crc fields is passed as the
20    cksum_offset parameter. We do not modify the buffer during verification,
21    hence we have to split the CRC calculation across the cksum_offset.
22 */
23 static inline uint32
24 xfs_start_cksum_safe(const char *buffer, size_t length, uint32 cksum_offset)
25 {
26 	uint32 zero = 0;
27 	uint32 crc;
28 
29 	// Calculate CRC up to the checksum.
30 	crc = calculate_crc32c(XFS_CRC_SEED, (uint8*)buffer, cksum_offset);
31 
32 	// Skip checksum field
33 	crc = calculate_crc32c(crc, (uint8*)&zero, sizeof(uint32));
34 
35 	// Calculate the rest of the CRC.
36 	return calculate_crc32c(crc, (uint8*)buffer + cksum_offset + sizeof(uint32),
37 		      length - (cksum_offset + sizeof(uint32)));
38 }
39 
40 
41 /*
42    Fast CRC method where the buffer is modified. Callers must have exclusive
43    access to the buffer while the calculation takes place.
44 */
45 static inline uint32
46 xfs_start_cksum_update(const char *buffer, size_t length, uint32 cksum_offset)
47 {
48 	// zero the CRC field
49 	*(uint32 *)(buffer + cksum_offset) = 0;
50 
51 	// single pass CRC calculation for the entire buffer
52 	return calculate_crc32c(XFS_CRC_SEED, (uint8*)buffer, length);
53 }
54 
55 
56 /*
57    Helper to generate the checksum for a buffer.
58 
59    This modifies the buffer temporarily - callers must have exclusive
60    access to the buffer while the calculation takes place.
61 */
62 static inline void
63 xfs_update_cksum(const char *buffer, size_t length, uint32 cksum_offset)
64 {
65 	uint32 crc = xfs_start_cksum_update(buffer, length, cksum_offset);
66 
67 	*(uint32 *)(buffer + cksum_offset) = ~crc;
68 }
69 
70 
71 /*
72    Helper to verify the checksum for a buffer.
73 */
74 static inline int
75 xfs_verify_cksum(const char *buffer, size_t length, uint32 cksum_offset)
76 {
77 	uint32 crc = xfs_start_cksum_safe(buffer, length, cksum_offset);
78 
79 	TRACE("calculated crc: (%" B_PRIu32 ")\n", ~crc);
80 
81 	TRACE("buffer = %s, cksum_offset: (%" B_PRIu32 ")\n", buffer, cksum_offset);
82 
83 	return *(uint32 *)(buffer + cksum_offset) == (~crc);
84 }
85 
86 #endif