26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <asm/errno.h>
30 #include <asm/uaccess.h>
32 #include <linux/slab.h>
45 static int find_boot_record(
struct INFTLrecord *inftl)
52 struct mtd_info *mtd = inftl->mbd.mtd;
56 pr_debug(
"INFTL: find_boot_record(inftl=%p)\n", inftl);
63 inftl->EraseSize = inftl->mbd.mtd->erasesize;
64 inftl->nb_blocks = (
u32)inftl->mbd.mtd->size / inftl->EraseSize;
69 for (block = 0; block < inftl->nb_blocks; block++) {
81 static int warncount = 5;
85 "of mtd%d failed: %d\n",
86 block * inftl->EraseSize,
87 inftl->mbd.mtd->index, ret);
90 "failures for this block will "
96 if (retlen < 6 ||
memcmp(buf,
"BNAND", 6)) {
104 8, &retlen,(
char *)&h1);
107 "0x%x in mtd%d, but OOB data read failed "
108 "(err %d)\n", block * inftl->EraseSize,
109 inftl->mbd.mtd->index, ret);
131 "Headers disagree.\n");
143 " bootRecordID = %s\n"
144 " NoOfBootImageBlocks = %d\n"
145 " NoOfBinaryPartitions = %d\n"
146 " NoOfBDTLPartitions = %d\n"
147 " BlockMultiplerBits = %d\n"
149 " OsakVersion = 0x%x\n"
150 " PercentUsed = %d\n",
159 "failed: NoOfBDTLPartitions (%d) == 0, "
166 "failed: Total Partitions (%d) > 4, "
176 "UnitSizeFactor 0x%02x\n",
181 "UnitSizeFactor 0x%02x is experimental\n",
183 inftl->EraseSize = inftl->mbd.mtd->erasesize <<
185 inftl->nb_blocks = (
u32)inftl->mbd.mtd->size / inftl->EraseSize;
190 for (i = 0; (i < 4); i++) {
200 " virtualUnits = %d\n"
204 " spareUnits = %d\n",
212 instr->
mtd = inftl->mbd.mtd;
222 instr->
len = inftl->EraseSize;
227 "Partition %d sanity check failed\n"
228 " firstUnit %d : lastUnit %d > "
229 "virtualUnits %d\n", i, ip->
lastUnit,
235 "Partition %d sanity check failed: "
236 "Reserved1 %d != 0\n",
247 "sanity check failed:\n No partition "
248 "marked as Disk Partition\n");
254 if (inftl->numvunits > (inftl->nb_blocks -
255 inftl->nb_boot_blocks - 2)) {
257 "failed:\n numvunits (%d) > nb_blocks "
258 "(%d) - nb_boot_blocks(%d) - 2\n",
259 inftl->numvunits, inftl->nb_blocks,
260 inftl->nb_boot_blocks);
264 inftl->mbd.size = inftl->numvunits *
273 inftl->nb_blocks = ip->
lastUnit + 1;
277 if (!inftl->PUtable) {
279 "failed (%zd bytes)\n",
280 inftl->nb_blocks *
sizeof(
u16));
285 if (!inftl->VUtable) {
286 kfree(inftl->PUtable);
288 "failed (%zd bytes)\n",
289 inftl->nb_blocks *
sizeof(
u16));
294 for (i = 0; i < inftl->nb_boot_blocks; i++)
297 for (; i < inftl->nb_blocks; i++)
304 for (i = 0; i < inftl->nb_blocks; i++) {
308 for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
310 i * inftl->EraseSize + physblock))
315 inftl->MediaUnit =
block;
323 static int memcmpb(
void *
a,
int c,
int n)
326 for (i = 0; i <
n; i++) {
327 if (c != ((
unsigned char *)a)[i])
337 static int check_free_sectors(
struct INFTLrecord *inftl,
unsigned int address,
338 int len,
int check_oob)
341 struct mtd_info *mtd = inftl->mbd.mtd;
355 if (memcmpb(buf + SECTORSIZE, 0xff, mtd->
oobsize) != 0)
378 struct mtd_info *mtd = inftl->mbd.mtd;
381 pr_debug(
"INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block);
389 instr->
mtd = inftl->mbd.mtd;
390 instr->
addr = block * inftl->EraseSize;
391 instr->
len = inftl->mbd.mtd->erasesize;
395 for (physblock = 0; physblock < inftl->EraseSize;
396 physblock += instr->
len, instr->
addr += instr->
len) {
410 if (check_free_sectors(inftl, instr->
addr, instr->
len, 1) != 0)
439 static void format_chain(
struct INFTLrecord *inftl,
unsigned int first_block)
441 unsigned int block = first_block, block1;
447 block1 = inftl->PUtable[
block];
462 if (block ==
BLOCK_NIL || block >= inftl->lastEUN)
471 pr_debug(
"-------------------------------------------"
472 "----------------------------------\n");
474 pr_debug(
"VUtable[%d] ->", s->nb_blocks);
475 for (i = 0; i < s->nb_blocks; i++) {
481 pr_debug(
"\n-------------------------------------------"
482 "----------------------------------\n");
484 pr_debug(
"PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
485 for (i = 0; i <= s->lastEUN; i++) {
491 pr_debug(
"\n-------------------------------------------"
492 "----------------------------------\n");
496 " h/s/c = %d/%d/%d\n"
500 " numfreeEUNs = %d\n"
501 " LastFreeEUN = %d\n"
503 " nb_boot_blocks = %d",
504 s->EraseSize, s->heads, s->sectors, s->cylinders,
505 s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
506 s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
508 pr_debug(
"\n-------------------------------------------"
509 "----------------------------------\n");
516 pr_debug(
"-------------------------------------------"
517 "----------------------------------\n");
519 pr_debug(
"INFTL Virtual Unit Chains:\n");
520 for (logical = 0; logical < s->nb_blocks; logical++) {
521 block = s->VUtable[logical];
522 if (block > s->nb_blocks)
524 pr_debug(
" LOGICAL %d --> %d ", logical, block);
525 for (i = 0; i < s->nb_blocks; i++) {
528 block = s->PUtable[
block];
534 pr_debug(
"-------------------------------------------"
535 "----------------------------------\n");
541 unsigned int block, first_block, prev_block, last_block;
542 unsigned int first_logical_block, logical_block, erase_mark;
543 int chain_length, do_format_chain;
550 pr_debug(
"INFTL: INFTL_mount(inftl=%p)\n", s);
553 if (find_boot_record(s) < 0) {
559 for (i = 0; i < s->nb_blocks; i++)
565 ANACtable = kcalloc(s->nb_blocks,
sizeof(
u8),
GFP_KERNEL);
568 "failed (%zd bytes)\n",
569 s->nb_blocks *
sizeof(
u8));
580 pr_debug(
"INFTL: pass 1, explore each unit\n");
581 for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
590 for (chain_length = 0; ; chain_length++) {
592 if ((chain_length == 0) &&
599 8, &retlen, (
char *)&h0) < 0 ||
614 if (prev_block < s->nb_blocks)
615 prev_block += s->firstEUN;
620 if (logical_block == first_logical_block) {
622 s->PUtable[last_block] =
block;
630 "in chain %d, chain length %d, erase "
631 "mark 0x%x?\n", block, first_block,
632 chain_length, erase_mark);
637 if (chain_length == 0)
650 if ((logical_block >= s->nb_blocks) ||
651 ((prev_block >= s->nb_blocks) &&
653 if (chain_length > 0) {
655 "block %d in chain %d?\n",
663 first_logical_block = logical_block;
665 if (first_logical_block != logical_block) {
679 s->PUtable[last_block] =
block;
688 if (block > s->lastEUN) {
690 "block %d in chain %d?\n", block,
697 if (do_format_chain) {
698 format_chain(s, first_block);
708 s->VUtable[first_logical_block] = first_block;
719 pr_debug(
"INFTL: pass 2, validate virtual chains\n");
720 for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
721 block = s->VUtable[logical_block];
728 ANAC = ANACtable[
block];
729 for (i = 0; i < s->numvunits; i++) {
732 if (s->PUtable[block] > s->lastEUN) {
734 "in virtual chain %d\n",
735 s->PUtable[block], logical_block);
739 if (ANACtable[block] != ANAC) {
745 s->VUtable[logical_block] =
block;
752 block = s->PUtable[
block];
755 if (i >= s->nb_blocks) {
760 format_chain(s, first_block);
773 pr_debug(
"INFTL: pass 3, format unused blocks\n");
774 for (block = s->firstEUN;
block <= s->lastEUN; block++) {
776 printk(
"INFTL: unreferenced block %d, formatting it\n",
786 s->LastFreeEUN =
block;