Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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