cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

decode_rs.c (8219B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Generic Reed Solomon encoder / decoder library
      4 *
      5 * Copyright 2002, Phil Karn, KA9Q
      6 * May be used under the terms of the GNU General Public License (GPL)
      7 *
      8 * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
      9 *
     10 * Generic data width independent code which is included by the wrappers.
     11 */
     12{
     13	struct rs_codec *rs = rsc->codec;
     14	int deg_lambda, el, deg_omega;
     15	int i, j, r, k, pad;
     16	int nn = rs->nn;
     17	int nroots = rs->nroots;
     18	int fcr = rs->fcr;
     19	int prim = rs->prim;
     20	int iprim = rs->iprim;
     21	uint16_t *alpha_to = rs->alpha_to;
     22	uint16_t *index_of = rs->index_of;
     23	uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error;
     24	int count = 0;
     25	int num_corrected;
     26	uint16_t msk = (uint16_t) rs->nn;
     27
     28	/*
     29	 * The decoder buffers are in the rs control struct. They are
     30	 * arrays sized [nroots + 1]
     31	 */
     32	uint16_t *lambda = rsc->buffers + RS_DECODE_LAMBDA * (nroots + 1);
     33	uint16_t *syn = rsc->buffers + RS_DECODE_SYN * (nroots + 1);
     34	uint16_t *b = rsc->buffers + RS_DECODE_B * (nroots + 1);
     35	uint16_t *t = rsc->buffers + RS_DECODE_T * (nroots + 1);
     36	uint16_t *omega = rsc->buffers + RS_DECODE_OMEGA * (nroots + 1);
     37	uint16_t *root = rsc->buffers + RS_DECODE_ROOT * (nroots + 1);
     38	uint16_t *reg = rsc->buffers + RS_DECODE_REG * (nroots + 1);
     39	uint16_t *loc = rsc->buffers + RS_DECODE_LOC * (nroots + 1);
     40
     41	/* Check length parameter for validity */
     42	pad = nn - nroots - len;
     43	BUG_ON(pad < 0 || pad >= nn - nroots);
     44
     45	/* Does the caller provide the syndrome ? */
     46	if (s != NULL) {
     47		for (i = 0; i < nroots; i++) {
     48			/* The syndrome is in index form,
     49			 * so nn represents zero
     50			 */
     51			if (s[i] != nn)
     52				goto decode;
     53		}
     54
     55		/* syndrome is zero, no errors to correct  */
     56		return 0;
     57	}
     58
     59	/* form the syndromes; i.e., evaluate data(x) at roots of
     60	 * g(x) */
     61	for (i = 0; i < nroots; i++)
     62		syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk;
     63
     64	for (j = 1; j < len; j++) {
     65		for (i = 0; i < nroots; i++) {
     66			if (syn[i] == 0) {
     67				syn[i] = (((uint16_t) data[j]) ^
     68					  invmsk) & msk;
     69			} else {
     70				syn[i] = ((((uint16_t) data[j]) ^
     71					   invmsk) & msk) ^
     72					alpha_to[rs_modnn(rs, index_of[syn[i]] +
     73						       (fcr + i) * prim)];
     74			}
     75		}
     76	}
     77
     78	for (j = 0; j < nroots; j++) {
     79		for (i = 0; i < nroots; i++) {
     80			if (syn[i] == 0) {
     81				syn[i] = ((uint16_t) par[j]) & msk;
     82			} else {
     83				syn[i] = (((uint16_t) par[j]) & msk) ^
     84					alpha_to[rs_modnn(rs, index_of[syn[i]] +
     85						       (fcr+i)*prim)];
     86			}
     87		}
     88	}
     89	s = syn;
     90
     91	/* Convert syndromes to index form, checking for nonzero condition */
     92	syn_error = 0;
     93	for (i = 0; i < nroots; i++) {
     94		syn_error |= s[i];
     95		s[i] = index_of[s[i]];
     96	}
     97
     98	if (!syn_error) {
     99		/* if syndrome is zero, data[] is a codeword and there are no
    100		 * errors to correct. So return data[] unmodified
    101		 */
    102		return 0;
    103	}
    104
    105 decode:
    106	memset(&lambda[1], 0, nroots * sizeof(lambda[0]));
    107	lambda[0] = 1;
    108
    109	if (no_eras > 0) {
    110		/* Init lambda to be the erasure locator polynomial */
    111		lambda[1] = alpha_to[rs_modnn(rs,
    112					prim * (nn - 1 - (eras_pos[0] + pad)))];
    113		for (i = 1; i < no_eras; i++) {
    114			u = rs_modnn(rs, prim * (nn - 1 - (eras_pos[i] + pad)));
    115			for (j = i + 1; j > 0; j--) {
    116				tmp = index_of[lambda[j - 1]];
    117				if (tmp != nn) {
    118					lambda[j] ^=
    119						alpha_to[rs_modnn(rs, u + tmp)];
    120				}
    121			}
    122		}
    123	}
    124
    125	for (i = 0; i < nroots + 1; i++)
    126		b[i] = index_of[lambda[i]];
    127
    128	/*
    129	 * Begin Berlekamp-Massey algorithm to determine error+erasure
    130	 * locator polynomial
    131	 */
    132	r = no_eras;
    133	el = no_eras;
    134	while (++r <= nroots) {	/* r is the step number */
    135		/* Compute discrepancy at the r-th step in poly-form */
    136		discr_r = 0;
    137		for (i = 0; i < r; i++) {
    138			if ((lambda[i] != 0) && (s[r - i - 1] != nn)) {
    139				discr_r ^=
    140					alpha_to[rs_modnn(rs,
    141							  index_of[lambda[i]] +
    142							  s[r - i - 1])];
    143			}
    144		}
    145		discr_r = index_of[discr_r];	/* Index form */
    146		if (discr_r == nn) {
    147			/* 2 lines below: B(x) <-- x*B(x) */
    148			memmove (&b[1], b, nroots * sizeof (b[0]));
    149			b[0] = nn;
    150		} else {
    151			/* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */
    152			t[0] = lambda[0];
    153			for (i = 0; i < nroots; i++) {
    154				if (b[i] != nn) {
    155					t[i + 1] = lambda[i + 1] ^
    156						alpha_to[rs_modnn(rs, discr_r +
    157								  b[i])];
    158				} else
    159					t[i + 1] = lambda[i + 1];
    160			}
    161			if (2 * el <= r + no_eras - 1) {
    162				el = r + no_eras - el;
    163				/*
    164				 * 2 lines below: B(x) <-- inv(discr_r) *
    165				 * lambda(x)
    166				 */
    167				for (i = 0; i <= nroots; i++) {
    168					b[i] = (lambda[i] == 0) ? nn :
    169						rs_modnn(rs, index_of[lambda[i]]
    170							 - discr_r + nn);
    171				}
    172			} else {
    173				/* 2 lines below: B(x) <-- x*B(x) */
    174				memmove(&b[1], b, nroots * sizeof(b[0]));
    175				b[0] = nn;
    176			}
    177			memcpy(lambda, t, (nroots + 1) * sizeof(t[0]));
    178		}
    179	}
    180
    181	/* Convert lambda to index form and compute deg(lambda(x)) */
    182	deg_lambda = 0;
    183	for (i = 0; i < nroots + 1; i++) {
    184		lambda[i] = index_of[lambda[i]];
    185		if (lambda[i] != nn)
    186			deg_lambda = i;
    187	}
    188
    189	if (deg_lambda == 0) {
    190		/*
    191		 * deg(lambda) is zero even though the syndrome is non-zero
    192		 * => uncorrectable error detected
    193		 */
    194		return -EBADMSG;
    195	}
    196
    197	/* Find roots of error+erasure locator polynomial by Chien search */
    198	memcpy(&reg[1], &lambda[1], nroots * sizeof(reg[0]));
    199	count = 0;		/* Number of roots of lambda(x) */
    200	for (i = 1, k = iprim - 1; i <= nn; i++, k = rs_modnn(rs, k + iprim)) {
    201		q = 1;		/* lambda[0] is always 0 */
    202		for (j = deg_lambda; j > 0; j--) {
    203			if (reg[j] != nn) {
    204				reg[j] = rs_modnn(rs, reg[j] + j);
    205				q ^= alpha_to[reg[j]];
    206			}
    207		}
    208		if (q != 0)
    209			continue;	/* Not a root */
    210
    211		if (k < pad) {
    212			/* Impossible error location. Uncorrectable error. */
    213			return -EBADMSG;
    214		}
    215
    216		/* store root (index-form) and error location number */
    217		root[count] = i;
    218		loc[count] = k;
    219		/* If we've already found max possible roots,
    220		 * abort the search to save time
    221		 */
    222		if (++count == deg_lambda)
    223			break;
    224	}
    225	if (deg_lambda != count) {
    226		/*
    227		 * deg(lambda) unequal to number of roots => uncorrectable
    228		 * error detected
    229		 */
    230		return -EBADMSG;
    231	}
    232	/*
    233	 * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
    234	 * x**nroots). in index form. Also find deg(omega).
    235	 */
    236	deg_omega = deg_lambda - 1;
    237	for (i = 0; i <= deg_omega; i++) {
    238		tmp = 0;
    239		for (j = i; j >= 0; j--) {
    240			if ((s[i - j] != nn) && (lambda[j] != nn))
    241				tmp ^=
    242				    alpha_to[rs_modnn(rs, s[i - j] + lambda[j])];
    243		}
    244		omega[i] = index_of[tmp];
    245	}
    246
    247	/*
    248	 * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
    249	 * inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form
    250	 * Note: we reuse the buffer for b to store the correction pattern
    251	 */
    252	num_corrected = 0;
    253	for (j = count - 1; j >= 0; j--) {
    254		num1 = 0;
    255		for (i = deg_omega; i >= 0; i--) {
    256			if (omega[i] != nn)
    257				num1 ^= alpha_to[rs_modnn(rs, omega[i] +
    258							i * root[j])];
    259		}
    260
    261		if (num1 == 0) {
    262			/* Nothing to correct at this position */
    263			b[j] = 0;
    264			continue;
    265		}
    266
    267		num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)];
    268		den = 0;
    269
    270		/* lambda[i+1] for i even is the formal derivative
    271		 * lambda_pr of lambda[i] */
    272		for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) {
    273			if (lambda[i + 1] != nn) {
    274				den ^= alpha_to[rs_modnn(rs, lambda[i + 1] +
    275						       i * root[j])];
    276			}
    277		}
    278
    279		b[j] = alpha_to[rs_modnn(rs, index_of[num1] +
    280					       index_of[num2] +
    281					       nn - index_of[den])];
    282		num_corrected++;
    283	}
    284
    285	/*
    286	 * We compute the syndrome of the 'error' and check that it matches
    287	 * the syndrome of the received word
    288	 */
    289	for (i = 0; i < nroots; i++) {
    290		tmp = 0;
    291		for (j = 0; j < count; j++) {
    292			if (b[j] == 0)
    293				continue;
    294
    295			k = (fcr + i) * prim * (nn-loc[j]-1);
    296			tmp ^= alpha_to[rs_modnn(rs, index_of[b[j]] + k)];
    297		}
    298
    299		if (tmp != alpha_to[s[i]])
    300			return -EBADMSG;
    301	}
    302
    303	/*
    304	 * Store the error correction pattern, if a
    305	 * correction buffer is available
    306	 */
    307	if (corr && eras_pos) {
    308		j = 0;
    309		for (i = 0; i < count; i++) {
    310			if (b[i]) {
    311				corr[j] = b[i];
    312				eras_pos[j++] = loc[i] - pad;
    313			}
    314		}
    315	} else if (data && par) {
    316		/* Apply error to data and parity */
    317		for (i = 0; i < count; i++) {
    318			if (loc[i] < (nn - nroots))
    319				data[loc[i] - pad] ^= b[i];
    320			else
    321				par[loc[i] - pad - len] ^= b[i];
    322		}
    323	}
    324
    325	return  num_corrected;
    326}