1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "nandfs.h"
4 #include "local.h"
5
6 static int
hammingdistance(uchar a,uchar b)7 hammingdistance(uchar a, uchar b)
8 {
9 uchar c;
10 int i, k;
11 if (a == b)
12 return 0;
13 c = a ^ b;
14 for (i = 0x80, k = 0; i; i >>= 1)
15 if (c & i)
16 k++;
17 return k;
18 }
19
20 static int
allones(uchar * data,int len)21 allones(uchar *data, int len)
22 {
23 while (len-- > 0)
24 if (*data++ != 0xff)
25 return 0;
26 return 1;
27 }
28
29 LogfsLowLevelReadResult
_nandfscorrectauxiliary(NandfsAuxiliary * hdr)30 _nandfscorrectauxiliary(NandfsAuxiliary *hdr)
31 {
32 /*
33 * correct single bit errors, detect more than 1, in
34 * tag, signature
35 * TODO: add nerase and path protection
36 */
37 LogfsLowLevelReadResult e;
38 int x;
39 int min, minx;
40
41 e = LogfsLowLevelReadResultOk;
42
43 min = 8;
44 minx = 0;
45 for (x = 0; x < _nandfsvalidtagscount; x++) {
46 int d = hammingdistance(hdr->tag, _nandfsvalidtags[x]);
47 if (d < min) {
48 min = d;
49 minx = x;
50 if (d == 0)
51 break;
52 }
53 }
54 if (min == 1) {
55 hdr->tag = _nandfsvalidtags[minx];
56 e = LogfsLowLevelReadResultSoftError;
57 }
58 else if (min > 1)
59 e = LogfsLowLevelReadResultHardError;
60 else {
61 if (hdr->tag != LogfsTnone) {
62 ulong tmp = getbig4(hdr->parth);
63 if (tmp != 0xffffffff && _nandfshamming31_26correct(&tmp)) {
64 putbig4(hdr->parth, tmp);
65 if (e != LogfsLowLevelReadResultOk)
66 e = LogfsLowLevelReadResultSoftError;
67 }
68 tmp = (getbig2(hdr->nerasemagicmsw) << 16) | getbig2(hdr->nerasemagiclsw);
69 if (tmp != 0xffffffff && _nandfshamming31_26correct(&tmp)) {
70 putbig2(hdr->nerasemagicmsw, tmp >> 16);
71 putbig2(hdr->nerasemagiclsw, tmp);
72 if (e != LogfsLowLevelReadResultOk)
73 e = LogfsLowLevelReadResultSoftError;
74 }
75 }
76 else if (allones((uchar *)hdr, sizeof(*hdr)))
77 e = LogfsLowLevelReadResultAllOnes;
78 }
79
80 return e;
81 }
82