1 #include "logfsos.h" 2 #include "logfs.h" 3 #include "nandfs.h" 4 #include "local.h" 5 6 char * 7 nandfsopen(Nandfs *nandfs, long base, long limit, int trace, int xcount, long *xdata) 8 { 9 NandfsBlockData *blockdata = nil; 10 long u; 11 ulong badones, goodones; 12 char *errmsg; 13 long possiblebaseblock, possiblesize; 14 long baseblock, limitblock; 15 int ppb; 16 17 if (trace > 1) 18 print("nandfsopen: base %ld limit %ld ppb %d\n", base, limit, 1 << nandfs->ll.l2pagesperblock); 19 20 if (nandfs->blockdata) 21 return Eperm; 22 23 if (base % nandfs->rawblocksize) 24 return Ebadarg; 25 baseblock = base / nandfs->rawblocksize; 26 27 if (limit == 0) 28 limitblock = nandfs->limitblock; 29 else if (limit % nandfs->rawblocksize) 30 return Ebadarg; 31 else 32 limitblock = limit / nandfs->rawblocksize; 33 34 if (trace > 1) 35 print("nandfsopen: baseblock %ld limitblock %ld\n", baseblock, limitblock); 36 37 possiblebaseblock = 0; 38 possiblesize = 0; 39 40 /* 41 * search for Tboot block which will reveal the parameters 42 */ 43 nandfs->baseblock = 0; 44 45 for (u = baseblock; u < limitblock; u++) { 46 NandfsTags tags; 47 LogfsLowLevelReadResult e; 48 int p; 49 int lim; 50 51 lim = xcount + 3; 52 53 for (p = 0; p < lim; p++) { 54 errmsg = nandfsreadpageauxiliary(nandfs, &tags, u, p, 1, &e); 55 if (errmsg) 56 goto error; 57 if (e != LogfsLowLevelReadResultOk || tags.magic != LogfsMagic || tags.tag != LogfsTboot) 58 break; 59 if (trace > 1) 60 print("block %lud/%d: 0x%.lux\n", u, p, tags.path); 61 switch (p) { 62 case 1: 63 possiblebaseblock = tags.path; 64 break; 65 case 2: 66 possiblesize = tags.path; 67 break; 68 default: 69 xdata[p - 3] = tags.path; 70 break; 71 } 72 } 73 if (p == lim) 74 break; 75 } 76 77 if (u >= limitblock) { 78 errmsg = "no valid boot blocks found"; 79 goto error; 80 } 81 82 if (possiblebaseblock < baseblock 83 || possiblebaseblock >= limitblock 84 || possiblebaseblock + possiblesize > limitblock 85 || possiblesize == 0) { 86 errmsg = "embedded parameters out of range"; 87 goto error; 88 } 89 90 baseblock = possiblebaseblock; 91 limitblock = possiblebaseblock + possiblesize; 92 93 if (trace > 0) { 94 int x; 95 print("nandfs filesystem detected: base %lud limit %lud", 96 baseblock, limitblock); 97 for (x = 0; x < xcount; x++) 98 print(" data%d %ld", x, xdata[x]); 99 print("\n"); 100 } 101 102 blockdata = nandfsrealloc(nil, (limitblock - baseblock) * sizeof(NandfsBlockData)); 103 if (blockdata == nil) { 104 errmsg = Enomem; 105 goto error; 106 } 107 /* 108 * sanity check 109 * check the partition until 10 good blocks have been found 110 * check that bad blocks represent 10% or less 111 */ 112 113 badones = goodones = 0; 114 ppb = 1 << nandfs->ll.l2pagesperblock; 115 for (u = baseblock; u < limitblock; u++) { 116 LogfsLowLevelReadResult firste, laste; 117 NandfsTags firsttags, lasttags; 118 errmsg = nandfsreadpageauxiliary(nandfs, &firsttags, u, 0, 1, &firste); 119 if (errmsg) 120 goto error; 121 errmsg = nandfsreadpageauxiliary(nandfs, &lasttags, u, ppb - 1, 1, &laste); 122 if (errmsg) 123 goto error; 124 if (firste == LogfsLowLevelReadResultBad || laste == LogfsLowLevelReadResultBad) 125 continue; 126 if (firste == LogfsLowLevelReadResultOk && laste == LogfsLowLevelReadResultOk && firsttags.magic == LogfsMagic && 127 lasttags.magic == LogfsMagic) 128 goodones++; 129 else 130 badones++; 131 if (badones == 0 && goodones >= 10) 132 break; 133 } 134 135 if (badones * 10 > goodones) { 136 errmsg = "most likely not a Log Filesystem"; 137 goto error; 138 } 139 140 for (u = baseblock; u < limitblock; u++) { 141 int erased, partial; 142 LogfsLowLevelReadResult firste, laste; 143 NandfsTags firsttags, lasttags, newtags; 144 int markedbad; 145 errmsg = nandfsreadpageauxiliary(nandfs, &firsttags, u, 0, 1, &firste); 146 if (errmsg) 147 goto error; 148 errmsg = nandfsreadpageauxiliary(nandfs, &lasttags, u, ppb - 1, 1, &laste); 149 if (errmsg) 150 goto error; 151 if (trace > 1) 152 print("%lud: ", u); 153 if (firste == LogfsLowLevelReadResultBad || laste == LogfsLowLevelReadResultBad) { 154 if (trace > 1) 155 print("bad\n"); 156 blockdata[u - baseblock].tag = LogfsTbad; 157 continue; 158 } 159 newtags = firsttags; 160 erased = 0; 161 partial = 0; 162 if (firsttags.tag != lasttags.tag) { 163 partial = 1; 164 if (trace > 1) 165 print("partially written\n"); 166 /* 167 * partially written block 168 * if Tboot, then it is either 169 * a failure during logfsformat() - well, we never got started, so give up 170 * a failure during blocktransfer() - erase it as the transfer was not completed 171 * tell the difference by the presence of another block with the same path 172 * if Tnone, then it's a no brainer 173 * if anything else, leave alone 174 */ 175 if (newtags.tag == LogfsTnone) { 176 newtags.tag = LogfsTnone; 177 newtags.path = NandfsPathMask; 178 errmsg = nandfseraseblock(nandfs, u, nil, &markedbad); 179 if (errmsg) 180 goto error; 181 if (markedbad) { 182 blockdata[u - baseblock].tag = LogfsTbad; 183 continue; 184 } 185 /* now erased */ 186 erased = 1; 187 partial = 0; 188 } 189 } 190 if (!erased && !partial && firste == LogfsLowLevelReadResultAllOnes) { 191 if (trace > 1) 192 print("probably erased"); 193 /* 194 * finding erased blocks at this stage is a rare event, so 195 * erase again just in case 196 */ 197 newtags.tag = LogfsTnone; 198 newtags.path = NandfsPathMask; 199 newtags.nerase = 1; // what do I do here? 200 errmsg = nandfseraseblock(nandfs, u, nil, &markedbad); 201 if (errmsg) 202 goto error; 203 if (markedbad) { 204 blockdata[u - baseblock].tag = LogfsTbad; 205 continue; 206 } 207 erased = 1; 208 } 209 if (erased) { 210 newtags.magic = 'V'; 211 errmsg = nandfseraseblock(nandfs, u, nil, &markedbad); 212 if (errmsg) 213 goto error; 214 if (markedbad) { 215 blockdata[u - baseblock].tag = LogfsTbad; 216 continue; 217 } 218 } 219 switch (newtags.tag) { 220 case LogfsTboot: 221 case LogfsTnone: 222 case LogfsTdata: 223 case LogfsTlog: 224 blockdata[u - baseblock].path = newtags.path; 225 blockdata[u - baseblock].tag = newtags.tag; 226 blockdata[u - baseblock].nerase = newtags.nerase; 227 blockdata[u - baseblock].partial = partial; 228 if (trace > 1) 229 print("%s 0x%.8lux %lud\n", 230 logfstagname(blockdata[u - baseblock].tag), 231 blockdata[u - baseblock].path, 232 blockdata[u - baseblock].nerase); 233 continue; 234 } 235 break; 236 } 237 nandfs->ll.blocks = u - baseblock; 238 nandfs->baseblock = baseblock; 239 nandfs->blockdata = nandfsrealloc(nil, nandfs->ll.blocks * sizeof(NandfsBlockData)); 240 if (nandfs->blockdata == nil) { 241 errmsg = Enomem; 242 goto error; 243 } 244 nandfs->trace = trace; 245 memmove(nandfs->blockdata, blockdata, sizeof(*nandfs->blockdata) * nandfs->ll.blocks); 246 nandfsfreemem(blockdata); 247 if (trace > 0) 248 print("nandfsopen: success\n"); 249 return nil; 250 error: 251 nandfsfreemem(blockdata); 252 return errmsg; 253 } 254