1 1.2 andvar /* $NetBSD: hamming.c,v 1.2 2021/12/07 21:37:37 andvar Exp $ */ 2 1.1 ahoka 3 1.1 ahoka /* 4 1.1 ahoka * Copyright (c) 2008, Atmel Corporation 5 1.1 ahoka * 6 1.1 ahoka * All rights reserved. 7 1.1 ahoka * 8 1.1 ahoka * Redistribution and use in source and binary forms, with or without 9 1.1 ahoka * modification, are permitted provided that the following conditions are met: 10 1.1 ahoka * 11 1.1 ahoka * - Redistributions of source code must retain the above copyright notice, 12 1.1 ahoka * this list of conditions and the disclaimer below. 13 1.1 ahoka * 14 1.1 ahoka * Atmel's name may not be used to endorse or promote products derived from 15 1.1 ahoka * this software without specific prior written permission. 16 1.1 ahoka * 17 1.1 ahoka * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR 18 1.1 ahoka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 1.1 ahoka * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 20 1.1 ahoka * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.1 ahoka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 1.1 ahoka * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 23 1.1 ahoka * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 1.1 ahoka * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 1.1 ahoka * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 1.1 ahoka * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 ahoka */ 28 1.1 ahoka 29 1.1 ahoka #include <sys/cdefs.h> 30 1.2 andvar __KERNEL_RCSID(0, "$NetBSD: hamming.c,v 1.2 2021/12/07 21:37:37 andvar Exp $"); 31 1.1 ahoka 32 1.1 ahoka #include <sys/param.h> 33 1.1 ahoka #include <lib/libkern/libkern.h> 34 1.1 ahoka #include "hamming.h" 35 1.1 ahoka 36 1.1 ahoka /** 37 1.1 ahoka * Calculates the 22-bit hamming code for a 256-bytes block of data. 38 1.1 ahoka * \param data Data buffer to calculate code for. 39 1.1 ahoka * \param code Pointer to a buffer where the code should be stored. 40 1.1 ahoka */ 41 1.1 ahoka void 42 1.1 ahoka hamming_compute_256(const uint8_t *data, uint8_t *code) 43 1.1 ahoka { 44 1.1 ahoka unsigned int i; 45 1.1 ahoka uint8_t column_sum = 0; 46 1.1 ahoka uint8_t even_line_code = 0; 47 1.1 ahoka uint8_t odd_line_code = 0; 48 1.1 ahoka uint8_t even_column_code = 0; 49 1.1 ahoka uint8_t odd_column_code = 0; 50 1.1 ahoka 51 1.1 ahoka /*- 52 1.1 ahoka * Xor all bytes together to get the column sum; 53 1.1 ahoka * At the same time, calculate the even and odd line codes 54 1.1 ahoka */ 55 1.1 ahoka for (i = 0; i < 256; i++) { 56 1.1 ahoka column_sum ^= data[i]; 57 1.1 ahoka 58 1.1 ahoka /*- 59 1.1 ahoka * If the xor sum of the byte is 0, then this byte has no 60 1.1 ahoka * incidence on the computed code; so check if the sum is 1. 61 1.1 ahoka */ 62 1.1 ahoka if ((popcount(data[i]) & 1) == 1) { 63 1.1 ahoka /*- 64 1.1 ahoka * Parity groups are formed by forcing a particular 65 1.1 ahoka * index bit to 0 (even) or 1 (odd). 66 1.1 ahoka * Example on one byte: 67 1.1 ahoka * 68 1.1 ahoka * bits (dec) 7 6 5 4 3 2 1 0 69 1.1 ahoka * (bin) 111 110 101 100 011 010 001 000 70 1.1 ahoka * '---'---'---'----------. 71 1.1 ahoka * | 72 1.1 ahoka * groups P4' ooooooooooooooo eeeeeeeeeeeeeee P4 | 73 1.1 ahoka * P2' ooooooo eeeeeee ooooooo eeeeeee P2 | 74 1.1 ahoka * P1' ooo eee ooo eee ooo eee ooo eee P1 | 75 1.1 ahoka * | 76 1.1 ahoka * We can see that: | 77 1.1 ahoka * - P4 -> bit 2 of index is 0 --------------------' 78 1.1 ahoka * - P4' -> bit 2 of index is 1. 79 1.1 ahoka * - P2 -> bit 1 of index if 0. 80 1.1 ahoka * - etc... 81 1.1 ahoka * We deduce that a bit position has an impact on all 82 1.1 ahoka * even Px if the log2(x)nth bit of its index is 0 83 1.1 ahoka * ex: log2(4) = 2, 84 1.1 ahoka * bit2 of the index must be 0 (-> 0 1 2 3) 85 1.1 ahoka * and on all odd Px' if the log2(x)nth bit 86 1.1 ahoka * of its index is 1 87 1.1 ahoka * ex: log2(2) = 1, 88 1.1 ahoka * bit1 of the index must be 1 (-> 0 1 4 5) 89 1.1 ahoka * 90 1.1 ahoka * As such, we calculate all the possible Px and Px' 91 1.1 ahoka * values at the same time in two variables, 92 1.1 ahoka * even_line_code and odd_line_code, such as 93 1.1 ahoka * even_line_code bits: P128 P64 P32 94 1.1 ahoka * P16 P8 P4 P2 P1 95 1.1 ahoka * odd_line_code bits: P128' P64' P32' P16' 96 1.1 ahoka * P8' P4' P2' P1' 97 1.1 ahoka */ 98 1.1 ahoka even_line_code ^= (255 - i); 99 1.1 ahoka odd_line_code ^= i; 100 1.1 ahoka } 101 1.1 ahoka } 102 1.1 ahoka 103 1.1 ahoka /*- 104 1.1 ahoka * At this point, we have the line parities, and the column sum. 105 1.2 andvar * First, We must calculate the parity group values on the column sum. 106 1.1 ahoka */ 107 1.1 ahoka for (i = 0; i < 8; i++) { 108 1.1 ahoka if (column_sum & 1) { 109 1.1 ahoka even_column_code ^= (7 - i); 110 1.1 ahoka odd_column_code ^= i; 111 1.1 ahoka } 112 1.1 ahoka column_sum >>= 1; 113 1.1 ahoka } 114 1.1 ahoka 115 1.1 ahoka /*- 116 1.1 ahoka * Now, we must interleave the parity values, 117 1.1 ahoka * to obtain the following layout: 118 1.1 ahoka * Code[0] = Line1 119 1.1 ahoka * Code[1] = Line2 120 1.1 ahoka * Code[2] = Column 121 1.1 ahoka * Line = Px' Px P(x-1)- P(x-1) ... 122 1.1 ahoka * Column = P4' P4 P2' P2 P1' P1 PadBit PadBit 123 1.1 ahoka */ 124 1.1 ahoka code[0] = 0; 125 1.1 ahoka code[1] = 0; 126 1.1 ahoka code[2] = 0; 127 1.1 ahoka 128 1.1 ahoka for (i = 0; i < 4; i++) { 129 1.1 ahoka code[0] <<= 2; 130 1.1 ahoka code[1] <<= 2; 131 1.1 ahoka code[2] <<= 2; 132 1.1 ahoka 133 1.1 ahoka /* Line 1 */ 134 1.1 ahoka if ((odd_line_code & 0x80) != 0) { 135 1.1 ahoka 136 1.1 ahoka code[0] |= 2; 137 1.1 ahoka } 138 1.1 ahoka if ((even_line_code & 0x80) != 0) { 139 1.1 ahoka 140 1.1 ahoka code[0] |= 1; 141 1.1 ahoka } 142 1.1 ahoka 143 1.1 ahoka /* Line 2 */ 144 1.1 ahoka if ((odd_line_code & 0x08) != 0) { 145 1.1 ahoka 146 1.1 ahoka code[1] |= 2; 147 1.1 ahoka } 148 1.1 ahoka if ((even_line_code & 0x08) != 0) { 149 1.1 ahoka 150 1.1 ahoka code[1] |= 1; 151 1.1 ahoka } 152 1.1 ahoka 153 1.1 ahoka /* Column */ 154 1.1 ahoka if ((odd_column_code & 0x04) != 0) { 155 1.1 ahoka 156 1.1 ahoka code[2] |= 2; 157 1.1 ahoka } 158 1.1 ahoka if ((even_column_code & 0x04) != 0) { 159 1.1 ahoka 160 1.1 ahoka code[2] |= 1; 161 1.1 ahoka } 162 1.1 ahoka 163 1.1 ahoka odd_line_code <<= 1; 164 1.1 ahoka even_line_code <<= 1; 165 1.1 ahoka odd_column_code <<= 1; 166 1.1 ahoka even_column_code <<= 1; 167 1.1 ahoka } 168 1.1 ahoka 169 1.1 ahoka /* Invert codes (linux compatibility) */ 170 1.1 ahoka code[0] = ~code[0]; 171 1.1 ahoka code[1] = ~code[1]; 172 1.1 ahoka code[2] = ~code[2]; 173 1.1 ahoka } 174 1.1 ahoka 175 1.1 ahoka /** 176 1.1 ahoka * Verifies and corrects a 256-bytes block of data using the given 22-bits 177 1.1 ahoka * hamming code. 178 1.1 ahoka * Returns 0 if there is no error, otherwise returns a HAMMING_ERROR code. 179 1.1 ahoka * param data Data buffer to check. 180 1.1 ahoka * \param original_code Hamming code to use for verifying the data. 181 1.1 ahoka */ 182 1.1 ahoka uint8_t 183 1.1 ahoka hamming_correct_256(uint8_t *data, const uint8_t *original_code, 184 1.1 ahoka const uint8_t *computed_code) 185 1.1 ahoka { 186 1.1 ahoka /* Calculate new code */ 187 1.1 ahoka /* we allocate 4 bytes so we can use popcount32 in one step */ 188 1.1 ahoka uint8_t correction_code[4]; 189 1.1 ahoka 190 1.1 ahoka /* this byte should remain zero all the time */ 191 1.1 ahoka correction_code[3] = 0; 192 1.1 ahoka 193 1.1 ahoka /* Xor both codes together */ 194 1.1 ahoka correction_code[0] = computed_code[0] ^ original_code[0]; 195 1.1 ahoka correction_code[1] = computed_code[1] ^ original_code[1]; 196 1.1 ahoka correction_code[2] = computed_code[2] ^ original_code[2]; 197 1.1 ahoka 198 1.1 ahoka /* If all bytes are 0, there is no error */ 199 1.1 ahoka if (*(uint32_t *)correction_code == 0) { 200 1.1 ahoka return 0; 201 1.1 ahoka } 202 1.1 ahoka /* If there is a single bit error, there are 11 bits set to 1 */ 203 1.1 ahoka if (popcount32(*(uint32_t *)correction_code) == 11) { 204 1.1 ahoka /* Get byte and bit indexes */ 205 1.1 ahoka uint8_t byte = correction_code[0] & 0x80; 206 1.1 ahoka byte |= (correction_code[0] << 1) & 0x40; 207 1.1 ahoka byte |= (correction_code[0] << 2) & 0x20; 208 1.1 ahoka byte |= (correction_code[0] << 3) & 0x10; 209 1.1 ahoka 210 1.1 ahoka byte |= (correction_code[1] >> 4) & 0x08; 211 1.1 ahoka byte |= (correction_code[1] >> 3) & 0x04; 212 1.1 ahoka byte |= (correction_code[1] >> 2) & 0x02; 213 1.1 ahoka byte |= (correction_code[1] >> 1) & 0x01; 214 1.1 ahoka 215 1.1 ahoka uint8_t bit = (correction_code[2] >> 5) & 0x04; 216 1.1 ahoka bit |= (correction_code[2] >> 4) & 0x02; 217 1.1 ahoka bit |= (correction_code[2] >> 3) & 0x01; 218 1.1 ahoka 219 1.1 ahoka /* Correct bit */ 220 1.1 ahoka data[byte] ^= (1 << bit); 221 1.1 ahoka 222 1.1 ahoka return HAMMING_ERROR_SINGLEBIT; 223 1.1 ahoka } 224 1.1 ahoka /* Check if ECC has been corrupted */ 225 1.1 ahoka if (popcount32(*(uint32_t *)correction_code) == 1) { 226 1.1 ahoka return HAMMING_ERROR_ECC; 227 1.1 ahoka } else { 228 1.1 ahoka /* Otherwise, this is a multi-bit error */ 229 1.1 ahoka return HAMMING_ERROR_MULTIPLEBITS; 230 1.1 ahoka } 231 1.1 ahoka } 232 1.1 ahoka 233