1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56#ifndef USE_HOSTCC
57#include <common.h>
58#include <log.h>
59#include <malloc.h>
60#include <ubi_uboot.h>
61#include <dm/devres.h>
62
63#include <linux/bitops.h>
64#else
65#include <errno.h>
66#if defined(__FreeBSD__)
67#include <sys/endian.h>
68#elif defined(__APPLE__)
69#include <machine/endian.h>
70#include <libkern/OSByteOrder.h>
71#else
72#include <endian.h>
73#endif
74#include <stdint.h>
75#include <stdlib.h>
76#include <string.h>
77
78#undef cpu_to_be32
79#if defined(__APPLE__)
80#define cpu_to_be32 OSSwapHostToBigInt32
81#else
82#define cpu_to_be32 htobe32
83#endif
84#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
85#define kmalloc(size, flags) malloc(size)
86#define kzalloc(size, flags) calloc(1, size)
87#define kfree free
88#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
89#endif
90
91#include <asm/byteorder.h>
92#include <linux/bch.h>
93
94#if defined(CONFIG_BCH_CONST_PARAMS)
95#define GF_M(_p) (CONFIG_BCH_CONST_M)
96#define GF_T(_p) (CONFIG_BCH_CONST_T)
97#define GF_N(_p) ((1 << (CONFIG_BCH_CONST_M))-1)
98#else
99#define GF_M(_p) ((_p)->m)
100#define GF_T(_p) ((_p)->t)
101#define GF_N(_p) ((_p)->n)
102#endif
103
104#define BCH_ECC_WORDS(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
105#define BCH_ECC_BYTES(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
106
107#ifndef dbg
108#define dbg(_fmt, args...) do {} while (0)
109#endif
110
111
112
113
114struct gf_poly {
115 unsigned int deg;
116 unsigned int c[0];
117};
118
119
120#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int))
121
122
123struct gf_poly_deg1 {
124 struct gf_poly poly;
125 unsigned int c[2];
126};
127
128#ifdef USE_HOSTCC
129#if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__APPLE__)
130static int fls(int x)
131{
132 int r = 32;
133
134 if (!x)
135 return 0;
136 if (!(x & 0xffff0000u)) {
137 x <<= 16;
138 r -= 16;
139 }
140 if (!(x & 0xff000000u)) {
141 x <<= 8;
142 r -= 8;
143 }
144 if (!(x & 0xf0000000u)) {
145 x <<= 4;
146 r -= 4;
147 }
148 if (!(x & 0xc0000000u)) {
149 x <<= 2;
150 r -= 2;
151 }
152 if (!(x & 0x80000000u)) {
153 x <<= 1;
154 r -= 1;
155 }
156 return r;
157}
158#endif
159#endif
160
161
162
163
164static void encode_bch_unaligned(struct bch_control *bch,
165 const unsigned char *data, unsigned int len,
166 uint32_t *ecc)
167{
168 int i;
169 const uint32_t *p;
170 const int l = BCH_ECC_WORDS(bch)-1;
171
172 while (len--) {
173 p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff);
174
175 for (i = 0; i < l; i++)
176 ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++);
177
178 ecc[l] = (ecc[l] << 8)^(*p);
179 }
180}
181
182
183
184
185static void load_ecc8(struct bch_control *bch, uint32_t *dst,
186 const uint8_t *src)
187{
188 uint8_t pad[4] = {0, 0, 0, 0};
189 unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
190
191 for (i = 0; i < nwords; i++, src += 4)
192 dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3];
193
194 memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords);
195 dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3];
196}
197
198
199
200
201static void store_ecc8(struct bch_control *bch, uint8_t *dst,
202 const uint32_t *src)
203{
204 uint8_t pad[4];
205 unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
206
207 for (i = 0; i < nwords; i++) {
208 *dst++ = (src[i] >> 24);
209 *dst++ = (src[i] >> 16) & 0xff;
210 *dst++ = (src[i] >> 8) & 0xff;
211 *dst++ = (src[i] >> 0) & 0xff;
212 }
213 pad[0] = (src[nwords] >> 24);
214 pad[1] = (src[nwords] >> 16) & 0xff;
215 pad[2] = (src[nwords] >> 8) & 0xff;
216 pad[3] = (src[nwords] >> 0) & 0xff;
217 memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords);
218}
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234void encode_bch(struct bch_control *bch, const uint8_t *data,
235 unsigned int len, uint8_t *ecc)
236{
237 const unsigned int l = BCH_ECC_WORDS(bch)-1;
238 unsigned int i, mlen;
239 unsigned long m;
240 uint32_t w, r[l+1];
241 const uint32_t * const tab0 = bch->mod8_tab;
242 const uint32_t * const tab1 = tab0 + 256*(l+1);
243 const uint32_t * const tab2 = tab1 + 256*(l+1);
244 const uint32_t * const tab3 = tab2 + 256*(l+1);
245 const uint32_t *pdata, *p0, *p1, *p2, *p3;
246
247 if (ecc) {
248
249 load_ecc8(bch, bch->ecc_buf, ecc);
250 } else {
251 memset(bch->ecc_buf, 0, sizeof(r));
252 }
253
254
255 m = ((unsigned long)data) & 3;
256 if (m) {
257 mlen = (len < (4-m)) ? len : 4-m;
258 encode_bch_unaligned(bch, data, mlen, bch->ecc_buf);
259 data += mlen;
260 len -= mlen;
261 }
262
263
264 pdata = (uint32_t *)data;
265 mlen = len/4;
266 data += 4*mlen;
267 len -= 4*mlen;
268 memcpy(r, bch->ecc_buf, sizeof(r));
269
270
271
272
273
274
275
276
277
278
279
280
281 while (mlen--) {
282
283 w = r[0]^cpu_to_be32(*pdata++);
284 p0 = tab0 + (l+1)*((w >> 0) & 0xff);
285 p1 = tab1 + (l+1)*((w >> 8) & 0xff);
286 p2 = tab2 + (l+1)*((w >> 16) & 0xff);
287 p3 = tab3 + (l+1)*((w >> 24) & 0xff);
288
289 for (i = 0; i < l; i++)
290 r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i];
291
292 r[l] = p0[l]^p1[l]^p2[l]^p3[l];
293 }
294 memcpy(bch->ecc_buf, r, sizeof(r));
295
296
297 if (len)
298 encode_bch_unaligned(bch, data, len, bch->ecc_buf);
299
300
301 if (ecc)
302 store_ecc8(bch, ecc, bch->ecc_buf);
303}
304
305static inline int modulo(struct bch_control *bch, unsigned int v)
306{
307 const unsigned int n = GF_N(bch);
308 while (v >= n) {
309 v -= n;
310 v = (v & n) + (v >> GF_M(bch));
311 }
312 return v;
313}
314
315
316
317
318static inline int mod_s(struct bch_control *bch, unsigned int v)
319{
320 const unsigned int n = GF_N(bch);
321 return (v < n) ? v : v-n;
322}
323
324static inline int deg(unsigned int poly)
325{
326
327 return fls(poly)-1;
328}
329
330static inline int parity(unsigned int x)
331{
332
333
334
335
336 x ^= x >> 1;
337 x ^= x >> 2;
338 x = (x & 0x11111111U) * 0x11111111U;
339 return (x >> 28) & 1;
340}
341
342
343
344static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
345 unsigned int b)
346{
347 return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
348 bch->a_log_tab[b])] : 0;
349}
350
351static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a)
352{
353 return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0;
354}
355
356static inline unsigned int gf_div(struct bch_control *bch, unsigned int a,
357 unsigned int b)
358{
359 return a ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
360 GF_N(bch)-bch->a_log_tab[b])] : 0;
361}
362
363static inline unsigned int gf_inv(struct bch_control *bch, unsigned int a)
364{
365 return bch->a_pow_tab[GF_N(bch)-bch->a_log_tab[a]];
366}
367
368static inline unsigned int a_pow(struct bch_control *bch, int i)
369{
370 return bch->a_pow_tab[modulo(bch, i)];
371}
372
373static inline int a_log(struct bch_control *bch, unsigned int x)
374{
375 return bch->a_log_tab[x];
376}
377
378static inline int a_ilog(struct bch_control *bch, unsigned int x)
379{
380 return mod_s(bch, GF_N(bch)-bch->a_log_tab[x]);
381}
382
383
384
385
386static void compute_syndromes(struct bch_control *bch, uint32_t *ecc,
387 unsigned int *syn)
388{
389 int i, j, s;
390 unsigned int m;
391 uint32_t poly;
392 const int t = GF_T(bch);
393
394 s = bch->ecc_bits;
395
396
397 m = ((unsigned int)s) & 31;
398 if (m)
399 ecc[s/32] &= ~((1u << (32-m))-1);
400 memset(syn, 0, 2*t*sizeof(*syn));
401
402
403 do {
404 poly = *ecc++;
405 s -= 32;
406 while (poly) {
407 i = deg(poly);
408 for (j = 0; j < 2*t; j += 2)
409 syn[j] ^= a_pow(bch, (j+1)*(i+s));
410
411 poly ^= (1 << i);
412 }
413 } while (s > 0);
414
415
416 for (j = 0; j < t; j++)
417 syn[2*j+1] = gf_sqr(bch, syn[j]);
418}
419
420static void gf_poly_copy(struct gf_poly *dst, struct gf_poly *src)
421{
422 memcpy(dst, src, GF_POLY_SZ(src->deg));
423}
424
425static int compute_error_locator_polynomial(struct bch_control *bch,
426 const unsigned int *syn)
427{
428 const unsigned int t = GF_T(bch);
429 const unsigned int n = GF_N(bch);
430 unsigned int i, j, tmp, l, pd = 1, d = syn[0];
431 struct gf_poly *elp = bch->elp;
432 struct gf_poly *pelp = bch->poly_2t[0];
433 struct gf_poly *elp_copy = bch->poly_2t[1];
434 int k, pp = -1;
435
436 memset(pelp, 0, GF_POLY_SZ(2*t));
437 memset(elp, 0, GF_POLY_SZ(2*t));
438
439 pelp->deg = 0;
440 pelp->c[0] = 1;
441 elp->deg = 0;
442 elp->c[0] = 1;
443
444
445 for (i = 0; (i < t) && (elp->deg <= t); i++) {
446 if (d) {
447 k = 2*i-pp;
448 gf_poly_copy(elp_copy, elp);
449
450 tmp = a_log(bch, d)+n-a_log(bch, pd);
451 for (j = 0; j <= pelp->deg; j++) {
452 if (pelp->c[j]) {
453 l = a_log(bch, pelp->c[j]);
454 elp->c[j+k] ^= a_pow(bch, tmp+l);
455 }
456 }
457
458 tmp = pelp->deg+k;
459 if (tmp > elp->deg) {
460 elp->deg = tmp;
461 gf_poly_copy(pelp, elp_copy);
462 pd = d;
463 pp = 2*i;
464 }
465 }
466
467 if (i < t-1) {
468 d = syn[2*i+2];
469 for (j = 1; j <= elp->deg; j++)
470 d ^= gf_mul(bch, elp->c[j], syn[2*i+2-j]);
471 }
472 }
473 dbg("elp=%s\n", gf_poly_str(elp));
474 return (elp->deg > t) ? -1 : (int)elp->deg;
475}
476
477
478
479
480
481static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
482 unsigned int *sol, int nsol)
483{
484 const int m = GF_M(bch);
485 unsigned int tmp, mask;
486 int rem, c, r, p, k, param[m];
487
488 k = 0;
489 mask = 1 << m;
490
491
492 for (c = 0; c < m; c++) {
493 rem = 0;
494 p = c-k;
495
496 for (r = p; r < m; r++) {
497 if (rows[r] & mask) {
498 if (r != p) {
499 tmp = rows[r];
500 rows[r] = rows[p];
501 rows[p] = tmp;
502 }
503 rem = r+1;
504 break;
505 }
506 }
507 if (rem) {
508
509 tmp = rows[p];
510 for (r = rem; r < m; r++) {
511 if (rows[r] & mask)
512 rows[r] ^= tmp;
513 }
514 } else {
515
516 param[k++] = c;
517 }
518 mask >>= 1;
519 }
520
521 if (k > 0) {
522 p = k;
523 for (r = m-1; r >= 0; r--) {
524 if ((r > m-1-k) && rows[r])
525
526 return 0;
527
528 rows[r] = (p && (r == param[p-1])) ?
529 p--, 1u << (m-r) : rows[r-p];
530 }
531 }
532
533 if (nsol != (1 << k))
534
535 return 0;
536
537 for (p = 0; p < nsol; p++) {
538
539 for (c = 0; c < k; c++)
540 rows[param[c]] = (rows[param[c]] & ~1)|((p >> c) & 1);
541
542
543 tmp = 0;
544 for (r = m-1; r >= 0; r--) {
545 mask = rows[r] & (tmp|1);
546 tmp |= parity(mask) << (m-r);
547 }
548 sol[p] = tmp >> 1;
549 }
550 return nsol;
551}
552
553
554
555
556
557static int find_affine4_roots(struct bch_control *bch, unsigned int a,
558 unsigned int b, unsigned int c,
559 unsigned int *roots)
560{
561 int i, j, k;
562 const int m = GF_M(bch);
563 unsigned int mask = 0xff, t, rows[16] = {0,};
564
565 j = a_log(bch, b);
566 k = a_log(bch, a);
567 rows[0] = c;
568
569
570 for (i = 0; i < m; i++) {
571 rows[i+1] = bch->a_pow_tab[4*i]^
572 (a ? bch->a_pow_tab[mod_s(bch, k)] : 0)^
573 (b ? bch->a_pow_tab[mod_s(bch, j)] : 0);
574 j++;
575 k += 2;
576 }
577
578
579
580
581 for (j = 8; j != 0; j >>= 1, mask ^= (mask << j)) {
582 for (k = 0; k < 16; k = (k+j+1) & ~j) {
583 t = ((rows[k] >> j)^rows[k+j]) & mask;
584 rows[k] ^= (t << j);
585 rows[k+j] ^= t;
586 }
587 }
588 return solve_linear_system(bch, rows, roots, 4);
589}
590
591
592
593
594static int find_poly_deg1_roots(struct bch_control *bch, struct gf_poly *poly,
595 unsigned int *roots)
596{
597 int n = 0;
598
599 if (poly->c[0])
600
601 roots[n++] = mod_s(bch, GF_N(bch)-bch->a_log_tab[poly->c[0]]+
602 bch->a_log_tab[poly->c[1]]);
603 return n;
604}
605
606
607
608
609static int find_poly_deg2_roots(struct bch_control *bch, struct gf_poly *poly,
610 unsigned int *roots)
611{
612 int n = 0, i, l0, l1, l2;
613 unsigned int u, v, r;
614
615 if (poly->c[0] && poly->c[1]) {
616
617 l0 = bch->a_log_tab[poly->c[0]];
618 l1 = bch->a_log_tab[poly->c[1]];
619 l2 = bch->a_log_tab[poly->c[2]];
620
621
622 u = a_pow(bch, l0+l2+2*(GF_N(bch)-l1));
623
624
625
626
627
628
629 r = 0;
630 v = u;
631 while (v) {
632 i = deg(v);
633 r ^= bch->xi_tab[i];
634 v ^= (1 << i);
635 }
636
637 if ((gf_sqr(bch, r)^r) == u) {
638
639 roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
640 bch->a_log_tab[r]+l2);
641 roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
642 bch->a_log_tab[r^1]+l2);
643 }
644 }
645 return n;
646}
647
648
649
650
651static int find_poly_deg3_roots(struct bch_control *bch, struct gf_poly *poly,
652 unsigned int *roots)
653{
654 int i, n = 0;
655 unsigned int a, b, c, a2, b2, c2, e3, tmp[4];
656
657 if (poly->c[0]) {
658
659 e3 = poly->c[3];
660 c2 = gf_div(bch, poly->c[0], e3);
661 b2 = gf_div(bch, poly->c[1], e3);
662 a2 = gf_div(bch, poly->c[2], e3);
663
664
665 c = gf_mul(bch, a2, c2);
666 b = gf_mul(bch, a2, b2)^c2;
667 a = gf_sqr(bch, a2)^b2;
668
669
670 if (find_affine4_roots(bch, a, b, c, tmp) == 4) {
671
672 for (i = 0; i < 4; i++) {
673 if (tmp[i] != a2)
674 roots[n++] = a_ilog(bch, tmp[i]);
675 }
676 }
677 }
678 return n;
679}
680
681
682
683
684static int find_poly_deg4_roots(struct bch_control *bch, struct gf_poly *poly,
685 unsigned int *roots)
686{
687 int i, l, n = 0;
688 unsigned int a, b, c, d, e = 0, f, a2, b2, c2, e4;
689
690 if (poly->c[0] == 0)
691 return 0;
692
693
694 e4 = poly->c[4];
695 d = gf_div(bch, poly->c[0], e4);
696 c = gf_div(bch, poly->c[1], e4);
697 b = gf_div(bch, poly->c[2], e4);
698 a = gf_div(bch, poly->c[3], e4);
699
700
701 if (a) {
702
703 if (c) {
704
705 f = gf_div(bch, c, a);
706 l = a_log(bch, f);
707 l += (l & 1) ? GF_N(bch) : 0;
708 e = a_pow(bch, l/2);
709
710
711
712
713
714
715
716 d = a_pow(bch, 2*l)^gf_mul(bch, b, f)^d;
717 b = gf_mul(bch, a, e)^b;
718 }
719
720 if (d == 0)
721
722 return 0;
723
724 c2 = gf_inv(bch, d);
725 b2 = gf_div(bch, a, d);
726 a2 = gf_div(bch, b, d);
727 } else {
728
729 c2 = d;
730 b2 = c;
731 a2 = b;
732 }
733
734 if (find_affine4_roots(bch, a2, b2, c2, roots) == 4) {
735 for (i = 0; i < 4; i++) {
736
737 f = a ? gf_inv(bch, roots[i]) : roots[i];
738 roots[i] = a_ilog(bch, f^e);
739 }
740 n = 4;
741 }
742 return n;
743}
744
745
746
747
748static void gf_poly_logrep(struct bch_control *bch,
749 const struct gf_poly *a, int *rep)
750{
751 int i, d = a->deg, l = GF_N(bch)-a_log(bch, a->c[a->deg]);
752
753
754 for (i = 0; i < d; i++)
755 rep[i] = a->c[i] ? mod_s(bch, a_log(bch, a->c[i])+l) : -1;
756}
757
758
759
760
761static void gf_poly_mod(struct bch_control *bch, struct gf_poly *a,
762 const struct gf_poly *b, int *rep)
763{
764 int la, p, m;
765 unsigned int i, j, *c = a->c;
766 const unsigned int d = b->deg;
767
768 if (a->deg < d)
769 return;
770
771
772 if (!rep) {
773 rep = bch->cache;
774 gf_poly_logrep(bch, b, rep);
775 }
776
777 for (j = a->deg; j >= d; j--) {
778 if (c[j]) {
779 la = a_log(bch, c[j]);
780 p = j-d;
781 for (i = 0; i < d; i++, p++) {
782 m = rep[i];
783 if (m >= 0)
784 c[p] ^= bch->a_pow_tab[mod_s(bch,
785 m+la)];
786 }
787 }
788 }
789 a->deg = d-1;
790 while (!c[a->deg] && a->deg)
791 a->deg--;
792}
793
794
795
796
797static void gf_poly_div(struct bch_control *bch, struct gf_poly *a,
798 const struct gf_poly *b, struct gf_poly *q)
799{
800 if (a->deg >= b->deg) {
801 q->deg = a->deg-b->deg;
802
803 gf_poly_mod(bch, a, b, NULL);
804
805 memcpy(q->c, &a->c[b->deg], (1+q->deg)*sizeof(unsigned int));
806 } else {
807 q->deg = 0;
808 q->c[0] = 0;
809 }
810}
811
812
813
814
815static struct gf_poly *gf_poly_gcd(struct bch_control *bch, struct gf_poly *a,
816 struct gf_poly *b)
817{
818 struct gf_poly *tmp;
819
820 dbg("gcd(%s,%s)=", gf_poly_str(a), gf_poly_str(b));
821
822 if (a->deg < b->deg) {
823 tmp = b;
824 b = a;
825 a = tmp;
826 }
827
828 while (b->deg > 0) {
829 gf_poly_mod(bch, a, b, NULL);
830 tmp = b;
831 b = a;
832 a = tmp;
833 }
834
835 dbg("%s\n", gf_poly_str(a));
836
837 return a;
838}
839
840
841
842
843
844static void compute_trace_bk_mod(struct bch_control *bch, int k,
845 const struct gf_poly *f, struct gf_poly *z,
846 struct gf_poly *out)
847{
848 const int m = GF_M(bch);
849 int i, j;
850
851
852 z->deg = 1;
853 z->c[0] = 0;
854 z->c[1] = bch->a_pow_tab[k];
855
856 out->deg = 0;
857 memset(out, 0, GF_POLY_SZ(f->deg));
858
859
860 gf_poly_logrep(bch, f, bch->cache);
861
862 for (i = 0; i < m; i++) {
863
864 for (j = z->deg; j >= 0; j--) {
865 out->c[j] ^= z->c[j];
866 z->c[2*j] = gf_sqr(bch, z->c[j]);
867 z->c[2*j+1] = 0;
868 }
869 if (z->deg > out->deg)
870 out->deg = z->deg;
871
872 if (i < m-1) {
873 z->deg *= 2;
874
875 gf_poly_mod(bch, z, f, bch->cache);
876 }
877 }
878 while (!out->c[out->deg] && out->deg)
879 out->deg--;
880
881 dbg("Tr(a^%d.X) mod f = %s\n", k, gf_poly_str(out));
882}
883
884
885
886
887static void factor_polynomial(struct bch_control *bch, int k, struct gf_poly *f,
888 struct gf_poly **g, struct gf_poly **h)
889{
890 struct gf_poly *f2 = bch->poly_2t[0];
891 struct gf_poly *q = bch->poly_2t[1];
892 struct gf_poly *tk = bch->poly_2t[2];
893 struct gf_poly *z = bch->poly_2t[3];
894 struct gf_poly *gcd;
895
896 dbg("factoring %s...\n", gf_poly_str(f));
897
898 *g = f;
899 *h = NULL;
900
901
902 compute_trace_bk_mod(bch, k, f, z, tk);
903
904 if (tk->deg > 0) {
905
906 gf_poly_copy(f2, f);
907 gcd = gf_poly_gcd(bch, f2, tk);
908 if (gcd->deg < f->deg) {
909
910 gf_poly_div(bch, f, gcd, q);
911
912 *h = &((struct gf_poly_deg1 *)f)[gcd->deg].poly;
913 gf_poly_copy(*g, gcd);
914 gf_poly_copy(*h, q);
915 }
916 }
917}
918
919
920
921
922
923static int find_poly_roots(struct bch_control *bch, unsigned int k,
924 struct gf_poly *poly, unsigned int *roots)
925{
926 int cnt;
927 struct gf_poly *f1, *f2;
928
929 switch (poly->deg) {
930
931 case 1:
932 cnt = find_poly_deg1_roots(bch, poly, roots);
933 break;
934 case 2:
935 cnt = find_poly_deg2_roots(bch, poly, roots);
936 break;
937 case 3:
938 cnt = find_poly_deg3_roots(bch, poly, roots);
939 break;
940 case 4:
941 cnt = find_poly_deg4_roots(bch, poly, roots);
942 break;
943 default:
944
945 cnt = 0;
946 if (poly->deg && (k <= GF_M(bch))) {
947 factor_polynomial(bch, k, poly, &f1, &f2);
948 if (f1)
949 cnt += find_poly_roots(bch, k+1, f1, roots);
950 if (f2)
951 cnt += find_poly_roots(bch, k+1, f2, roots+cnt);
952 }
953 break;
954 }
955 return cnt;
956}
957
958#if defined(USE_CHIEN_SEARCH)
959
960
961
962
963static int chien_search(struct bch_control *bch, unsigned int len,
964 struct gf_poly *p, unsigned int *roots)
965{
966 int m;
967 unsigned int i, j, syn, syn0, count = 0;
968 const unsigned int k = 8*len+bch->ecc_bits;
969
970
971 gf_poly_logrep(bch, p, bch->cache);
972 bch->cache[p->deg] = 0;
973 syn0 = gf_div(bch, p->c[0], p->c[p->deg]);
974
975 for (i = GF_N(bch)-k+1; i <= GF_N(bch); i++) {
976
977 for (j = 1, syn = syn0; j <= p->deg; j++) {
978 m = bch->cache[j];
979 if (m >= 0)
980 syn ^= a_pow(bch, m+j*i);
981 }
982 if (syn == 0) {
983 roots[count++] = GF_N(bch)-i;
984 if (count == p->deg)
985 break;
986 }
987 }
988 return (count == p->deg) ? count : 0;
989}
990#define find_poly_roots(_p, _k, _elp, _loc) chien_search(_p, len, _elp, _loc)
991#endif
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
1036 const uint8_t *recv_ecc, const uint8_t *calc_ecc,
1037 const unsigned int *syn, unsigned int *errloc)
1038{
1039 const unsigned int ecc_words = BCH_ECC_WORDS(bch);
1040 unsigned int nbits;
1041 int i, err, nroots;
1042 uint32_t sum;
1043
1044
1045 if (8*len > (bch->n-bch->ecc_bits))
1046 return -EINVAL;
1047
1048
1049 if (!syn) {
1050 if (!calc_ecc) {
1051
1052 if (!data || !recv_ecc)
1053 return -EINVAL;
1054 encode_bch(bch, data, len, NULL);
1055 } else {
1056
1057 load_ecc8(bch, bch->ecc_buf, calc_ecc);
1058 }
1059
1060 if (recv_ecc) {
1061 load_ecc8(bch, bch->ecc_buf2, recv_ecc);
1062
1063 for (i = 0, sum = 0; i < (int)ecc_words; i++) {
1064 bch->ecc_buf[i] ^= bch->ecc_buf2[i];
1065 sum |= bch->ecc_buf[i];
1066 }
1067 if (!sum)
1068
1069 return 0;
1070 }
1071 compute_syndromes(bch, bch->ecc_buf, bch->syn);
1072 syn = bch->syn;
1073 }
1074
1075 err = compute_error_locator_polynomial(bch, syn);
1076 if (err > 0) {
1077 nroots = find_poly_roots(bch, 1, bch->elp, errloc);
1078 if (err != nroots)
1079 err = -1;
1080 }
1081 if (err > 0) {
1082
1083 nbits = (len*8)+bch->ecc_bits;
1084 for (i = 0; i < err; i++) {
1085 if (errloc[i] >= nbits) {
1086 err = -1;
1087 break;
1088 }
1089 errloc[i] = nbits-1-errloc[i];
1090 errloc[i] = (errloc[i] & ~7)|(7-(errloc[i] & 7));
1091 }
1092 }
1093 return (err >= 0) ? err : -EBADMSG;
1094}
1095
1096
1097
1098
1099static int build_gf_tables(struct bch_control *bch, unsigned int poly)
1100{
1101 unsigned int i, x = 1;
1102 const unsigned int k = 1 << deg(poly);
1103
1104
1105 if (k != (1u << GF_M(bch)))
1106 return -1;
1107
1108 for (i = 0; i < GF_N(bch); i++) {
1109 bch->a_pow_tab[i] = x;
1110 bch->a_log_tab[x] = i;
1111 if (i && (x == 1))
1112
1113 return -1;
1114 x <<= 1;
1115 if (x & k)
1116 x ^= poly;
1117 }
1118 bch->a_pow_tab[GF_N(bch)] = 1;
1119 bch->a_log_tab[0] = 0;
1120
1121 return 0;
1122}
1123
1124
1125
1126
1127static void build_mod8_tables(struct bch_control *bch, const uint32_t *g)
1128{
1129 int i, j, b, d;
1130 uint32_t data, hi, lo, *tab;
1131 const int l = BCH_ECC_WORDS(bch);
1132 const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32);
1133 const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32);
1134
1135 memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab));
1136
1137 for (i = 0; i < 256; i++) {
1138
1139 for (b = 0; b < 4; b++) {
1140
1141 tab = bch->mod8_tab + (b*256+i)*l;
1142 data = i << (8*b);
1143 while (data) {
1144 d = deg(data);
1145
1146 data ^= g[0] >> (31-d);
1147 for (j = 0; j < ecclen; j++) {
1148 hi = (d < 31) ? g[j] << (d+1) : 0;
1149 lo = (j+1 < plen) ?
1150 g[j+1] >> (31-d) : 0;
1151 tab[j] ^= hi|lo;
1152 }
1153 }
1154 }
1155 }
1156}
1157
1158
1159
1160
1161static int build_deg2_base(struct bch_control *bch)
1162{
1163 const int m = GF_M(bch);
1164 int i, j, r;
1165 unsigned int sum, x, y, remaining, ak = 0, xi[m];
1166
1167
1168 for (i = 0; i < m; i++) {
1169 for (j = 0, sum = 0; j < m; j++)
1170 sum ^= a_pow(bch, i*(1 << j));
1171
1172 if (sum) {
1173 ak = bch->a_pow_tab[i];
1174 break;
1175 }
1176 }
1177
1178 remaining = m;
1179 memset(xi, 0, sizeof(xi));
1180
1181 for (x = 0; (x <= GF_N(bch)) && remaining; x++) {
1182 y = gf_sqr(bch, x)^x;
1183 for (i = 0; i < 2; i++) {
1184 r = a_log(bch, y);
1185 if (y && (r < m) && !xi[r]) {
1186 bch->xi_tab[r] = x;
1187 xi[r] = 1;
1188 remaining--;
1189 dbg("x%d = %x\n", r, x);
1190 break;
1191 }
1192 y ^= ak;
1193 }
1194 }
1195
1196 return remaining ? -1 : 0;
1197}
1198
1199static void *bch_alloc(size_t size, int *err)
1200{
1201 void *ptr;
1202
1203 ptr = kmalloc(size, GFP_KERNEL);
1204 if (ptr == NULL)
1205 *err = 1;
1206 return ptr;
1207}
1208
1209
1210
1211
1212static uint32_t *compute_generator_polynomial(struct bch_control *bch)
1213{
1214 const unsigned int m = GF_M(bch);
1215 const unsigned int t = GF_T(bch);
1216 int n, err = 0;
1217 unsigned int i, j, nbits, r, word, *roots;
1218 struct gf_poly *g;
1219 uint32_t *genpoly;
1220
1221 g = bch_alloc(GF_POLY_SZ(m*t), &err);
1222 roots = bch_alloc((bch->n+1)*sizeof(*roots), &err);
1223 genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err);
1224
1225 if (err) {
1226 kfree(genpoly);
1227 genpoly = NULL;
1228 goto finish;
1229 }
1230
1231
1232 memset(roots , 0, (bch->n+1)*sizeof(*roots));
1233 for (i = 0; i < t; i++) {
1234 for (j = 0, r = 2*i+1; j < m; j++) {
1235 roots[r] = 1;
1236 r = mod_s(bch, 2*r);
1237 }
1238 }
1239
1240 g->deg = 0;
1241 g->c[0] = 1;
1242 for (i = 0; i < GF_N(bch); i++) {
1243 if (roots[i]) {
1244
1245 r = bch->a_pow_tab[i];
1246 g->c[g->deg+1] = 1;
1247 for (j = g->deg; j > 0; j--)
1248 g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1];
1249
1250 g->c[0] = gf_mul(bch, g->c[0], r);
1251 g->deg++;
1252 }
1253 }
1254
1255 n = g->deg+1;
1256 i = 0;
1257
1258 while (n > 0) {
1259 nbits = (n > 32) ? 32 : n;
1260 for (j = 0, word = 0; j < nbits; j++) {
1261 if (g->c[n-1-j])
1262 word |= 1u << (31-j);
1263 }
1264 genpoly[i++] = word;
1265 n -= nbits;
1266 }
1267 bch->ecc_bits = g->deg;
1268
1269finish:
1270 kfree(g);
1271 kfree(roots);
1272
1273 return genpoly;
1274}
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
1298{
1299 int err = 0;
1300 unsigned int i, words;
1301 uint32_t *genpoly;
1302 struct bch_control *bch = NULL;
1303
1304 const int min_m = 5;
1305 const int max_m = 15;
1306
1307
1308 static const unsigned int prim_poly_tab[] = {
1309 0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b,
1310 0x402b, 0x8003,
1311 };
1312
1313#if defined(CONFIG_BCH_CONST_PARAMS)
1314 if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) {
1315 printk(KERN_ERR "bch encoder/decoder was configured to support "
1316 "parameters m=%d, t=%d only!\n",
1317 CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T);
1318 goto fail;
1319 }
1320#endif
1321 if ((m < min_m) || (m > max_m))
1322
1323
1324
1325
1326
1327 goto fail;
1328
1329
1330 if ((t < 1) || (m*t >= ((1 << m)-1)))
1331
1332 goto fail;
1333
1334
1335 if (prim_poly == 0)
1336 prim_poly = prim_poly_tab[m-min_m];
1337
1338 bch = kzalloc(sizeof(*bch), GFP_KERNEL);
1339 if (bch == NULL)
1340 goto fail;
1341
1342 bch->m = m;
1343 bch->t = t;
1344 bch->n = (1 << m)-1;
1345 words = DIV_ROUND_UP(m*t, 32);
1346 bch->ecc_bytes = DIV_ROUND_UP(m*t, 8);
1347 bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err);
1348 bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err);
1349 bch->mod8_tab = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err);
1350 bch->ecc_buf = bch_alloc(words*sizeof(*bch->ecc_buf), &err);
1351 bch->ecc_buf2 = bch_alloc(words*sizeof(*bch->ecc_buf2), &err);
1352 bch->xi_tab = bch_alloc(m*sizeof(*bch->xi_tab), &err);
1353 bch->syn = bch_alloc(2*t*sizeof(*bch->syn), &err);
1354 bch->cache = bch_alloc(2*t*sizeof(*bch->cache), &err);
1355 bch->elp = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err);
1356
1357 for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
1358 bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err);
1359
1360 if (err)
1361 goto fail;
1362
1363 err = build_gf_tables(bch, prim_poly);
1364 if (err)
1365 goto fail;
1366
1367
1368 genpoly = compute_generator_polynomial(bch);
1369 if (genpoly == NULL)
1370 goto fail;
1371
1372 build_mod8_tables(bch, genpoly);
1373 kfree(genpoly);
1374
1375 err = build_deg2_base(bch);
1376 if (err)
1377 goto fail;
1378
1379 return bch;
1380
1381fail:
1382 free_bch(bch);
1383 return NULL;
1384}
1385
1386
1387
1388
1389
1390void free_bch(struct bch_control *bch)
1391{
1392 unsigned int i;
1393
1394 if (bch) {
1395 kfree(bch->a_pow_tab);
1396 kfree(bch->a_log_tab);
1397 kfree(bch->mod8_tab);
1398 kfree(bch->ecc_buf);
1399 kfree(bch->ecc_buf2);
1400 kfree(bch->xi_tab);
1401 kfree(bch->syn);
1402 kfree(bch->cache);
1403 kfree(bch->elp);
1404
1405 for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
1406 kfree(bch->poly_2t[i]);
1407
1408 kfree(bch);
1409 }
1410}
1411