xref: /openbmc/linux/drivers/mtd/nftlmount.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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.40 2004/11/22 14:38:29 kalev 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.40 $";
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 	unsigned int i;
49 
50         /* Assume logical EraseSize == physical erasesize for starting the scan.
51 	   We'll sort it out later if we find a MediaHeader which says otherwise */
52 	/* Actually, we won't.  The new DiskOnChip driver has already scanned
53 	   the MediaHeader and adjusted the virtual erasesize it presents in
54 	   the mtd device accordingly.  We could even get rid of
55 	   nftl->EraseSize if there were any point in doing so. */
56 	nftl->EraseSize = nftl->mbd.mtd->erasesize;
57         nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
58 
59 	nftl->MediaUnit = BLOCK_NIL;
60 	nftl->SpareMediaUnit = BLOCK_NIL;
61 
62 	/* search for a valid boot record */
63 	for (block = 0; block < nftl->nb_blocks; block++) {
64 		int ret;
65 
66 		/* Check for ANAND header first. Then can whinge if it's found but later
67 		   checks fail */
68 		ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
69 		/* We ignore ret in case the ECC of the MediaHeader is invalid
70 		   (which is apparently acceptable) */
71 		if (retlen != SECTORSIZE) {
72 			static int warncount = 5;
73 
74 			if (warncount) {
75 				printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n",
76 				       block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
77 				if (!--warncount)
78 					printk(KERN_WARNING "Further failures for this block will not be printed\n");
79 			}
80 			continue;
81 		}
82 
83 		if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
84 			/* ANAND\0 not found. Continue */
85 #if 0
86 			printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
87 			       block * nftl->EraseSize, nftl->mbd.mtd->index);
88 #endif
89 			continue;
90 		}
91 
92 		/* To be safer with BIOS, also use erase mark as discriminant */
93 		if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
94 				8, &retlen, (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_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
113 				&retlen, buf, (char *)&oob, NULL) < 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 = 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_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
232 						       i + SECTORSIZE, SECTORSIZE, &retlen, buf,
233 						       (char *)&oob, NULL)) < 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 	int i;
272 	size_t retlen;
273 	u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
274 
275 	for (i = 0; i < len; i += SECTORSIZE) {
276 		if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
277 			return -1;
278 		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
279 			return -1;
280 
281 		if (check_oob) {
282 			if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
283 				return -1;
284 		}
285 		address += SECTORSIZE;
286 	}
287 
288 	return 0;
289 }
290 
291 /* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and
292  *              Update NFTL metadata. Each erase operation is checked with check_free_sectors
293  *
294  * Return: 0 when succeed, -1 on error.
295  *
296  *  ToDo: 1. Is it neceressary to check_free_sector after erasing ??
297  */
298 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
299 {
300 	size_t retlen;
301 	unsigned int nb_erases, erase_mark;
302 	struct nftl_uci1 uci;
303 	struct erase_info *instr = &nftl->instr;
304 
305 	/* Read the Unit Control Information #1 for Wear-Leveling */
306 	if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
307 			8, &retlen, (char *)&uci) < 0)
308 		goto default_uci1;
309 
310 	erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
311 	if (erase_mark != ERASE_MARK) {
312 	default_uci1:
313 		uci.EraseMark = cpu_to_le16(ERASE_MARK);
314 		uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
315 		uci.WearInfo = cpu_to_le32(0);
316 	}
317 
318 	memset(instr, 0, sizeof(struct erase_info));
319 
320 	/* XXX: use async erase interface, XXX: test return code */
321 	instr->mtd = nftl->mbd.mtd;
322 	instr->addr = block * nftl->EraseSize;
323 	instr->len = nftl->EraseSize;
324 	MTD_ERASE(nftl->mbd.mtd, instr);
325 
326 	if (instr->state == MTD_ERASE_FAILED) {
327 		printk("Error while formatting block %d\n", block);
328 		goto fail;
329 	}
330 
331 		/* increase and write Wear-Leveling info */
332 		nb_erases = le32_to_cpu(uci.WearInfo);
333 		nb_erases++;
334 
335 		/* wrap (almost impossible with current flashs) or free block */
336 		if (nb_erases == 0)
337 			nb_erases = 1;
338 
339 		/* check the "freeness" of Erase Unit before updating metadata
340 		 * FixMe:  is this check really necessary ? since we have check the
341 		 *         return code after the erase operation. */
342 		if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
343 			goto fail;
344 
345 		uci.WearInfo = le32_to_cpu(nb_erases);
346 		if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
347 				 &retlen, (char *)&uci) < 0)
348 			goto fail;
349 		return 0;
350 fail:
351 	/* could not format, update the bad block table (caller is responsible
352 	   for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
353 	nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr);
354 	return -1;
355 }
356 
357 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
358  *	Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
359  *	was being folded when NFTL was interrupted.
360  *
361  *	The check_free_sectors in this function is neceressary. There is a possible
362  *	situation that after writing the Data area, the Block Control Information is
363  *	not updated according (due to power failure or something) which leaves the block
364  *	in an umconsistent state. So we have to check if a block is really FREE in this
365  *	case. */
366 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
367 {
368 	unsigned int block, i, status;
369 	struct nftl_bci bci;
370 	int sectors_per_block;
371 	size_t retlen;
372 
373 	sectors_per_block = nftl->EraseSize / SECTORSIZE;
374 	block = first_block;
375 	for (;;) {
376 		for (i = 0; i < sectors_per_block; i++) {
377 			if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE,
378 					8, &retlen, (char *)&bci) < 0)
379 				status = SECTOR_IGNORE;
380 			else
381 				status = bci.Status | bci.Status1;
382 
383 			switch(status) {
384 			case SECTOR_FREE:
385 				/* verify that the sector is really free. If not, mark
386 				   as ignore */
387 				if (memcmpb(&bci, 0xff, 8) != 0 ||
388 				    check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
389 						       SECTORSIZE, 0) != 0) {
390 					printk("Incorrect free sector %d in block %d: "
391 					       "marking it as ignored\n",
392 					       i, block);
393 
394 					/* sector not free actually : mark it as SECTOR_IGNORE  */
395 					bci.Status = SECTOR_IGNORE;
396 					bci.Status1 = SECTOR_IGNORE;
397 					MTD_WRITEOOB(nftl->mbd.mtd,
398 						     block * nftl->EraseSize + i * SECTORSIZE,
399 						     8, &retlen, (char *)&bci);
400 				}
401 				break;
402 			default:
403 				break;
404 			}
405 		}
406 
407 		/* proceed to next Erase Unit on the chain */
408 		block = nftl->ReplUnitTable[block];
409 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
410 			printk("incorrect ReplUnitTable[] : %d\n", block);
411 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
412 			break;
413 	}
414 }
415 
416 /* calc_chain_lenght: Walk through a Virtual Unit Chain and estimate chain length */
417 static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
418 {
419 	unsigned int length = 0, block = first_block;
420 
421 	for (;;) {
422 		length++;
423 		/* avoid infinite loops, although this is guaranted not to
424 		   happen because of the previous checks */
425 		if (length >= nftl->nb_blocks) {
426 			printk("nftl: length too long %d !\n", length);
427 			break;
428 		}
429 
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 	return length;
437 }
438 
439 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
440  *	Virtual Unit Chain, i.e. all the units are disconnected.
441  *
442  *	It is not stricly correct to begin from the first block of the chain because
443  *	if we stop the code, we may see again a valid chain if there was a first_block
444  *	flag in a block inside it. But is it really a problem ?
445  *
446  * FixMe: Figure out what the last statesment means. What if power failure when we are
447  *	in the for (;;) loop formatting blocks ??
448  */
449 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
450 {
451 	unsigned int block = first_block, block1;
452 
453 	printk("Formatting chain at block %d\n", first_block);
454 
455 	for (;;) {
456 		block1 = nftl->ReplUnitTable[block];
457 
458 		printk("Formatting block %d\n", block);
459 		if (NFTL_formatblock(nftl, block) < 0) {
460 			/* cannot format !!!! Mark it as Bad Unit */
461 			nftl->ReplUnitTable[block] = BLOCK_RESERVED;
462 		} else {
463 			nftl->ReplUnitTable[block] = BLOCK_FREE;
464 		}
465 
466 		/* goto next block on the chain */
467 		block = block1;
468 
469 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
470 			printk("incorrect ReplUnitTable[] : %d\n", block);
471 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
472 			break;
473 	}
474 }
475 
476 /* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or
477  *	totally free (only 0xff).
478  *
479  * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
480  *	following critia:
481  *	1. */
482 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
483 {
484 	struct nftl_uci1 h1;
485 	unsigned int erase_mark;
486 	size_t retlen;
487 
488 	/* check erase mark. */
489 	if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
490 			&retlen, (char *)&h1) < 0)
491 		return -1;
492 
493 	erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
494 	if (erase_mark != ERASE_MARK) {
495 		/* if no erase mark, the block must be totally free. This is
496 		   possible in two cases : empty filsystem or interrupted erase (very unlikely) */
497 		if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
498 			return -1;
499 
500 		/* free block : write erase mark */
501 		h1.EraseMark = cpu_to_le16(ERASE_MARK);
502 		h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
503 		h1.WearInfo = cpu_to_le32(0);
504 		if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
505 				 &retlen, (char *)&h1) < 0)
506 			return -1;
507 	} else {
508 #if 0
509 		/* if erase mark present, need to skip it when doing check */
510 		for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) {
511 			/* check free sector */
512 			if (check_free_sectors (nftl, block * nftl->EraseSize + i,
513 						SECTORSIZE, 0) != 0)
514 				return -1;
515 
516 			if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i,
517 					16, &retlen, buf) < 0)
518 				return -1;
519 			if (i == SECTORSIZE) {
520 				/* skip erase mark */
521 				if (memcmpb(buf, 0xff, 8))
522 					return -1;
523 			} else {
524 				if (memcmpb(buf, 0xff, 16))
525 					return -1;
526 			}
527 		}
528 #endif
529 	}
530 
531 	return 0;
532 }
533 
534 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
535  *	to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
536  *	is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
537  *	for some reason. A clean up/check of the VUC is neceressary in this case.
538  *
539  * WARNING: return 0 if read error
540  */
541 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
542 {
543 	struct nftl_uci2 uci;
544 	size_t retlen;
545 
546 	if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
547 			8, &retlen, (char *)&uci) < 0)
548 		return 0;
549 
550 	return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
551 }
552 
553 int NFTL_mount(struct NFTLrecord *s)
554 {
555 	int i;
556 	unsigned int first_logical_block, logical_block, rep_block, nb_erases, erase_mark;
557 	unsigned int block, first_block, is_first_block;
558 	int chain_length, do_format_chain;
559 	struct nftl_uci0 h0;
560 	struct nftl_uci1 h1;
561 	size_t retlen;
562 
563 	/* search for NFTL MediaHeader and Spare NFTL Media Header */
564 	if (find_boot_record(s) < 0) {
565 		printk("Could not find valid boot record\n");
566 		return -1;
567 	}
568 
569 	/* init the logical to physical table */
570 	for (i = 0; i < s->nb_blocks; i++) {
571 		s->EUNtable[i] = BLOCK_NIL;
572 	}
573 
574 	/* first pass : explore each block chain */
575 	first_logical_block = 0;
576 	for (first_block = 0; first_block < s->nb_blocks; first_block++) {
577 		/* if the block was not already explored, we can look at it */
578 		if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) {
579 			block = first_block;
580 			chain_length = 0;
581 			do_format_chain = 0;
582 
583 			for (;;) {
584 				/* read the block header. If error, we format the chain */
585 				if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
586 						&retlen, (char *)&h0) < 0 ||
587 				    MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
588 						&retlen, (char *)&h1) < 0) {
589 					s->ReplUnitTable[block] = BLOCK_NIL;
590 					do_format_chain = 1;
591 					break;
592 				}
593 
594 				logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum));
595 				rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum));
596 				nb_erases = le32_to_cpu (h1.WearInfo);
597 				erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
598 
599 				is_first_block = !(logical_block >> 15);
600 				logical_block = logical_block & 0x7fff;
601 
602 				/* invalid/free block test */
603 				if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) {
604 					if (chain_length == 0) {
605 						/* if not currently in a chain, we can handle it safely */
606 						if (check_and_mark_free_block(s, block) < 0) {
607 							/* not really free: format it */
608 							printk("Formatting block %d\n", block);
609 							if (NFTL_formatblock(s, block) < 0) {
610 								/* could not format: reserve the block */
611 								s->ReplUnitTable[block] = BLOCK_RESERVED;
612 							} else {
613 								s->ReplUnitTable[block] = BLOCK_FREE;
614 							}
615 						} else {
616 							/* free block: mark it */
617 							s->ReplUnitTable[block] = BLOCK_FREE;
618 						}
619 						/* directly examine the next block. */
620 						goto examine_ReplUnitTable;
621 					} else {
622 						/* the block was in a chain : this is bad. We
623 						   must format all the chain */
624 						printk("Block %d: free but referenced in chain %d\n",
625 						       block, first_block);
626 						s->ReplUnitTable[block] = BLOCK_NIL;
627 						do_format_chain = 1;
628 						break;
629 					}
630 				}
631 
632 				/* we accept only first blocks here */
633 				if (chain_length == 0) {
634 					/* this block is not the first block in chain :
635 					   ignore it, it will be included in a chain
636 					   later, or marked as not explored */
637 					if (!is_first_block)
638 						goto examine_ReplUnitTable;
639 					first_logical_block = logical_block;
640 				} else {
641 					if (logical_block != first_logical_block) {
642 						printk("Block %d: incorrect logical block: %d expected: %d\n",
643 						       block, logical_block, first_logical_block);
644 						/* the chain is incorrect : we must format it,
645 						   but we need to read it completly */
646 						do_format_chain = 1;
647 					}
648 					if (is_first_block) {
649 						/* we accept that a block is marked as first
650 						   block while being last block in a chain
651 						   only if the chain is being folded */
652 						if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS ||
653 						    rep_block != 0xffff) {
654 							printk("Block %d: incorrectly marked as first block in chain\n",
655 							       block);
656 							/* the chain is incorrect : we must format it,
657 							   but we need to read it completly */
658 							do_format_chain = 1;
659 						} else {
660 							printk("Block %d: folding in progress - ignoring first block flag\n",
661 							       block);
662 						}
663 					}
664 				}
665 				chain_length++;
666 				if (rep_block == 0xffff) {
667 					/* no more blocks after */
668 					s->ReplUnitTable[block] = BLOCK_NIL;
669 					break;
670 				} else if (rep_block >= s->nb_blocks) {
671 					printk("Block %d: referencing invalid block %d\n",
672 					       block, rep_block);
673 					do_format_chain = 1;
674 					s->ReplUnitTable[block] = BLOCK_NIL;
675 					break;
676 				} else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) {
677 					/* same problem as previous 'is_first_block' test:
678 					   we accept that the last block of a chain has
679 					   the first_block flag set if folding is in
680 					   progress. We handle here the case where the
681 					   last block appeared first */
682 					if (s->ReplUnitTable[rep_block] == BLOCK_NIL &&
683 					    s->EUNtable[first_logical_block] == rep_block &&
684 					    get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) {
685 						/* EUNtable[] will be set after */
686 						printk("Block %d: folding in progress - ignoring first block flag\n",
687 						       rep_block);
688 						s->ReplUnitTable[block] = rep_block;
689 						s->EUNtable[first_logical_block] = BLOCK_NIL;
690 					} else {
691 						printk("Block %d: referencing block %d already in another chain\n",
692 						       block, rep_block);
693 						/* XXX: should handle correctly fold in progress chains */
694 						do_format_chain = 1;
695 						s->ReplUnitTable[block] = BLOCK_NIL;
696 					}
697 					break;
698 				} else {
699 					/* this is OK */
700 					s->ReplUnitTable[block] = rep_block;
701 					block = rep_block;
702 				}
703 			}
704 
705 			/* the chain was completely explored. Now we can decide
706 			   what to do with it */
707 			if (do_format_chain) {
708 				/* invalid chain : format it */
709 				format_chain(s, first_block);
710 			} else {
711 				unsigned int first_block1, chain_to_format, chain_length1;
712 				int fold_mark;
713 
714 				/* valid chain : get foldmark */
715 				fold_mark = get_fold_mark(s, first_block);
716 				if (fold_mark == 0) {
717 					/* cannot get foldmark : format the chain */
718 					printk("Could read foldmark at block %d\n", first_block);
719 					format_chain(s, first_block);
720 				} else {
721 					if (fold_mark == FOLD_MARK_IN_PROGRESS)
722 						check_sectors_in_chain(s, first_block);
723 
724 					/* now handle the case where we find two chains at the
725 					   same virtual address : we select the longer one,
726 					   because the shorter one is the one which was being
727 					   folded if the folding was not done in place */
728 					first_block1 = s->EUNtable[first_logical_block];
729 					if (first_block1 != BLOCK_NIL) {
730 						/* XXX: what to do if same length ? */
731 						chain_length1 = calc_chain_length(s, first_block1);
732 						printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
733 						       first_block1, chain_length1, first_block, chain_length);
734 
735 						if (chain_length >= chain_length1) {
736 							chain_to_format = first_block1;
737 							s->EUNtable[first_logical_block] = first_block;
738 						} else {
739 							chain_to_format = first_block;
740 						}
741 						format_chain(s, chain_to_format);
742 					} else {
743 						s->EUNtable[first_logical_block] = first_block;
744 					}
745 				}
746 			}
747 		}
748 	examine_ReplUnitTable:;
749 	}
750 
751 	/* second pass to format unreferenced blocks  and init free block count */
752 	s->numfreeEUNs = 0;
753 	s->LastFreeEUN = le16_to_cpu(s->MediaHdr.FirstPhysicalEUN);
754 
755 	for (block = 0; block < s->nb_blocks; block++) {
756 		if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {
757 			printk("Unreferenced block %d, formatting it\n", block);
758 			if (NFTL_formatblock(s, block) < 0)
759 				s->ReplUnitTable[block] = BLOCK_RESERVED;
760 			else
761 				s->ReplUnitTable[block] = BLOCK_FREE;
762 		}
763 		if (s->ReplUnitTable[block] == BLOCK_FREE) {
764 			s->numfreeEUNs++;
765 			s->LastFreeEUN = block;
766 		}
767 	}
768 
769 	return 0;
770 }
771