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