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