xref: /inferno-os/libnandfs/correctauxilliary.c (revision 5d0c4cf3fc288434c41cba52dd998ab1d7375a7b)
1  #include "logfsos.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 != 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