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