xref: /openbmc/linux/drivers/mtd/nftlmount.c (revision 7fe2f639)
1 /*
2  * NFTL mount code with extensive checks
3  *
4  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
5  * Copyright © 2000 Netgem S.A.
6  * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include <linux/kernel.h>
24 #include <asm/errno.h>
25 #include <linux/delay.h>
26 #include <linux/slab.h>
27 #include <linux/mtd/mtd.h>
28 #include <linux/mtd/nand.h>
29 #include <linux/mtd/nftl.h>
30 
31 #define SECTORSIZE 512
32 
33 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
34  *	various device information of the NFTL partition and Bad Unit Table. Update
35  *	the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
36  *	is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
37  */
38 static int find_boot_record(struct NFTLrecord *nftl)
39 {
40 	struct nftl_uci1 h1;
41 	unsigned int block, boot_record_count = 0;
42 	size_t retlen;
43 	u8 buf[SECTORSIZE];
44 	struct NFTLMediaHeader *mh = &nftl->MediaHdr;
45 	struct mtd_info *mtd = nftl->mbd.mtd;
46 	unsigned int i;
47 
48         /* Assume logical EraseSize == physical erasesize for starting the scan.
49 	   We'll sort it out later if we find a MediaHeader which says otherwise */
50 	/* Actually, we won't.  The new DiskOnChip driver has already scanned
51 	   the MediaHeader and adjusted the virtual erasesize it presents in
52 	   the mtd device accordingly.  We could even get rid of
53 	   nftl->EraseSize if there were any point in doing so. */
54 	nftl->EraseSize = nftl->mbd.mtd->erasesize;
55         nftl->nb_blocks = (u32)nftl->mbd.mtd->size / nftl->EraseSize;
56 
57 	nftl->MediaUnit = BLOCK_NIL;
58 	nftl->SpareMediaUnit = BLOCK_NIL;
59 
60 	/* search for a valid boot record */
61 	for (block = 0; block < nftl->nb_blocks; block++) {
62 		int ret;
63 
64 		/* Check for ANAND header first. Then can whinge if it's found but later
65 		   checks fail */
66 		ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE,
67 				&retlen, buf);
68 		/* We ignore ret in case the ECC of the MediaHeader is invalid
69 		   (which is apparently acceptable) */
70 		if (retlen != SECTORSIZE) {
71 			static int warncount = 5;
72 
73 			if (warncount) {
74 				printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n",
75 				       block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
76 				if (!--warncount)
77 					printk(KERN_WARNING "Further failures for this block will not be printed\n");
78 			}
79 			continue;
80 		}
81 
82 		if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
83 			/* ANAND\0 not found. Continue */
84 #if 0
85 			printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
86 			       block * nftl->EraseSize, nftl->mbd.mtd->index);
87 #endif
88 			continue;
89 		}
90 
91 		/* To be safer with BIOS, also use erase mark as discriminant */
92 		if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize +
93 					 SECTORSIZE + 8, 8, &retlen,
94 					 (char *)&h1) < 0)) {
95 			printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n",
96 			       block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
97 			continue;
98 		}
99 
100 #if 0 /* Some people seem to have devices without ECC or erase marks
101 	 on the Media Header blocks. There are enough other sanity
102 	 checks in here that we can probably do without it.
103       */
104 		if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) {
105 			printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n",
106 			       block * nftl->EraseSize, nftl->mbd.mtd->index,
107 			       le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1));
108 			continue;
109 		}
110 
111 		/* Finally reread to check ECC */
112 		if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE,
113 				     &retlen, buf) < 0)) {
114 			printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
115 			       block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
116 			continue;
117 		}
118 
119 		/* Paranoia. Check the ANAND header is still there after the ECC read */
120 		if (memcmp(buf, "ANAND", 6)) {
121 			printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but went away on reread!\n",
122 			       block * nftl->EraseSize, nftl->mbd.mtd->index);
123 			printk(KERN_NOTICE "New data are: %02x %02x %02x %02x %02x %02x\n",
124 			       buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
125 			continue;
126 		}
127 #endif
128 		/* OK, we like it. */
129 
130 		if (boot_record_count) {
131 			/* We've already processed one. So we just check if
132 			   this one is the same as the first one we found */
133 			if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) {
134 				printk(KERN_NOTICE "NFTL Media Headers at 0x%x and 0x%x disagree.\n",
135 				       nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);
136 				/* if (debug) Print both side by side */
137 				if (boot_record_count < 2) {
138 					/* We haven't yet seen two real ones */
139 					return -1;
140 				}
141 				continue;
142 			}
143 			if (boot_record_count == 1)
144 				nftl->SpareMediaUnit = block;
145 
146 			/* Mark this boot record (NFTL MediaHeader) block as reserved */
147 			nftl->ReplUnitTable[block] = BLOCK_RESERVED;
148 
149 
150 			boot_record_count++;
151 			continue;
152 		}
153 
154 		/* This is the first we've seen. Copy the media header structure into place */
155 		memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
156 
157 		/* Do some sanity checks on it */
158 #if 0
159 The new DiskOnChip driver scans the MediaHeader itself, and presents a virtual
160 erasesize based on UnitSizeFactor.  So the erasesize we read from the mtd
161 device is already correct.
162 		if (mh->UnitSizeFactor == 0) {
163 			printk(KERN_NOTICE "NFTL: UnitSizeFactor 0x00 detected. This violates the spec but we think we know what it means...\n");
164 		} else if (mh->UnitSizeFactor < 0xfc) {
165 			printk(KERN_NOTICE "Sorry, we don't support UnitSizeFactor 0x%02x\n",
166 			       mh->UnitSizeFactor);
167 			return -1;
168 		} else if (mh->UnitSizeFactor != 0xff) {
169 			printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n",
170 			       mh->UnitSizeFactor);
171 			nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
172 			nftl->nb_blocks = (u32)nftl->mbd.mtd->size / nftl->EraseSize;
173 		}
174 #endif
175 		nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
176 		if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
177 			printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
178 			printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
179 			       nftl->nb_boot_blocks, nftl->nb_blocks);
180 			return -1;
181 		}
182 
183 		nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;
184 		if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) {
185 			printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
186 			printk(KERN_NOTICE "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n",
187 			       nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks);
188 			return -1;
189 		}
190 
191 		nftl->mbd.size  = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
192 
193 		/* If we're not using the last sectors in the device for some reason,
194 		   reduce nb_blocks accordingly so we forget they're there */
195 		nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);
196 
197 		/* XXX: will be suppressed */
198 		nftl->lastEUN = nftl->nb_blocks - 1;
199 
200 		/* memory alloc */
201 		nftl->EUNtable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
202 		if (!nftl->EUNtable) {
203 			printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n");
204 			return -ENOMEM;
205 		}
206 
207 		nftl->ReplUnitTable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
208 		if (!nftl->ReplUnitTable) {
209 			kfree(nftl->EUNtable);
210 			printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
211 			return -ENOMEM;
212 		}
213 
214 		/* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
215 		for (i = 0; i < nftl->nb_boot_blocks; i++)
216 			nftl->ReplUnitTable[i] = BLOCK_RESERVED;
217 		/* mark all remaining blocks as potentially containing data */
218 		for (; i < nftl->nb_blocks; i++) {
219 			nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
220 		}
221 
222 		/* Mark this boot record (NFTL MediaHeader) block as reserved */
223 		nftl->ReplUnitTable[block] = BLOCK_RESERVED;
224 
225 		/* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
226 		for (i = 0; i < nftl->nb_blocks; i++) {
227 #if 0
228 The new DiskOnChip driver already scanned the bad block table.  Just query it.
229 			if ((i & (SECTORSIZE - 1)) == 0) {
230 				/* read one sector for every SECTORSIZE of blocks */
231 				if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize +
232 						     i + SECTORSIZE, SECTORSIZE, &retlen,
233 						     buf)) < 0) {
234 					printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
235 					       ret);
236 					kfree(nftl->ReplUnitTable);
237 					kfree(nftl->EUNtable);
238 					return -1;
239 				}
240 			}
241 			/* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
242 			if (buf[i & (SECTORSIZE - 1)] != 0xff)
243 				nftl->ReplUnitTable[i] = BLOCK_RESERVED;
244 #endif
245 			if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
246 				nftl->ReplUnitTable[i] = BLOCK_RESERVED;
247 		}
248 
249 		nftl->MediaUnit = block;
250 		boot_record_count++;
251 
252 	} /* foreach (block) */
253 
254 	return boot_record_count?0:-1;
255 }
256 
257 static int memcmpb(void *a, int c, int n)
258 {
259 	int i;
260 	for (i = 0; i < n; i++) {
261 		if (c != ((unsigned char *)a)[i])
262 			return 1;
263 	}
264 	return 0;
265 }
266 
267 /* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */
268 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
269 			      int check_oob)
270 {
271 	u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
272 	struct mtd_info *mtd = nftl->mbd.mtd;
273 	size_t retlen;
274 	int i;
275 
276 	for (i = 0; i < len; i += SECTORSIZE) {
277 		if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
278 			return -1;
279 		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
280 			return -1;
281 
282 		if (check_oob) {
283 			if(nftl_read_oob(mtd, address, mtd->oobsize,
284 					 &retlen, &buf[SECTORSIZE]) < 0)
285 				return -1;
286 			if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
287 				return -1;
288 		}
289 		address += SECTORSIZE;
290 	}
291 
292 	return 0;
293 }
294 
295 /* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and
296  *              Update NFTL metadata. Each erase operation is checked with check_free_sectors
297  *
298  * Return: 0 when succeed, -1 on error.
299  *
300  *  ToDo: 1. Is it neceressary to check_free_sector after erasing ??
301  */
302 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
303 {
304 	size_t retlen;
305 	unsigned int nb_erases, erase_mark;
306 	struct nftl_uci1 uci;
307 	struct erase_info *instr = &nftl->instr;
308 	struct mtd_info *mtd = nftl->mbd.mtd;
309 
310 	/* Read the Unit Control Information #1 for Wear-Leveling */
311 	if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8,
312 			  8, &retlen, (char *)&uci) < 0)
313 		goto default_uci1;
314 
315 	erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
316 	if (erase_mark != ERASE_MARK) {
317 	default_uci1:
318 		uci.EraseMark = cpu_to_le16(ERASE_MARK);
319 		uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
320 		uci.WearInfo = cpu_to_le32(0);
321 	}
322 
323 	memset(instr, 0, sizeof(struct erase_info));
324 
325 	/* XXX: use async erase interface, XXX: test return code */
326 	instr->mtd = nftl->mbd.mtd;
327 	instr->addr = block * nftl->EraseSize;
328 	instr->len = nftl->EraseSize;
329 	mtd->erase(mtd, instr);
330 
331 	if (instr->state == MTD_ERASE_FAILED) {
332 		printk("Error while formatting block %d\n", block);
333 		goto fail;
334 	}
335 
336 		/* increase and write Wear-Leveling info */
337 		nb_erases = le32_to_cpu(uci.WearInfo);
338 		nb_erases++;
339 
340 		/* wrap (almost impossible with current flashs) or free block */
341 		if (nb_erases == 0)
342 			nb_erases = 1;
343 
344 		/* check the "freeness" of Erase Unit before updating metadata
345 		 * FixMe:  is this check really necessary ? since we have check the
346 		 *         return code after the erase operation. */
347 		if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
348 			goto fail;
349 
350 		uci.WearInfo = le32_to_cpu(nb_erases);
351 		if (nftl_write_oob(mtd, block * nftl->EraseSize + SECTORSIZE +
352 				   8, 8, &retlen, (char *)&uci) < 0)
353 			goto fail;
354 		return 0;
355 fail:
356 	/* could not format, update the bad block table (caller is responsible
357 	   for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
358 	nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr);
359 	return -1;
360 }
361 
362 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
363  *	Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
364  *	was being folded when NFTL was interrupted.
365  *
366  *	The check_free_sectors in this function is neceressary. There is a possible
367  *	situation that after writing the Data area, the Block Control Information is
368  *	not updated according (due to power failure or something) which leaves the block
369  *	in an umconsistent state. So we have to check if a block is really FREE in this
370  *	case. */
371 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
372 {
373 	struct mtd_info *mtd = nftl->mbd.mtd;
374 	unsigned int block, i, status;
375 	struct nftl_bci bci;
376 	int sectors_per_block;
377 	size_t retlen;
378 
379 	sectors_per_block = nftl->EraseSize / SECTORSIZE;
380 	block = first_block;
381 	for (;;) {
382 		for (i = 0; i < sectors_per_block; i++) {
383 			if (nftl_read_oob(mtd,
384 					  block * nftl->EraseSize + i * SECTORSIZE,
385 					  8, &retlen, (char *)&bci) < 0)
386 				status = SECTOR_IGNORE;
387 			else
388 				status = bci.Status | bci.Status1;
389 
390 			switch(status) {
391 			case SECTOR_FREE:
392 				/* verify that the sector is really free. If not, mark
393 				   as ignore */
394 				if (memcmpb(&bci, 0xff, 8) != 0 ||
395 				    check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
396 						       SECTORSIZE, 0) != 0) {
397 					printk("Incorrect free sector %d in block %d: "
398 					       "marking it as ignored\n",
399 					       i, block);
400 
401 					/* sector not free actually : mark it as SECTOR_IGNORE  */
402 					bci.Status = SECTOR_IGNORE;
403 					bci.Status1 = SECTOR_IGNORE;
404 					nftl_write_oob(mtd, block *
405 						       nftl->EraseSize +
406 						       i * SECTORSIZE, 8,
407 						       &retlen, (char *)&bci);
408 				}
409 				break;
410 			default:
411 				break;
412 			}
413 		}
414 
415 		/* proceed to next Erase Unit on the chain */
416 		block = nftl->ReplUnitTable[block];
417 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
418 			printk("incorrect ReplUnitTable[] : %d\n", block);
419 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
420 			break;
421 	}
422 }
423 
424 /* calc_chain_length: Walk through a Virtual Unit Chain and estimate chain length */
425 static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
426 {
427 	unsigned int length = 0, block = first_block;
428 
429 	for (;;) {
430 		length++;
431 		/* avoid infinite loops, although this is guaranted not to
432 		   happen because of the previous checks */
433 		if (length >= nftl->nb_blocks) {
434 			printk("nftl: length too long %d !\n", length);
435 			break;
436 		}
437 
438 		block = nftl->ReplUnitTable[block];
439 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
440 			printk("incorrect ReplUnitTable[] : %d\n", block);
441 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
442 			break;
443 	}
444 	return length;
445 }
446 
447 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
448  *	Virtual Unit Chain, i.e. all the units are disconnected.
449  *
450  *	It is not stricly correct to begin from the first block of the chain because
451  *	if we stop the code, we may see again a valid chain if there was a first_block
452  *	flag in a block inside it. But is it really a problem ?
453  *
454  * FixMe: Figure out what the last statesment means. What if power failure when we are
455  *	in the for (;;) loop formatting blocks ??
456  */
457 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
458 {
459 	unsigned int block = first_block, block1;
460 
461 	printk("Formatting chain at block %d\n", first_block);
462 
463 	for (;;) {
464 		block1 = nftl->ReplUnitTable[block];
465 
466 		printk("Formatting block %d\n", block);
467 		if (NFTL_formatblock(nftl, block) < 0) {
468 			/* cannot format !!!! Mark it as Bad Unit */
469 			nftl->ReplUnitTable[block] = BLOCK_RESERVED;
470 		} else {
471 			nftl->ReplUnitTable[block] = BLOCK_FREE;
472 		}
473 
474 		/* goto next block on the chain */
475 		block = block1;
476 
477 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
478 			printk("incorrect ReplUnitTable[] : %d\n", block);
479 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
480 			break;
481 	}
482 }
483 
484 /* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or
485  *	totally free (only 0xff).
486  *
487  * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
488  *	following critia:
489  *	1. */
490 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
491 {
492 	struct mtd_info *mtd = nftl->mbd.mtd;
493 	struct nftl_uci1 h1;
494 	unsigned int erase_mark;
495 	size_t retlen;
496 
497 	/* check erase mark. */
498 	if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
499 			  &retlen, (char *)&h1) < 0)
500 		return -1;
501 
502 	erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
503 	if (erase_mark != ERASE_MARK) {
504 		/* if no erase mark, the block must be totally free. This is
505 		   possible in two cases : empty filsystem or interrupted erase (very unlikely) */
506 		if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
507 			return -1;
508 
509 		/* free block : write erase mark */
510 		h1.EraseMark = cpu_to_le16(ERASE_MARK);
511 		h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
512 		h1.WearInfo = cpu_to_le32(0);
513 		if (nftl_write_oob(mtd,
514 				   block * nftl->EraseSize + SECTORSIZE + 8, 8,
515 				   &retlen, (char *)&h1) < 0)
516 			return -1;
517 	} else {
518 #if 0
519 		/* if erase mark present, need to skip it when doing check */
520 		for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) {
521 			/* check free sector */
522 			if (check_free_sectors (nftl, block * nftl->EraseSize + i,
523 						SECTORSIZE, 0) != 0)
524 				return -1;
525 
526 			if (nftl_read_oob(mtd, block * nftl->EraseSize + i,
527 					  16, &retlen, buf) < 0)
528 				return -1;
529 			if (i == SECTORSIZE) {
530 				/* skip erase mark */
531 				if (memcmpb(buf, 0xff, 8))
532 					return -1;
533 			} else {
534 				if (memcmpb(buf, 0xff, 16))
535 					return -1;
536 			}
537 		}
538 #endif
539 	}
540 
541 	return 0;
542 }
543 
544 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
545  *	to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
546  *	is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
547  *	for some reason. A clean up/check of the VUC is neceressary in this case.
548  *
549  * WARNING: return 0 if read error
550  */
551 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
552 {
553 	struct mtd_info *mtd = nftl->mbd.mtd;
554 	struct nftl_uci2 uci;
555 	size_t retlen;
556 
557 	if (nftl_read_oob(mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
558 			  8, &retlen, (char *)&uci) < 0)
559 		return 0;
560 
561 	return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
562 }
563 
564 int NFTL_mount(struct NFTLrecord *s)
565 {
566 	int i;
567 	unsigned int first_logical_block, logical_block, rep_block, nb_erases, erase_mark;
568 	unsigned int block, first_block, is_first_block;
569 	int chain_length, do_format_chain;
570 	struct nftl_uci0 h0;
571 	struct nftl_uci1 h1;
572 	struct mtd_info *mtd = s->mbd.mtd;
573 	size_t retlen;
574 
575 	/* search for NFTL MediaHeader and Spare NFTL Media Header */
576 	if (find_boot_record(s) < 0) {
577 		printk("Could not find valid boot record\n");
578 		return -1;
579 	}
580 
581 	/* init the logical to physical table */
582 	for (i = 0; i < s->nb_blocks; i++) {
583 		s->EUNtable[i] = BLOCK_NIL;
584 	}
585 
586 	/* first pass : explore each block chain */
587 	first_logical_block = 0;
588 	for (first_block = 0; first_block < s->nb_blocks; first_block++) {
589 		/* if the block was not already explored, we can look at it */
590 		if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) {
591 			block = first_block;
592 			chain_length = 0;
593 			do_format_chain = 0;
594 
595 			for (;;) {
596 				/* read the block header. If error, we format the chain */
597 				if (nftl_read_oob(mtd,
598 						  block * s->EraseSize + 8, 8,
599 						  &retlen, (char *)&h0) < 0 ||
600 				    nftl_read_oob(mtd,
601 						  block * s->EraseSize +
602 						  SECTORSIZE + 8, 8,
603 						  &retlen, (char *)&h1) < 0) {
604 					s->ReplUnitTable[block] = BLOCK_NIL;
605 					do_format_chain = 1;
606 					break;
607 				}
608 
609 				logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum));
610 				rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum));
611 				nb_erases = le32_to_cpu (h1.WearInfo);
612 				erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
613 
614 				is_first_block = !(logical_block >> 15);
615 				logical_block = logical_block & 0x7fff;
616 
617 				/* invalid/free block test */
618 				if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) {
619 					if (chain_length == 0) {
620 						/* if not currently in a chain, we can handle it safely */
621 						if (check_and_mark_free_block(s, block) < 0) {
622 							/* not really free: format it */
623 							printk("Formatting block %d\n", block);
624 							if (NFTL_formatblock(s, block) < 0) {
625 								/* could not format: reserve the block */
626 								s->ReplUnitTable[block] = BLOCK_RESERVED;
627 							} else {
628 								s->ReplUnitTable[block] = BLOCK_FREE;
629 							}
630 						} else {
631 							/* free block: mark it */
632 							s->ReplUnitTable[block] = BLOCK_FREE;
633 						}
634 						/* directly examine the next block. */
635 						goto examine_ReplUnitTable;
636 					} else {
637 						/* the block was in a chain : this is bad. We
638 						   must format all the chain */
639 						printk("Block %d: free but referenced in chain %d\n",
640 						       block, first_block);
641 						s->ReplUnitTable[block] = BLOCK_NIL;
642 						do_format_chain = 1;
643 						break;
644 					}
645 				}
646 
647 				/* we accept only first blocks here */
648 				if (chain_length == 0) {
649 					/* this block is not the first block in chain :
650 					   ignore it, it will be included in a chain
651 					   later, or marked as not explored */
652 					if (!is_first_block)
653 						goto examine_ReplUnitTable;
654 					first_logical_block = logical_block;
655 				} else {
656 					if (logical_block != first_logical_block) {
657 						printk("Block %d: incorrect logical block: %d expected: %d\n",
658 						       block, logical_block, first_logical_block);
659 						/* the chain is incorrect : we must format it,
660 						   but we need to read it completly */
661 						do_format_chain = 1;
662 					}
663 					if (is_first_block) {
664 						/* we accept that a block is marked as first
665 						   block while being last block in a chain
666 						   only if the chain is being folded */
667 						if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS ||
668 						    rep_block != 0xffff) {
669 							printk("Block %d: incorrectly marked as first block in chain\n",
670 							       block);
671 							/* the chain is incorrect : we must format it,
672 							   but we need to read it completly */
673 							do_format_chain = 1;
674 						} else {
675 							printk("Block %d: folding in progress - ignoring first block flag\n",
676 							       block);
677 						}
678 					}
679 				}
680 				chain_length++;
681 				if (rep_block == 0xffff) {
682 					/* no more blocks after */
683 					s->ReplUnitTable[block] = BLOCK_NIL;
684 					break;
685 				} else if (rep_block >= s->nb_blocks) {
686 					printk("Block %d: referencing invalid block %d\n",
687 					       block, rep_block);
688 					do_format_chain = 1;
689 					s->ReplUnitTable[block] = BLOCK_NIL;
690 					break;
691 				} else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) {
692 					/* same problem as previous 'is_first_block' test:
693 					   we accept that the last block of a chain has
694 					   the first_block flag set if folding is in
695 					   progress. We handle here the case where the
696 					   last block appeared first */
697 					if (s->ReplUnitTable[rep_block] == BLOCK_NIL &&
698 					    s->EUNtable[first_logical_block] == rep_block &&
699 					    get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) {
700 						/* EUNtable[] will be set after */
701 						printk("Block %d: folding in progress - ignoring first block flag\n",
702 						       rep_block);
703 						s->ReplUnitTable[block] = rep_block;
704 						s->EUNtable[first_logical_block] = BLOCK_NIL;
705 					} else {
706 						printk("Block %d: referencing block %d already in another chain\n",
707 						       block, rep_block);
708 						/* XXX: should handle correctly fold in progress chains */
709 						do_format_chain = 1;
710 						s->ReplUnitTable[block] = BLOCK_NIL;
711 					}
712 					break;
713 				} else {
714 					/* this is OK */
715 					s->ReplUnitTable[block] = rep_block;
716 					block = rep_block;
717 				}
718 			}
719 
720 			/* the chain was completely explored. Now we can decide
721 			   what to do with it */
722 			if (do_format_chain) {
723 				/* invalid chain : format it */
724 				format_chain(s, first_block);
725 			} else {
726 				unsigned int first_block1, chain_to_format, chain_length1;
727 				int fold_mark;
728 
729 				/* valid chain : get foldmark */
730 				fold_mark = get_fold_mark(s, first_block);
731 				if (fold_mark == 0) {
732 					/* cannot get foldmark : format the chain */
733 					printk("Could read foldmark at block %d\n", first_block);
734 					format_chain(s, first_block);
735 				} else {
736 					if (fold_mark == FOLD_MARK_IN_PROGRESS)
737 						check_sectors_in_chain(s, first_block);
738 
739 					/* now handle the case where we find two chains at the
740 					   same virtual address : we select the longer one,
741 					   because the shorter one is the one which was being
742 					   folded if the folding was not done in place */
743 					first_block1 = s->EUNtable[first_logical_block];
744 					if (first_block1 != BLOCK_NIL) {
745 						/* XXX: what to do if same length ? */
746 						chain_length1 = calc_chain_length(s, first_block1);
747 						printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
748 						       first_block1, chain_length1, first_block, chain_length);
749 
750 						if (chain_length >= chain_length1) {
751 							chain_to_format = first_block1;
752 							s->EUNtable[first_logical_block] = first_block;
753 						} else {
754 							chain_to_format = first_block;
755 						}
756 						format_chain(s, chain_to_format);
757 					} else {
758 						s->EUNtable[first_logical_block] = first_block;
759 					}
760 				}
761 			}
762 		}
763 	examine_ReplUnitTable:;
764 	}
765 
766 	/* second pass to format unreferenced blocks  and init free block count */
767 	s->numfreeEUNs = 0;
768 	s->LastFreeEUN = le16_to_cpu(s->MediaHdr.FirstPhysicalEUN);
769 
770 	for (block = 0; block < s->nb_blocks; block++) {
771 		if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {
772 			printk("Unreferenced block %d, formatting it\n", block);
773 			if (NFTL_formatblock(s, block) < 0)
774 				s->ReplUnitTable[block] = BLOCK_RESERVED;
775 			else
776 				s->ReplUnitTable[block] = BLOCK_FREE;
777 		}
778 		if (s->ReplUnitTable[block] == BLOCK_FREE) {
779 			s->numfreeEUNs++;
780 			s->LastFreeEUN = block;
781 		}
782 	}
783 
784 	return 0;
785 }
786