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