1ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/*
2ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos *      crc16.c
3ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos *
4ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * This source code is licensed under the GNU General Public License,
5ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * Version 2. See the file COPYING for more details.
6ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos */
7ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
8d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
90eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#if HAVE_SYS_TYPES_H
100eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#include <sys/types.h>
110eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#endif
120eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#include <ext2fs/ext2_types.h>
130eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o
14ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "crc16.h"
15ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
16ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
17c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'ostatic __u16 const crc16_table[256] = {
18ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
19ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
20ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
21ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
22ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
23ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
24ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
25ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
26ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
27ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
28ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
29ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
30ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
31ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
32ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
33ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
34ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
35ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
36ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
37ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
38ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
39ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
40ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
41ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
42ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
43ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
44ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
45ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
46ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
47ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
48ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
49ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
50ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos};
51ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
52ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/**
53ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * Compute the CRC-16 for the data buffer
54ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos *
55ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * @param crc     previous CRC value
56ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * @param buffer  data pointer
57ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * @param len     number of bytes in the buffer
58ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * @return        the updated CRC value
59ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos */
60c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'ocrc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len)
61ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{
62ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	const unsigned char *cp = buffer;
63ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
64ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	while (len--)
65c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		/*
66c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		 * for an unknown reason, PPC treats __u16 as signed
67c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		 * and keeps doing sign extension on the value.
68c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		 * Instead, use only the low 16 bits of an unsigned
69c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		 * int for holding the CRC value to avoid this.
70c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		 */
71c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		crc = (((crc >> 8) & 0xffU) ^
72c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		       crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU;
73ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	return crc;
74ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos}
75