1 #include "lib9.h" 2 #include "logfs.h" 3 #include "nandfs.h" 4 #include "local.h" 5 6 static int 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 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 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 != 0xfffffffff && _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