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