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