xref: /openbmc/linux/drivers/mtd/nftlmount.c (revision 965f22bc)
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 		if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
361 			goto fail;
362 
363 		uci.WearInfo = le32_to_cpu(nb_erases);
364 		if (nftl_write_oob(mtd, block * nftl->EraseSize + SECTORSIZE +
365 				   8, 8, &retlen, (char *)&uci) < 0)
366 			goto fail;
367 		return 0;
368 fail:
369 	/* could not format, update the bad block table (caller is responsible
370 	   for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
371 	mtd_block_markbad(nftl->mbd.mtd, instr->addr);
372 	return -1;
373 }
374 
375 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
376  *	Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
377  *	was being folded when NFTL was interrupted.
378  *
379  *	The check_free_sectors in this function is necessary. There is a possible
380  *	situation that after writing the Data area, the Block Control Information is
381  *	not updated according (due to power failure or something) which leaves the block
382  *	in an inconsistent state. So we have to check if a block is really FREE in this
383  *	case. */
384 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
385 {
386 	struct mtd_info *mtd = nftl->mbd.mtd;
387 	unsigned int block, i, status;
388 	struct nftl_bci bci;
389 	int sectors_per_block;
390 	size_t retlen;
391 
392 	sectors_per_block = nftl->EraseSize / SECTORSIZE;
393 	block = first_block;
394 	for (;;) {
395 		for (i = 0; i < sectors_per_block; i++) {
396 			if (nftl_read_oob(mtd,
397 					  block * nftl->EraseSize + i * SECTORSIZE,
398 					  8, &retlen, (char *)&bci) < 0)
399 				status = SECTOR_IGNORE;
400 			else
401 				status = bci.Status | bci.Status1;
402 
403 			switch(status) {
404 			case SECTOR_FREE:
405 				/* verify that the sector is really free. If not, mark
406 				   as ignore */
407 				if (memcmpb(&bci, 0xff, 8) != 0 ||
408 				    check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
409 						       SECTORSIZE, 0) != 0) {
410 					printk("Incorrect free sector %d in block %d: "
411 					       "marking it as ignored\n",
412 					       i, block);
413 
414 					/* sector not free actually : mark it as SECTOR_IGNORE  */
415 					bci.Status = SECTOR_IGNORE;
416 					bci.Status1 = SECTOR_IGNORE;
417 					nftl_write_oob(mtd, block *
418 						       nftl->EraseSize +
419 						       i * SECTORSIZE, 8,
420 						       &retlen, (char *)&bci);
421 				}
422 				break;
423 			default:
424 				break;
425 			}
426 		}
427 
428 		/* proceed to next Erase Unit on the chain */
429 		block = nftl->ReplUnitTable[block];
430 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
431 			printk("incorrect ReplUnitTable[] : %d\n", block);
432 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
433 			break;
434 	}
435 }
436 
437 /* calc_chain_length: Walk through a Virtual Unit Chain and estimate chain length */
438 static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
439 {
440 	unsigned int length = 0, block = first_block;
441 
442 	for (;;) {
443 		length++;
444 		/* avoid infinite loops, although this is guaranteed not to
445 		   happen because of the previous checks */
446 		if (length >= nftl->nb_blocks) {
447 			printk("nftl: length too long %d !\n", length);
448 			break;
449 		}
450 
451 		block = nftl->ReplUnitTable[block];
452 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
453 			printk("incorrect ReplUnitTable[] : %d\n", block);
454 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
455 			break;
456 	}
457 	return length;
458 }
459 
460 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
461  *	Virtual Unit Chain, i.e. all the units are disconnected.
462  *
463  *	It is not strictly correct to begin from the first block of the chain because
464  *	if we stop the code, we may see again a valid chain if there was a first_block
465  *	flag in a block inside it. But is it really a problem ?
466  *
467  * FixMe: Figure out what the last statement means. What if power failure when we are
468  *	in the for (;;) loop formatting blocks ??
469  */
470 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
471 {
472 	unsigned int block = first_block, block1;
473 
474 	printk("Formatting chain at block %d\n", first_block);
475 
476 	for (;;) {
477 		block1 = nftl->ReplUnitTable[block];
478 
479 		printk("Formatting block %d\n", block);
480 		if (NFTL_formatblock(nftl, block) < 0) {
481 			/* cannot format !!!! Mark it as Bad Unit */
482 			nftl->ReplUnitTable[block] = BLOCK_RESERVED;
483 		} else {
484 			nftl->ReplUnitTable[block] = BLOCK_FREE;
485 		}
486 
487 		/* goto next block on the chain */
488 		block = block1;
489 
490 		if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
491 			printk("incorrect ReplUnitTable[] : %d\n", block);
492 		if (block == BLOCK_NIL || block >= nftl->nb_blocks)
493 			break;
494 	}
495 }
496 
497 /* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or
498  *	totally free (only 0xff).
499  *
500  * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
501  *	following criteria:
502  *	1. */
503 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
504 {
505 	struct mtd_info *mtd = nftl->mbd.mtd;
506 	struct nftl_uci1 h1;
507 	unsigned int erase_mark;
508 	size_t retlen;
509 
510 	/* check erase mark. */
511 	if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
512 			  &retlen, (char *)&h1) < 0)
513 		return -1;
514 
515 	erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
516 	if (erase_mark != ERASE_MARK) {
517 		/* if no erase mark, the block must be totally free. This is
518 		   possible in two cases : empty filesystem or interrupted erase (very unlikely) */
519 		if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
520 			return -1;
521 
522 		/* free block : write erase mark */
523 		h1.EraseMark = cpu_to_le16(ERASE_MARK);
524 		h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
525 		h1.WearInfo = cpu_to_le32(0);
526 		if (nftl_write_oob(mtd,
527 				   block * nftl->EraseSize + SECTORSIZE + 8, 8,
528 				   &retlen, (char *)&h1) < 0)
529 			return -1;
530 	} else {
531 #if 0
532 		/* if erase mark present, need to skip it when doing check */
533 		for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) {
534 			/* check free sector */
535 			if (check_free_sectors (nftl, block * nftl->EraseSize + i,
536 						SECTORSIZE, 0) != 0)
537 				return -1;
538 
539 			if (nftl_read_oob(mtd, block * nftl->EraseSize + i,
540 					  16, &retlen, buf) < 0)
541 				return -1;
542 			if (i == SECTORSIZE) {
543 				/* skip erase mark */
544 				if (memcmpb(buf, 0xff, 8))
545 					return -1;
546 			} else {
547 				if (memcmpb(buf, 0xff, 16))
548 					return -1;
549 			}
550 		}
551 #endif
552 	}
553 
554 	return 0;
555 }
556 
557 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
558  *	to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
559  *	is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
560  *	for some reason. A clean up/check of the VUC is necessary in this case.
561  *
562  * WARNING: return 0 if read error
563  */
564 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
565 {
566 	struct mtd_info *mtd = nftl->mbd.mtd;
567 	struct nftl_uci2 uci;
568 	size_t retlen;
569 
570 	if (nftl_read_oob(mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
571 			  8, &retlen, (char *)&uci) < 0)
572 		return 0;
573 
574 	return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
575 }
576 
577 int NFTL_mount(struct NFTLrecord *s)
578 {
579 	int i;
580 	unsigned int first_logical_block, logical_block, rep_block, erase_mark;
581 	unsigned int block, first_block, is_first_block;
582 	int chain_length, do_format_chain;
583 	struct nftl_uci0 h0;
584 	struct nftl_uci1 h1;
585 	struct mtd_info *mtd = s->mbd.mtd;
586 	size_t retlen;
587 
588 	/* search for NFTL MediaHeader and Spare NFTL Media Header */
589 	if (find_boot_record(s) < 0) {
590 		printk("Could not find valid boot record\n");
591 		return -1;
592 	}
593 
594 	/* init the logical to physical table */
595 	for (i = 0; i < s->nb_blocks; i++) {
596 		s->EUNtable[i] = BLOCK_NIL;
597 	}
598 
599 	/* first pass : explore each block chain */
600 	first_logical_block = 0;
601 	for (first_block = 0; first_block < s->nb_blocks; first_block++) {
602 		/* if the block was not already explored, we can look at it */
603 		if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) {
604 			block = first_block;
605 			chain_length = 0;
606 			do_format_chain = 0;
607 
608 			for (;;) {
609 				/* read the block header. If error, we format the chain */
610 				if (nftl_read_oob(mtd,
611 						  block * s->EraseSize + 8, 8,
612 						  &retlen, (char *)&h0) < 0 ||
613 				    nftl_read_oob(mtd,
614 						  block * s->EraseSize +
615 						  SECTORSIZE + 8, 8,
616 						  &retlen, (char *)&h1) < 0) {
617 					s->ReplUnitTable[block] = BLOCK_NIL;
618 					do_format_chain = 1;
619 					break;
620 				}
621 
622 				logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum));
623 				rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum));
624 				erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
625 
626 				is_first_block = !(logical_block >> 15);
627 				logical_block = logical_block & 0x7fff;
628 
629 				/* invalid/free block test */
630 				if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) {
631 					if (chain_length == 0) {
632 						/* if not currently in a chain, we can handle it safely */
633 						if (check_and_mark_free_block(s, block) < 0) {
634 							/* not really free: format it */
635 							printk("Formatting block %d\n", block);
636 							if (NFTL_formatblock(s, block) < 0) {
637 								/* could not format: reserve the block */
638 								s->ReplUnitTable[block] = BLOCK_RESERVED;
639 							} else {
640 								s->ReplUnitTable[block] = BLOCK_FREE;
641 							}
642 						} else {
643 							/* free block: mark it */
644 							s->ReplUnitTable[block] = BLOCK_FREE;
645 						}
646 						/* directly examine the next block. */
647 						goto examine_ReplUnitTable;
648 					} else {
649 						/* the block was in a chain : this is bad. We
650 						   must format all the chain */
651 						printk("Block %d: free but referenced in chain %d\n",
652 						       block, first_block);
653 						s->ReplUnitTable[block] = BLOCK_NIL;
654 						do_format_chain = 1;
655 						break;
656 					}
657 				}
658 
659 				/* we accept only first blocks here */
660 				if (chain_length == 0) {
661 					/* this block is not the first block in chain :
662 					   ignore it, it will be included in a chain
663 					   later, or marked as not explored */
664 					if (!is_first_block)
665 						goto examine_ReplUnitTable;
666 					first_logical_block = logical_block;
667 				} else {
668 					if (logical_block != first_logical_block) {
669 						printk("Block %d: incorrect logical block: %d expected: %d\n",
670 						       block, logical_block, first_logical_block);
671 						/* the chain is incorrect : we must format it,
672 						   but we need to read it completely */
673 						do_format_chain = 1;
674 					}
675 					if (is_first_block) {
676 						/* we accept that a block is marked as first
677 						   block while being last block in a chain
678 						   only if the chain is being folded */
679 						if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS ||
680 						    rep_block != 0xffff) {
681 							printk("Block %d: incorrectly marked as first block in chain\n",
682 							       block);
683 							/* the chain is incorrect : we must format it,
684 							   but we need to read it completely */
685 							do_format_chain = 1;
686 						} else {
687 							printk("Block %d: folding in progress - ignoring first block flag\n",
688 							       block);
689 						}
690 					}
691 				}
692 				chain_length++;
693 				if (rep_block == 0xffff) {
694 					/* no more blocks after */
695 					s->ReplUnitTable[block] = BLOCK_NIL;
696 					break;
697 				} else if (rep_block >= s->nb_blocks) {
698 					printk("Block %d: referencing invalid block %d\n",
699 					       block, rep_block);
700 					do_format_chain = 1;
701 					s->ReplUnitTable[block] = BLOCK_NIL;
702 					break;
703 				} else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) {
704 					/* same problem as previous 'is_first_block' test:
705 					   we accept that the last block of a chain has
706 					   the first_block flag set if folding is in
707 					   progress. We handle here the case where the
708 					   last block appeared first */
709 					if (s->ReplUnitTable[rep_block] == BLOCK_NIL &&
710 					    s->EUNtable[first_logical_block] == rep_block &&
711 					    get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) {
712 						/* EUNtable[] will be set after */
713 						printk("Block %d: folding in progress - ignoring first block flag\n",
714 						       rep_block);
715 						s->ReplUnitTable[block] = rep_block;
716 						s->EUNtable[first_logical_block] = BLOCK_NIL;
717 					} else {
718 						printk("Block %d: referencing block %d already in another chain\n",
719 						       block, rep_block);
720 						/* XXX: should handle correctly fold in progress chains */
721 						do_format_chain = 1;
722 						s->ReplUnitTable[block] = BLOCK_NIL;
723 					}
724 					break;
725 				} else {
726 					/* this is OK */
727 					s->ReplUnitTable[block] = rep_block;
728 					block = rep_block;
729 				}
730 			}
731 
732 			/* the chain was completely explored. Now we can decide
733 			   what to do with it */
734 			if (do_format_chain) {
735 				/* invalid chain : format it */
736 				format_chain(s, first_block);
737 			} else {
738 				unsigned int first_block1, chain_to_format, chain_length1;
739 				int fold_mark;
740 
741 				/* valid chain : get foldmark */
742 				fold_mark = get_fold_mark(s, first_block);
743 				if (fold_mark == 0) {
744 					/* cannot get foldmark : format the chain */
745 					printk("Could read foldmark at block %d\n", first_block);
746 					format_chain(s, first_block);
747 				} else {
748 					if (fold_mark == FOLD_MARK_IN_PROGRESS)
749 						check_sectors_in_chain(s, first_block);
750 
751 					/* now handle the case where we find two chains at the
752 					   same virtual address : we select the longer one,
753 					   because the shorter one is the one which was being
754 					   folded if the folding was not done in place */
755 					first_block1 = s->EUNtable[first_logical_block];
756 					if (first_block1 != BLOCK_NIL) {
757 						/* XXX: what to do if same length ? */
758 						chain_length1 = calc_chain_length(s, first_block1);
759 						printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
760 						       first_block1, chain_length1, first_block, chain_length);
761 
762 						if (chain_length >= chain_length1) {
763 							chain_to_format = first_block1;
764 							s->EUNtable[first_logical_block] = first_block;
765 						} else {
766 							chain_to_format = first_block;
767 						}
768 						format_chain(s, chain_to_format);
769 					} else {
770 						s->EUNtable[first_logical_block] = first_block;
771 					}
772 				}
773 			}
774 		}
775 	examine_ReplUnitTable:;
776 	}
777 
778 	/* second pass to format unreferenced blocks  and init free block count */
779 	s->numfreeEUNs = 0;
780 	s->LastFreeEUN = le16_to_cpu(s->MediaHdr.FirstPhysicalEUN);
781 
782 	for (block = 0; block < s->nb_blocks; block++) {
783 		if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {
784 			printk("Unreferenced block %d, formatting it\n", block);
785 			if (NFTL_formatblock(s, block) < 0)
786 				s->ReplUnitTable[block] = BLOCK_RESERVED;
787 			else
788 				s->ReplUnitTable[block] = BLOCK_FREE;
789 		}
790 		if (s->ReplUnitTable[block] == BLOCK_FREE) {
791 			s->numfreeEUNs++;
792 			s->LastFreeEUN = block;
793 		}
794 	}
795 
796 	return 0;
797 }
798