1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "nandfs.h"
437da2899SCharles.Forsyth #include "local.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth char *
nandfsopen(Nandfs * nandfs,long base,long limit,int trace,int xcount,long * xdata)737da2899SCharles.Forsyth nandfsopen(Nandfs *nandfs, long base, long limit, int trace, int xcount, long *xdata)
837da2899SCharles.Forsyth {
937da2899SCharles.Forsyth NandfsBlockData *blockdata = nil;
1037da2899SCharles.Forsyth long u;
1137da2899SCharles.Forsyth ulong badones, goodones;
1237da2899SCharles.Forsyth char *errmsg;
1337da2899SCharles.Forsyth long possiblebaseblock, possiblesize;
1437da2899SCharles.Forsyth long baseblock, limitblock;
1537da2899SCharles.Forsyth int ppb;
1637da2899SCharles.Forsyth
1737da2899SCharles.Forsyth if (trace > 1)
1837da2899SCharles.Forsyth print("nandfsopen: base %ld limit %ld ppb %d\n", base, limit, 1 << nandfs->ll.l2pagesperblock);
1937da2899SCharles.Forsyth
2037da2899SCharles.Forsyth if (nandfs->blockdata)
2137da2899SCharles.Forsyth return Eperm;
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsyth if (base % nandfs->rawblocksize)
2437da2899SCharles.Forsyth return Ebadarg;
2537da2899SCharles.Forsyth baseblock = base / nandfs->rawblocksize;
2637da2899SCharles.Forsyth
2737da2899SCharles.Forsyth if (limit == 0)
2837da2899SCharles.Forsyth limitblock = nandfs->limitblock;
2937da2899SCharles.Forsyth else if (limit % nandfs->rawblocksize)
3037da2899SCharles.Forsyth return Ebadarg;
3137da2899SCharles.Forsyth else
3237da2899SCharles.Forsyth limitblock = limit / nandfs->rawblocksize;
3337da2899SCharles.Forsyth
3437da2899SCharles.Forsyth if (trace > 1)
3537da2899SCharles.Forsyth print("nandfsopen: baseblock %ld limitblock %ld\n", baseblock, limitblock);
3637da2899SCharles.Forsyth
3737da2899SCharles.Forsyth possiblebaseblock = 0;
3837da2899SCharles.Forsyth possiblesize = 0;
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth /*
4137da2899SCharles.Forsyth * search for Tboot block which will reveal the parameters
4237da2899SCharles.Forsyth */
4337da2899SCharles.Forsyth nandfs->baseblock = 0;
4437da2899SCharles.Forsyth
4537da2899SCharles.Forsyth for (u = baseblock; u < limitblock; u++) {
4637da2899SCharles.Forsyth NandfsTags tags;
4737da2899SCharles.Forsyth LogfsLowLevelReadResult e;
4837da2899SCharles.Forsyth int p;
4937da2899SCharles.Forsyth int lim;
5037da2899SCharles.Forsyth
5137da2899SCharles.Forsyth lim = xcount + 3;
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsyth for (p = 0; p < lim; p++) {
5437da2899SCharles.Forsyth errmsg = nandfsreadpageauxiliary(nandfs, &tags, u, p, 1, &e);
5537da2899SCharles.Forsyth if (errmsg)
5637da2899SCharles.Forsyth goto error;
5737da2899SCharles.Forsyth if (e != LogfsLowLevelReadResultOk || tags.magic != LogfsMagic || tags.tag != LogfsTboot)
5837da2899SCharles.Forsyth break;
5937da2899SCharles.Forsyth if (trace > 1)
6037da2899SCharles.Forsyth print("block %lud/%d: 0x%.lux\n", u, p, tags.path);
6137da2899SCharles.Forsyth switch (p) {
6237da2899SCharles.Forsyth case 1:
6337da2899SCharles.Forsyth possiblebaseblock = tags.path;
6437da2899SCharles.Forsyth break;
6537da2899SCharles.Forsyth case 2:
6637da2899SCharles.Forsyth possiblesize = tags.path;
6737da2899SCharles.Forsyth break;
6837da2899SCharles.Forsyth default:
6937da2899SCharles.Forsyth xdata[p - 3] = tags.path;
7037da2899SCharles.Forsyth break;
7137da2899SCharles.Forsyth }
7237da2899SCharles.Forsyth }
7337da2899SCharles.Forsyth if (p == lim)
7437da2899SCharles.Forsyth break;
7537da2899SCharles.Forsyth }
7637da2899SCharles.Forsyth
7737da2899SCharles.Forsyth if (u >= limitblock) {
7837da2899SCharles.Forsyth errmsg = "no valid boot blocks found";
7937da2899SCharles.Forsyth goto error;
8037da2899SCharles.Forsyth }
8137da2899SCharles.Forsyth
8237da2899SCharles.Forsyth if (possiblebaseblock < baseblock
8337da2899SCharles.Forsyth || possiblebaseblock >= limitblock
8437da2899SCharles.Forsyth || possiblebaseblock + possiblesize > limitblock
8537da2899SCharles.Forsyth || possiblesize == 0) {
8637da2899SCharles.Forsyth errmsg = "embedded parameters out of range";
8737da2899SCharles.Forsyth goto error;
8837da2899SCharles.Forsyth }
8937da2899SCharles.Forsyth
9037da2899SCharles.Forsyth baseblock = possiblebaseblock;
9137da2899SCharles.Forsyth limitblock = possiblebaseblock + possiblesize;
9237da2899SCharles.Forsyth
9337da2899SCharles.Forsyth if (trace > 0) {
9437da2899SCharles.Forsyth int x;
9537da2899SCharles.Forsyth print("nandfs filesystem detected: base %lud limit %lud",
9637da2899SCharles.Forsyth baseblock, limitblock);
9737da2899SCharles.Forsyth for (x = 0; x < xcount; x++)
9837da2899SCharles.Forsyth print(" data%d %ld", x, xdata[x]);
9937da2899SCharles.Forsyth print("\n");
10037da2899SCharles.Forsyth }
10137da2899SCharles.Forsyth
10237da2899SCharles.Forsyth blockdata = nandfsrealloc(nil, (limitblock - baseblock) * sizeof(NandfsBlockData));
10337da2899SCharles.Forsyth if (blockdata == nil) {
10437da2899SCharles.Forsyth errmsg = Enomem;
10537da2899SCharles.Forsyth goto error;
10637da2899SCharles.Forsyth }
10737da2899SCharles.Forsyth /*
10837da2899SCharles.Forsyth * sanity check
10937da2899SCharles.Forsyth * check the partition until 10 good blocks have been found
11037da2899SCharles.Forsyth * check that bad blocks represent 10% or less
11137da2899SCharles.Forsyth */
11237da2899SCharles.Forsyth
11337da2899SCharles.Forsyth badones = goodones = 0;
11437da2899SCharles.Forsyth ppb = 1 << nandfs->ll.l2pagesperblock;
11537da2899SCharles.Forsyth for (u = baseblock; u < limitblock; u++) {
11637da2899SCharles.Forsyth LogfsLowLevelReadResult firste, laste;
11737da2899SCharles.Forsyth NandfsTags firsttags, lasttags;
11837da2899SCharles.Forsyth errmsg = nandfsreadpageauxiliary(nandfs, &firsttags, u, 0, 1, &firste);
11937da2899SCharles.Forsyth if (errmsg)
12037da2899SCharles.Forsyth goto error;
12137da2899SCharles.Forsyth errmsg = nandfsreadpageauxiliary(nandfs, &lasttags, u, ppb - 1, 1, &laste);
12237da2899SCharles.Forsyth if (errmsg)
12337da2899SCharles.Forsyth goto error;
12437da2899SCharles.Forsyth if (firste == LogfsLowLevelReadResultBad || laste == LogfsLowLevelReadResultBad)
12537da2899SCharles.Forsyth continue;
12637da2899SCharles.Forsyth if (firste == LogfsLowLevelReadResultOk && laste == LogfsLowLevelReadResultOk && firsttags.magic == LogfsMagic &&
12737da2899SCharles.Forsyth lasttags.magic == LogfsMagic)
12837da2899SCharles.Forsyth goodones++;
12937da2899SCharles.Forsyth else
13037da2899SCharles.Forsyth badones++;
13137da2899SCharles.Forsyth if (badones == 0 && goodones >= 10)
13237da2899SCharles.Forsyth break;
13337da2899SCharles.Forsyth }
13437da2899SCharles.Forsyth
13537da2899SCharles.Forsyth if (badones * 10 > goodones) {
13637da2899SCharles.Forsyth errmsg = "most likely not a Log Filesystem";
13737da2899SCharles.Forsyth goto error;
13837da2899SCharles.Forsyth }
13937da2899SCharles.Forsyth
14037da2899SCharles.Forsyth for (u = baseblock; u < limitblock; u++) {
14137da2899SCharles.Forsyth int erased, partial;
14237da2899SCharles.Forsyth LogfsLowLevelReadResult firste, laste;
14337da2899SCharles.Forsyth NandfsTags firsttags, lasttags, newtags;
14437da2899SCharles.Forsyth int markedbad;
14537da2899SCharles.Forsyth errmsg = nandfsreadpageauxiliary(nandfs, &firsttags, u, 0, 1, &firste);
14637da2899SCharles.Forsyth if (errmsg)
14737da2899SCharles.Forsyth goto error;
14837da2899SCharles.Forsyth errmsg = nandfsreadpageauxiliary(nandfs, &lasttags, u, ppb - 1, 1, &laste);
14937da2899SCharles.Forsyth if (errmsg)
15037da2899SCharles.Forsyth goto error;
15137da2899SCharles.Forsyth if (trace > 1)
15237da2899SCharles.Forsyth print("%lud: ", u);
15337da2899SCharles.Forsyth if (firste == LogfsLowLevelReadResultBad || laste == LogfsLowLevelReadResultBad) {
15437da2899SCharles.Forsyth if (trace > 1)
15537da2899SCharles.Forsyth print("bad\n");
15637da2899SCharles.Forsyth blockdata[u - baseblock].tag = LogfsTbad;
15737da2899SCharles.Forsyth continue;
15837da2899SCharles.Forsyth }
15937da2899SCharles.Forsyth newtags = firsttags;
16037da2899SCharles.Forsyth erased = 0;
16137da2899SCharles.Forsyth partial = 0;
16237da2899SCharles.Forsyth if (firsttags.tag != lasttags.tag) {
16337da2899SCharles.Forsyth partial = 1;
16437da2899SCharles.Forsyth if (trace > 1)
16537da2899SCharles.Forsyth print("partially written\n");
16637da2899SCharles.Forsyth /*
16737da2899SCharles.Forsyth * partially written block
16837da2899SCharles.Forsyth * if Tboot, then it is either
16937da2899SCharles.Forsyth * a failure during logfsformat() - well, we never got started, so give up
17037da2899SCharles.Forsyth * a failure during blocktransfer() - erase it as the transfer was not completed
17137da2899SCharles.Forsyth * tell the difference by the presence of another block with the same path
17237da2899SCharles.Forsyth * if Tnone, then it's a no brainer
17337da2899SCharles.Forsyth * if anything else, leave alone
17437da2899SCharles.Forsyth */
17537da2899SCharles.Forsyth if (newtags.tag == LogfsTnone) {
17637da2899SCharles.Forsyth newtags.tag = LogfsTnone;
17737da2899SCharles.Forsyth newtags.path = NandfsPathMask;
17837da2899SCharles.Forsyth errmsg = nandfseraseblock(nandfs, u, nil, &markedbad);
17937da2899SCharles.Forsyth if (errmsg)
18037da2899SCharles.Forsyth goto error;
18137da2899SCharles.Forsyth if (markedbad) {
18237da2899SCharles.Forsyth blockdata[u - baseblock].tag = LogfsTbad;
18337da2899SCharles.Forsyth continue;
18437da2899SCharles.Forsyth }
18537da2899SCharles.Forsyth /* now erased */
18637da2899SCharles.Forsyth erased = 1;
18737da2899SCharles.Forsyth partial = 0;
18837da2899SCharles.Forsyth }
18937da2899SCharles.Forsyth }
19037da2899SCharles.Forsyth if (!erased && !partial && firste == LogfsLowLevelReadResultAllOnes) {
19137da2899SCharles.Forsyth if (trace > 1)
19237da2899SCharles.Forsyth print("probably erased");
19337da2899SCharles.Forsyth /*
19437da2899SCharles.Forsyth * finding erased blocks at this stage is a rare event, so
19537da2899SCharles.Forsyth * erase again just in case
19637da2899SCharles.Forsyth */
19737da2899SCharles.Forsyth newtags.tag = LogfsTnone;
19837da2899SCharles.Forsyth newtags.path = NandfsPathMask;
19937da2899SCharles.Forsyth newtags.nerase = 1; // what do I do here?
20037da2899SCharles.Forsyth errmsg = nandfseraseblock(nandfs, u, nil, &markedbad);
20137da2899SCharles.Forsyth if (errmsg)
20237da2899SCharles.Forsyth goto error;
20337da2899SCharles.Forsyth if (markedbad) {
20437da2899SCharles.Forsyth blockdata[u - baseblock].tag = LogfsTbad;
20537da2899SCharles.Forsyth continue;
20637da2899SCharles.Forsyth }
20737da2899SCharles.Forsyth erased = 1;
20837da2899SCharles.Forsyth }
20937da2899SCharles.Forsyth if (erased) {
21037da2899SCharles.Forsyth newtags.magic = 'V';
21137da2899SCharles.Forsyth errmsg = nandfseraseblock(nandfs, u, nil, &markedbad);
21237da2899SCharles.Forsyth if (errmsg)
21337da2899SCharles.Forsyth goto error;
21437da2899SCharles.Forsyth if (markedbad) {
21537da2899SCharles.Forsyth blockdata[u - baseblock].tag = LogfsTbad;
21637da2899SCharles.Forsyth continue;
21737da2899SCharles.Forsyth }
21837da2899SCharles.Forsyth }
21937da2899SCharles.Forsyth switch (newtags.tag) {
22037da2899SCharles.Forsyth case LogfsTboot:
22137da2899SCharles.Forsyth case LogfsTnone:
22237da2899SCharles.Forsyth case LogfsTdata:
22337da2899SCharles.Forsyth case LogfsTlog:
22437da2899SCharles.Forsyth blockdata[u - baseblock].path = newtags.path;
22537da2899SCharles.Forsyth blockdata[u - baseblock].tag = newtags.tag;
22637da2899SCharles.Forsyth blockdata[u - baseblock].nerase = newtags.nerase;
22737da2899SCharles.Forsyth blockdata[u - baseblock].partial = partial;
22837da2899SCharles.Forsyth if (trace > 1)
22937da2899SCharles.Forsyth print("%s 0x%.8lux %lud\n",
23037da2899SCharles.Forsyth logfstagname(blockdata[u - baseblock].tag),
23137da2899SCharles.Forsyth blockdata[u - baseblock].path,
23237da2899SCharles.Forsyth blockdata[u - baseblock].nerase);
23337da2899SCharles.Forsyth continue;
23437da2899SCharles.Forsyth }
23537da2899SCharles.Forsyth break;
23637da2899SCharles.Forsyth }
23737da2899SCharles.Forsyth nandfs->ll.blocks = u - baseblock;
23837da2899SCharles.Forsyth nandfs->baseblock = baseblock;
23937da2899SCharles.Forsyth nandfs->blockdata = nandfsrealloc(nil, nandfs->ll.blocks * sizeof(NandfsBlockData));
24037da2899SCharles.Forsyth if (nandfs->blockdata == nil) {
24137da2899SCharles.Forsyth errmsg = Enomem;
24237da2899SCharles.Forsyth goto error;
24337da2899SCharles.Forsyth }
24437da2899SCharles.Forsyth nandfs->trace = trace;
24537da2899SCharles.Forsyth memmove(nandfs->blockdata, blockdata, sizeof(*nandfs->blockdata) * nandfs->ll.blocks);
24637da2899SCharles.Forsyth nandfsfreemem(blockdata);
24737da2899SCharles.Forsyth if (trace > 0)
24837da2899SCharles.Forsyth print("nandfsopen: success\n");
24937da2899SCharles.Forsyth return nil;
25037da2899SCharles.Forsyth error:
25137da2899SCharles.Forsyth nandfsfreemem(blockdata);
25237da2899SCharles.Forsyth return errmsg;
25337da2899SCharles.Forsyth }
254