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