/* * crc.c * * PURPOSE * CRC-16 routines for the OSTA-UDF(tm) file system. * * DESCRIPTION * CRCs are calculated by dividing a message bit stream by a polynomial * bit stream using XOR instead of subtraction. The CRC is the Nth * remainder for a N-bit stream. * * WARNING! UDF divides a MSB bit stream by a MSB polynomial, and most of * the rest of the universe divides a LSB bit stream by a MSB polynomial. * Reverse the bit order of the polynomial, test for CRC bit 0 set (if so * XOR CRC with polynomial), and do shifts to the right. * * The CRC-16 polynomial used is x^16 + x^12 + x^5 + 1. The polynomial in * binary is: 1 0001 0000 0010 0001. This is the standard CCITT one. * * Since the most significant bit (on the left) is either 0, or if 1 it is * always XOR'ed with 1 (the MSB of the polynomial) resulting in 0, it can * be ignored. This reduces the register size required to a handy 16-bits. * * Example: CRC-16 of 0xa5 * 10101011 * 10001000000100001 | 10100101.0000000000000000 * 10001000 000100001 * ================== * 1st remainder 101001 0001000010 * 000000 0000000000 * ================= * 2nd remainder 101001 00010000100 * 100010 00000100001 * ================== * 3rd remainder 1011 000101001010 * 0000 000000000000 * ================= * 4th remainder 1011 0001010010100 * 1000 1000000100001 * ================== * 5th remainder 11 10010101101010 * 00 00000000000000 * ================= * 6th remainder 11 100101011010100 * 10 001000000100001 * ================== * 7th remainder 1 1011010111101010 * 1 0001000000100001 * =================== * 8th remainder 1010010111001011 * * Note that a CRC can be implemented in hardware by a linear feedback * shift register. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ #if !defined(GENERATE) #include /* CRC-16 table, based on the CCITT polynomial and an initial value of 0 */ static __u16 crc_tbl[256] = { 0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U, 0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU, 0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U, 0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU, 0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U, 0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU, 0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U, 0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU, 0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U, 0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU, 0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U, 0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU, 0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U, 0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U, 0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U, 0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U, 0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU, 0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U, 0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU, 0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U, 0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU, 0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U, 0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU, 0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U, 0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU, 0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U, 0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU, 0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U, 0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U, 0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U, 0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U, 0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U }; /* * udf_crc * * PURPOSE * Calculate a CRC-16 a byte at a time by using the table. * * DESCRIPTION * The following is describes the contents of a linear feedback shift * register after every shift. Notice the symmetry between R and D. * * Shift 1: * R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 * R15 R15 R15 * D07 D07 D07 * Shift 2: * R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 * R15 R14 R15 R14 R15 R14 * D07 D06 D07 D06 D07 D06 * Shift 3: * R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 * R15 R14 R13 R15 R14 R13 R15 R14 R13 * D07 D06 D05 D07 D06 D05 D07 D06 D05 * Shift 4: * R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 * R15 R14 R13 R12 R15 R14 R13 R12 R15 R14 R13 R12 * D07 D06 D05 D04 D07 D06 D05 D04 D07 D06 D05 D04 * Shift 5: * R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 * R14 R13 R12 R11 R14 R13 R12 R11 R14 R13 R12 R11 * R15 R15 R15 R15 R15 * D06 D05 D04 D03 D06 D05 D04 D03 D06 D05 D04 D03 * D07 D07 D07 D07 D07 * Shift 6: * R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 * R13 R12 R11 R10 R13 R12 R11 R10 R13 R12 R11 R10 * R15 R14 R15 R14 R15 R14 R15 R14 * R15 R14 * D05 D04 D03 D02 D05 D04 D03 D02 D05 D04 D03 D02 * D07 D06 D07 D06 D07 D06 D07 D06 * D07 D06 * Shift 7: * R08 R07 R06 R05 R04 R03 R02 R01 R00 * R12 R11 R10 R09 R12 R11 R10 R09 R12 R11 R10 R09 * R15 R14 R13 R15 R14 R13 R15 R14 R13 R15 R14 R13 * R15 R14 R13 * D04 D03 D02 D01 D04 D03 D02 D01 D04 D03 D02 D01 * D07 D06 D05 D07 D06 D05 D07 D06 D05 D07 D06 D05 * D07 D06 D05 * Shift 8: * R07 R06 R05 R04 R03 R02 R01 R00 * R11 R10 R09 R08 R11 R10 R09 R08 R11 R10 R09 R08 * R15 R14 R13 R12 R15 R14 R13 R12 R15 R14 R13 R12 * R15 R14 R13 R12 R15 R14 R13 R12 * D03 D02 D01 D00 D03 D02 D01 R00 D03 D02 D01 D00 * D07 D06 D05 D04 D07 D06 D05 R04 D07 D06 D05 D04 * D07 D06 D05 D04 D07 D06 D05 D04 * * Which means I did all this work to figure out that: * crc = (crc << 8) ^ crc_tbl[crc >> 8] ^ crc_tbl[data] * or with only one table lookup: * crc = (crc << 8) ^ crc_tbl[(crc >> 8) ^ data] * Note that this formula _only_ applies to the CCITT polynomial! * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ extern __u16 udf_crc(__u16 *data, unsigned count) { register unsigned crc = 0U; while (--count) crc = (crc << 8) ^ crc_tbl[(crc >> 8) ^ *(data++)]; return (__u16)(crc & 0xffffU); } #else /* if defined(GENERATE) */ /* * PURPOSE * Generate the table used to calulate CRC-16 a byte at a time. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ #include int main(void) { unsigned bit, crc, entry; printf("static __u16 crc_tbl = {"); for (entry = 0; entry < 256; entry++) { crc = entry << 8; for (bit = 0; bit < 8; bit++) { crc <<= 1; if (crc & 0x10000) crc ^= 0x11021; } if (entry & 7) printf(", 0x%04xU", crc); else printf("\n\t0x%04xU", crc); } printf("\n};\n"); } #endif /* defined(GENERATE) */