cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

inftlmount.c (21986B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * inftlmount.c -- INFTL mount code with extensive checks.
      4 *
      5 * Author: Greg Ungerer (gerg@snapgear.com)
      6 * Copyright © 2002-2003, Greg Ungerer (gerg@snapgear.com)
      7 *
      8 * Based heavily on the nftlmount.c code which is:
      9 * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
     10 * Copyright © 2000 Netgem S.A.
     11 */
     12
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <asm/errno.h>
     16#include <asm/io.h>
     17#include <linux/uaccess.h>
     18#include <linux/delay.h>
     19#include <linux/slab.h>
     20#include <linux/mtd/mtd.h>
     21#include <linux/mtd/nftl.h>
     22#include <linux/mtd/inftl.h>
     23
     24/*
     25 * find_boot_record: Find the INFTL Media Header and its Spare copy which
     26 *	contains the various device information of the INFTL partition and
     27 *	Bad Unit Table. Update the PUtable[] table according to the Bad
     28 *	Unit Table. PUtable[] is used for management of Erase Unit in
     29 *	other routines in inftlcore.c and inftlmount.c.
     30 */
     31static int find_boot_record(struct INFTLrecord *inftl)
     32{
     33	struct inftl_unittail h1;
     34	//struct inftl_oob oob;
     35	unsigned int i, block;
     36	u8 buf[SECTORSIZE];
     37	struct INFTLMediaHeader *mh = &inftl->MediaHdr;
     38	struct mtd_info *mtd = inftl->mbd.mtd;
     39	struct INFTLPartition *ip;
     40	size_t retlen;
     41
     42	pr_debug("INFTL: find_boot_record(inftl=%p)\n", inftl);
     43
     44        /*
     45	 * Assume logical EraseSize == physical erasesize for starting the
     46	 * scan. We'll sort it out later if we find a MediaHeader which says
     47	 * otherwise.
     48	 */
     49	inftl->EraseSize = inftl->mbd.mtd->erasesize;
     50        inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
     51
     52	inftl->MediaUnit = BLOCK_NIL;
     53
     54	/* Search for a valid boot record */
     55	for (block = 0; block < inftl->nb_blocks; block++) {
     56		int ret;
     57
     58		/*
     59		 * Check for BNAND header first. Then whinge if it's found
     60		 * but later checks fail.
     61		 */
     62		ret = mtd_read(mtd, block * inftl->EraseSize, SECTORSIZE,
     63			       &retlen, buf);
     64		/* We ignore ret in case the ECC of the MediaHeader is invalid
     65		   (which is apparently acceptable) */
     66		if (retlen != SECTORSIZE) {
     67			static int warncount = 5;
     68
     69			if (warncount) {
     70				printk(KERN_WARNING "INFTL: block read at 0x%x "
     71					"of mtd%d failed: %d\n",
     72					block * inftl->EraseSize,
     73					inftl->mbd.mtd->index, ret);
     74				if (!--warncount)
     75					printk(KERN_WARNING "INFTL: further "
     76						"failures for this block will "
     77						"not be printed\n");
     78			}
     79			continue;
     80		}
     81
     82		if (retlen < 6 || memcmp(buf, "BNAND", 6)) {
     83			/* BNAND\0 not found. Continue */
     84			continue;
     85		}
     86
     87		/* To be safer with BIOS, also use erase mark as discriminant */
     88		ret = inftl_read_oob(mtd,
     89				     block * inftl->EraseSize + SECTORSIZE + 8,
     90				     8, &retlen,(char *)&h1);
     91		if (ret < 0) {
     92			printk(KERN_WARNING "INFTL: ANAND header found at "
     93				"0x%x in mtd%d, but OOB data read failed "
     94				"(err %d)\n", block * inftl->EraseSize,
     95				inftl->mbd.mtd->index, ret);
     96			continue;
     97		}
     98
     99
    100		/*
    101		 * This is the first we've seen.
    102		 * Copy the media header structure into place.
    103		 */
    104		memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
    105
    106		/* Read the spare media header at offset 4096 */
    107		mtd_read(mtd, block * inftl->EraseSize + 4096, SECTORSIZE,
    108			 &retlen, buf);
    109		if (retlen != SECTORSIZE) {
    110			printk(KERN_WARNING "INFTL: Unable to read spare "
    111			       "Media Header\n");
    112			return -1;
    113		}
    114		/* Check if this one is the same as the first one we found. */
    115		if (memcmp(mh, buf, sizeof(struct INFTLMediaHeader))) {
    116			printk(KERN_WARNING "INFTL: Primary and spare Media "
    117			       "Headers disagree.\n");
    118			return -1;
    119		}
    120
    121		mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
    122		mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
    123		mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
    124		mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
    125		mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
    126		mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
    127
    128		pr_debug("INFTL: Media Header ->\n"
    129			 "    bootRecordID          = %s\n"
    130			 "    NoOfBootImageBlocks   = %d\n"
    131			 "    NoOfBinaryPartitions  = %d\n"
    132			 "    NoOfBDTLPartitions    = %d\n"
    133			 "    BlockMultiplierBits   = %d\n"
    134			 "    FormatFlgs            = %d\n"
    135			 "    OsakVersion           = 0x%x\n"
    136			 "    PercentUsed           = %d\n",
    137			 mh->bootRecordID, mh->NoOfBootImageBlocks,
    138			 mh->NoOfBinaryPartitions,
    139			 mh->NoOfBDTLPartitions,
    140			 mh->BlockMultiplierBits, mh->FormatFlags,
    141			 mh->OsakVersion, mh->PercentUsed);
    142
    143		if (mh->NoOfBDTLPartitions == 0) {
    144			printk(KERN_WARNING "INFTL: Media Header sanity check "
    145				"failed: NoOfBDTLPartitions (%d) == 0, "
    146				"must be at least 1\n", mh->NoOfBDTLPartitions);
    147			return -1;
    148		}
    149
    150		if ((mh->NoOfBDTLPartitions + mh->NoOfBinaryPartitions) > 4) {
    151			printk(KERN_WARNING "INFTL: Media Header sanity check "
    152				"failed: Total Partitions (%d) > 4, "
    153				"BDTL=%d Binary=%d\n", mh->NoOfBDTLPartitions +
    154				mh->NoOfBinaryPartitions,
    155				mh->NoOfBDTLPartitions,
    156				mh->NoOfBinaryPartitions);
    157			return -1;
    158		}
    159
    160		if (mh->BlockMultiplierBits > 1) {
    161			printk(KERN_WARNING "INFTL: sorry, we don't support "
    162				"UnitSizeFactor 0x%02x\n",
    163				mh->BlockMultiplierBits);
    164			return -1;
    165		} else if (mh->BlockMultiplierBits == 1) {
    166			printk(KERN_WARNING "INFTL: support for INFTL with "
    167				"UnitSizeFactor 0x%02x is experimental\n",
    168				mh->BlockMultiplierBits);
    169			inftl->EraseSize = inftl->mbd.mtd->erasesize <<
    170				mh->BlockMultiplierBits;
    171			inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
    172			block >>= mh->BlockMultiplierBits;
    173		}
    174
    175		/* Scan the partitions */
    176		for (i = 0; (i < 4); i++) {
    177			ip = &mh->Partitions[i];
    178			ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
    179			ip->firstUnit = le32_to_cpu(ip->firstUnit);
    180			ip->lastUnit = le32_to_cpu(ip->lastUnit);
    181			ip->flags = le32_to_cpu(ip->flags);
    182			ip->spareUnits = le32_to_cpu(ip->spareUnits);
    183			ip->Reserved0 = le32_to_cpu(ip->Reserved0);
    184
    185			pr_debug("    PARTITION[%d] ->\n"
    186				 "        virtualUnits    = %d\n"
    187				 "        firstUnit       = %d\n"
    188				 "        lastUnit        = %d\n"
    189				 "        flags           = 0x%x\n"
    190				 "        spareUnits      = %d\n",
    191				 i, ip->virtualUnits, ip->firstUnit,
    192				 ip->lastUnit, ip->flags,
    193				 ip->spareUnits);
    194
    195			if (ip->Reserved0 != ip->firstUnit) {
    196				struct erase_info *instr = &inftl->instr;
    197
    198				/*
    199				 * 	Most likely this is using the
    200				 * 	undocumented qiuck mount feature.
    201				 * 	We don't support that, we will need
    202				 * 	to erase the hidden block for full
    203				 * 	compatibility.
    204				 */
    205				instr->addr = ip->Reserved0 * inftl->EraseSize;
    206				instr->len = inftl->EraseSize;
    207				mtd_erase(mtd, instr);
    208			}
    209			if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
    210				printk(KERN_WARNING "INFTL: Media Header "
    211					"Partition %d sanity check failed\n"
    212					"    firstUnit %d : lastUnit %d  >  "
    213					"virtualUnits %d\n", i, ip->lastUnit,
    214					ip->firstUnit, ip->Reserved0);
    215				return -1;
    216			}
    217			if (ip->Reserved1 != 0) {
    218				printk(KERN_WARNING "INFTL: Media Header "
    219					"Partition %d sanity check failed: "
    220					"Reserved1 %d != 0\n",
    221					i, ip->Reserved1);
    222				return -1;
    223			}
    224
    225			if (ip->flags & INFTL_BDTL)
    226				break;
    227		}
    228
    229		if (i >= 4) {
    230			printk(KERN_WARNING "INFTL: Media Header Partition "
    231				"sanity check failed:\n       No partition "
    232				"marked as Disk Partition\n");
    233			return -1;
    234		}
    235
    236		inftl->nb_boot_blocks = ip->firstUnit;
    237		inftl->numvunits = ip->virtualUnits;
    238		if (inftl->numvunits > (inftl->nb_blocks -
    239		    inftl->nb_boot_blocks - 2)) {
    240			printk(KERN_WARNING "INFTL: Media Header sanity check "
    241				"failed:\n        numvunits (%d) > nb_blocks "
    242				"(%d) - nb_boot_blocks(%d) - 2\n",
    243				inftl->numvunits, inftl->nb_blocks,
    244				inftl->nb_boot_blocks);
    245			return -1;
    246		}
    247
    248		inftl->mbd.size  = inftl->numvunits *
    249			(inftl->EraseSize / SECTORSIZE);
    250
    251		/*
    252		 * Block count is set to last used EUN (we won't need to keep
    253		 * any meta-data past that point).
    254		 */
    255		inftl->firstEUN = ip->firstUnit;
    256		inftl->lastEUN = ip->lastUnit;
    257		inftl->nb_blocks = ip->lastUnit + 1;
    258
    259		/* Memory alloc */
    260		inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
    261					       GFP_KERNEL);
    262		if (!inftl->PUtable)
    263			return -ENOMEM;
    264
    265		inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
    266					       GFP_KERNEL);
    267		if (!inftl->VUtable) {
    268			kfree(inftl->PUtable);
    269			return -ENOMEM;
    270		}
    271
    272		/* Mark the blocks before INFTL MediaHeader as reserved */
    273		for (i = 0; i < inftl->nb_boot_blocks; i++)
    274			inftl->PUtable[i] = BLOCK_RESERVED;
    275		/* Mark all remaining blocks as potentially containing data */
    276		for (; i < inftl->nb_blocks; i++)
    277			inftl->PUtable[i] = BLOCK_NOTEXPLORED;
    278
    279		/* Mark this boot record (NFTL MediaHeader) block as reserved */
    280		inftl->PUtable[block] = BLOCK_RESERVED;
    281
    282		/* Read Bad Erase Unit Table and modify PUtable[] accordingly */
    283		for (i = 0; i < inftl->nb_blocks; i++) {
    284			int physblock;
    285			/* If any of the physical eraseblocks are bad, don't
    286			   use the unit. */
    287			for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
    288				if (mtd_block_isbad(inftl->mbd.mtd,
    289						    i * inftl->EraseSize + physblock))
    290					inftl->PUtable[i] = BLOCK_RESERVED;
    291			}
    292		}
    293
    294		inftl->MediaUnit = block;
    295		return 0;
    296	}
    297
    298	/* Not found. */
    299	return -1;
    300}
    301
    302static int memcmpb(void *a, int c, int n)
    303{
    304	int i;
    305	for (i = 0; i < n; i++) {
    306		if (c != ((unsigned char *)a)[i])
    307			return 1;
    308	}
    309	return 0;
    310}
    311
    312/*
    313 * check_free_sector: check if a free sector is actually FREE,
    314 *	i.e. All 0xff in data and oob area.
    315 */
    316static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
    317	int len, int check_oob)
    318{
    319	struct mtd_info *mtd = inftl->mbd.mtd;
    320	size_t retlen;
    321	int i, ret;
    322	u8 *buf;
    323
    324	buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL);
    325	if (!buf)
    326		return -ENOMEM;
    327
    328	ret = -1;
    329	for (i = 0; i < len; i += SECTORSIZE) {
    330		if (mtd_read(mtd, address, SECTORSIZE, &retlen, buf))
    331			goto out;
    332		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
    333			goto out;
    334
    335		if (check_oob) {
    336			if(inftl_read_oob(mtd, address, mtd->oobsize,
    337					  &retlen, &buf[SECTORSIZE]) < 0)
    338				goto out;
    339			if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
    340				goto out;
    341		}
    342		address += SECTORSIZE;
    343	}
    344
    345	ret = 0;
    346
    347out:
    348	kfree(buf);
    349	return ret;
    350}
    351
    352/*
    353 * INFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase
    354 *		 Unit and Update INFTL metadata. Each erase operation is
    355 *		 checked with check_free_sectors.
    356 *
    357 * Return: 0 when succeed, -1 on error.
    358 *
    359 * ToDo: 1. Is it necessary to check_free_sector after erasing ??
    360 */
    361int INFTL_formatblock(struct INFTLrecord *inftl, int block)
    362{
    363	size_t retlen;
    364	struct inftl_unittail uci;
    365	struct erase_info *instr = &inftl->instr;
    366	struct mtd_info *mtd = inftl->mbd.mtd;
    367	int physblock;
    368
    369	pr_debug("INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block);
    370
    371	memset(instr, 0, sizeof(struct erase_info));
    372
    373	/* FIXME: Shouldn't we be setting the 'discarded' flag to zero
    374	   _first_? */
    375
    376	/* Use async erase interface, test return code */
    377	instr->addr = block * inftl->EraseSize;
    378	instr->len = inftl->mbd.mtd->erasesize;
    379	/* Erase one physical eraseblock at a time, even though the NAND api
    380	   allows us to group them.  This way we if we have a failure, we can
    381	   mark only the failed block in the bbt. */
    382	for (physblock = 0; physblock < inftl->EraseSize;
    383	     physblock += instr->len, instr->addr += instr->len) {
    384		int ret;
    385
    386		ret = mtd_erase(inftl->mbd.mtd, instr);
    387		if (ret) {
    388			printk(KERN_WARNING "INFTL: error while formatting block %d\n",
    389				block);
    390			goto fail;
    391		}
    392
    393		/*
    394		 * Check the "freeness" of Erase Unit before updating metadata.
    395		 * FixMe: is this check really necessary? Since we have check
    396		 * the return code after the erase operation.
    397		 */
    398		if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
    399			goto fail;
    400	}
    401
    402	uci.EraseMark = cpu_to_le16(ERASE_MARK);
    403	uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
    404	uci.Reserved[0] = 0;
    405	uci.Reserved[1] = 0;
    406	uci.Reserved[2] = 0;
    407	uci.Reserved[3] = 0;
    408	instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
    409	if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0)
    410		goto fail;
    411	return 0;
    412fail:
    413	/* could not format, update the bad block table (caller is responsible
    414	   for setting the PUtable to BLOCK_RESERVED on failure) */
    415	mtd_block_markbad(inftl->mbd.mtd, instr->addr);
    416	return -1;
    417}
    418
    419/*
    420 * format_chain: Format an invalid Virtual Unit chain. It frees all the Erase
    421 *	Units in a Virtual Unit Chain, i.e. all the units are disconnected.
    422 *
    423 *	Since the chain is invalid then we will have to erase it from its
    424 *	head (normally for INFTL we go from the oldest). But if it has a
    425 *	loop then there is no oldest...
    426 */
    427static void format_chain(struct INFTLrecord *inftl, unsigned int first_block)
    428{
    429	unsigned int block = first_block, block1;
    430
    431	printk(KERN_WARNING "INFTL: formatting chain at block %d\n",
    432		first_block);
    433
    434	for (;;) {
    435		block1 = inftl->PUtable[block];
    436
    437		printk(KERN_WARNING "INFTL: formatting block %d\n", block);
    438		if (INFTL_formatblock(inftl, block) < 0) {
    439			/*
    440			 * Cannot format !!!! Mark it as Bad Unit,
    441			 */
    442			inftl->PUtable[block] = BLOCK_RESERVED;
    443		} else {
    444			inftl->PUtable[block] = BLOCK_FREE;
    445		}
    446
    447		/* Goto next block on the chain */
    448		block = block1;
    449
    450		if (block == BLOCK_NIL || block >= inftl->lastEUN)
    451			break;
    452	}
    453}
    454
    455void INFTL_dumptables(struct INFTLrecord *s)
    456{
    457	int i;
    458
    459	pr_debug("-------------------------------------------"
    460		"----------------------------------\n");
    461
    462	pr_debug("VUtable[%d] ->", s->nb_blocks);
    463	for (i = 0; i < s->nb_blocks; i++) {
    464		if ((i % 8) == 0)
    465			pr_debug("\n%04x: ", i);
    466		pr_debug("%04x ", s->VUtable[i]);
    467	}
    468
    469	pr_debug("\n-------------------------------------------"
    470		"----------------------------------\n");
    471
    472	pr_debug("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
    473	for (i = 0; i <= s->lastEUN; i++) {
    474		if ((i % 8) == 0)
    475			pr_debug("\n%04x: ", i);
    476		pr_debug("%04x ", s->PUtable[i]);
    477	}
    478
    479	pr_debug("\n-------------------------------------------"
    480		"----------------------------------\n");
    481
    482	pr_debug("INFTL ->\n"
    483		"  EraseSize       = %d\n"
    484		"  h/s/c           = %d/%d/%d\n"
    485		"  numvunits       = %d\n"
    486		"  firstEUN        = %d\n"
    487		"  lastEUN         = %d\n"
    488		"  numfreeEUNs     = %d\n"
    489		"  LastFreeEUN     = %d\n"
    490		"  nb_blocks       = %d\n"
    491		"  nb_boot_blocks  = %d",
    492		s->EraseSize, s->heads, s->sectors, s->cylinders,
    493		s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
    494		s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
    495
    496	pr_debug("\n-------------------------------------------"
    497		"----------------------------------\n");
    498}
    499
    500void INFTL_dumpVUchains(struct INFTLrecord *s)
    501{
    502	int logical, block, i;
    503
    504	pr_debug("-------------------------------------------"
    505		"----------------------------------\n");
    506
    507	pr_debug("INFTL Virtual Unit Chains:\n");
    508	for (logical = 0; logical < s->nb_blocks; logical++) {
    509		block = s->VUtable[logical];
    510		if (block >= s->nb_blocks)
    511			continue;
    512		pr_debug("  LOGICAL %d --> %d ", logical, block);
    513		for (i = 0; i < s->nb_blocks; i++) {
    514			if (s->PUtable[block] == BLOCK_NIL)
    515				break;
    516			block = s->PUtable[block];
    517			pr_debug("%d ", block);
    518		}
    519		pr_debug("\n");
    520	}
    521
    522	pr_debug("-------------------------------------------"
    523		"----------------------------------\n");
    524}
    525
    526int INFTL_mount(struct INFTLrecord *s)
    527{
    528	struct mtd_info *mtd = s->mbd.mtd;
    529	unsigned int block, first_block, prev_block, last_block;
    530	unsigned int first_logical_block, logical_block, erase_mark;
    531	int chain_length, do_format_chain;
    532	struct inftl_unithead1 h0;
    533	struct inftl_unittail h1;
    534	size_t retlen;
    535	int i;
    536	u8 *ANACtable, ANAC;
    537
    538	pr_debug("INFTL: INFTL_mount(inftl=%p)\n", s);
    539
    540	/* Search for INFTL MediaHeader and Spare INFTL Media Header */
    541	if (find_boot_record(s) < 0) {
    542		printk(KERN_WARNING "INFTL: could not find valid boot record?\n");
    543		return -ENXIO;
    544	}
    545
    546	/* Init the logical to physical table */
    547	for (i = 0; i < s->nb_blocks; i++)
    548		s->VUtable[i] = BLOCK_NIL;
    549
    550	logical_block = block = BLOCK_NIL;
    551
    552	/* Temporary buffer to store ANAC numbers. */
    553	ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL);
    554	if (!ANACtable)
    555		return -ENOMEM;
    556
    557	/*
    558	 * First pass is to explore each physical unit, and construct the
    559	 * virtual chains that exist (newest physical unit goes into VUtable).
    560	 * Any block that is in any way invalid will be left in the
    561	 * NOTEXPLORED state. Then at the end we will try to format it and
    562	 * mark it as free.
    563	 */
    564	pr_debug("INFTL: pass 1, explore each unit\n");
    565	for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
    566		if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
    567			continue;
    568
    569		do_format_chain = 0;
    570		first_logical_block = BLOCK_NIL;
    571		last_block = BLOCK_NIL;
    572		block = first_block;
    573
    574		for (chain_length = 0; ; chain_length++) {
    575
    576			if ((chain_length == 0) &&
    577			    (s->PUtable[block] != BLOCK_NOTEXPLORED)) {
    578				/* Nothing to do here, onto next block */
    579				break;
    580			}
    581
    582			if (inftl_read_oob(mtd, block * s->EraseSize + 8,
    583					   8, &retlen, (char *)&h0) < 0 ||
    584			    inftl_read_oob(mtd, block * s->EraseSize +
    585					   2 * SECTORSIZE + 8, 8, &retlen,
    586					   (char *)&h1) < 0) {
    587				/* Should never happen? */
    588				do_format_chain++;
    589				break;
    590			}
    591
    592			logical_block = le16_to_cpu(h0.virtualUnitNo);
    593			prev_block = le16_to_cpu(h0.prevUnitNo);
    594			erase_mark = le16_to_cpu((h1.EraseMark | h1.EraseMark1));
    595			ANACtable[block] = h0.ANAC;
    596
    597			/* Previous block is relative to start of Partition */
    598			if (prev_block < s->nb_blocks)
    599				prev_block += s->firstEUN;
    600
    601			/* Already explored partial chain? */
    602			if (s->PUtable[block] != BLOCK_NOTEXPLORED) {
    603				/* Check if chain for this logical */
    604				if (logical_block == first_logical_block) {
    605					if (last_block != BLOCK_NIL)
    606						s->PUtable[last_block] = block;
    607				}
    608				break;
    609			}
    610
    611			/* Check for invalid block */
    612			if (erase_mark != ERASE_MARK) {
    613				printk(KERN_WARNING "INFTL: corrupt block %d "
    614					"in chain %d, chain length %d, erase "
    615					"mark 0x%x?\n", block, first_block,
    616					chain_length, erase_mark);
    617				/*
    618				 * Assume end of chain, probably incomplete
    619				 * fold/erase...
    620				 */
    621				if (chain_length == 0)
    622					do_format_chain++;
    623				break;
    624			}
    625
    626			/* Check for it being free already then... */
    627			if ((logical_block == BLOCK_FREE) ||
    628			    (logical_block == BLOCK_NIL)) {
    629				s->PUtable[block] = BLOCK_FREE;
    630				break;
    631			}
    632
    633			/* Sanity checks on block numbers */
    634			if ((logical_block >= s->nb_blocks) ||
    635			    ((prev_block >= s->nb_blocks) &&
    636			     (prev_block != BLOCK_NIL))) {
    637				if (chain_length > 0) {
    638					printk(KERN_WARNING "INFTL: corrupt "
    639						"block %d in chain %d?\n",
    640						block, first_block);
    641					do_format_chain++;
    642				}
    643				break;
    644			}
    645
    646			if (first_logical_block == BLOCK_NIL) {
    647				first_logical_block = logical_block;
    648			} else {
    649				if (first_logical_block != logical_block) {
    650					/* Normal for folded chain... */
    651					break;
    652				}
    653			}
    654
    655			/*
    656			 * Current block is valid, so if we followed a virtual
    657			 * chain to get here then we can set the previous
    658			 * block pointer in our PUtable now. Then move onto
    659			 * the previous block in the chain.
    660			 */
    661			s->PUtable[block] = BLOCK_NIL;
    662			if (last_block != BLOCK_NIL)
    663				s->PUtable[last_block] = block;
    664			last_block = block;
    665			block = prev_block;
    666
    667			/* Check for end of chain */
    668			if (block == BLOCK_NIL)
    669				break;
    670
    671			/* Validate next block before following it... */
    672			if (block > s->lastEUN) {
    673				printk(KERN_WARNING "INFTL: invalid previous "
    674					"block %d in chain %d?\n", block,
    675					first_block);
    676				do_format_chain++;
    677				break;
    678			}
    679		}
    680
    681		if (do_format_chain) {
    682			format_chain(s, first_block);
    683			continue;
    684		}
    685
    686		/*
    687		 * Looks like a valid chain then. It may not really be the
    688		 * newest block in the chain, but it is the newest we have
    689		 * found so far. We might update it in later iterations of
    690		 * this loop if we find something newer.
    691		 */
    692		s->VUtable[first_logical_block] = first_block;
    693		logical_block = BLOCK_NIL;
    694	}
    695
    696	INFTL_dumptables(s);
    697
    698	/*
    699	 * Second pass, check for infinite loops in chains. These are
    700	 * possible because we don't update the previous pointers when
    701	 * we fold chains. No big deal, just fix them up in PUtable.
    702	 */
    703	pr_debug("INFTL: pass 2, validate virtual chains\n");
    704	for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
    705		block = s->VUtable[logical_block];
    706		last_block = BLOCK_NIL;
    707
    708		/* Check for free/reserved/nil */
    709		if (block >= BLOCK_RESERVED)
    710			continue;
    711
    712		ANAC = ANACtable[block];
    713		for (i = 0; i < s->numvunits; i++) {
    714			if (s->PUtable[block] == BLOCK_NIL)
    715				break;
    716			if (s->PUtable[block] > s->lastEUN) {
    717				printk(KERN_WARNING "INFTL: invalid prev %d, "
    718					"in virtual chain %d\n",
    719					s->PUtable[block], logical_block);
    720				s->PUtable[block] = BLOCK_NIL;
    721
    722			}
    723			if (ANACtable[block] != ANAC) {
    724				/*
    725				 * Chain must point back to itself. This is ok,
    726				 * but we will need adjust the tables with this
    727				 * newest block and oldest block.
    728				 */
    729				s->VUtable[logical_block] = block;
    730				s->PUtable[last_block] = BLOCK_NIL;
    731				break;
    732			}
    733
    734			ANAC--;
    735			last_block = block;
    736			block = s->PUtable[block];
    737		}
    738
    739		if (i >= s->nb_blocks) {
    740			/*
    741			 * Uhoo, infinite chain with valid ANACS!
    742			 * Format whole chain...
    743			 */
    744			format_chain(s, first_block);
    745		}
    746	}
    747
    748	INFTL_dumptables(s);
    749	INFTL_dumpVUchains(s);
    750
    751	/*
    752	 * Third pass, format unreferenced blocks and init free block count.
    753	 */
    754	s->numfreeEUNs = 0;
    755	s->LastFreeEUN = BLOCK_NIL;
    756
    757	pr_debug("INFTL: pass 3, format unused blocks\n");
    758	for (block = s->firstEUN; block <= s->lastEUN; block++) {
    759		if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
    760			printk("INFTL: unreferenced block %d, formatting it\n",
    761				block);
    762			if (INFTL_formatblock(s, block) < 0)
    763				s->PUtable[block] = BLOCK_RESERVED;
    764			else
    765				s->PUtable[block] = BLOCK_FREE;
    766		}
    767		if (s->PUtable[block] == BLOCK_FREE) {
    768			s->numfreeEUNs++;
    769			if (s->LastFreeEUN == BLOCK_NIL)
    770				s->LastFreeEUN = block;
    771		}
    772	}
    773
    774	kfree(ANACtable);
    775	return 0;
    776}