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*/ 23static inline uint32 24xfs_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*/ 45static inline uint32 46xfs_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*/ 62static inline void 63xfs_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*/ 74static inline int 75xfs_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