예제 #1
0
/*******************************************************************
* Reconstruct bmt, called when found bmt info doesn't match bad 
* block info in flash.
* 
* Return NULL for failure
*******************************************************************/
bmt_struct *reconstruct_bmt(bmt_struct * bmt)
{
    int i;
    int index = system_block_count;
    unsigned short bad_index;
    int mapped;

    bmt->version = BMT_VERSION;
    bmt->bad_count = 0;
    bmt->mapped_count = 0;

    memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry));

    for (i = 0; i < bmt_block_count; i++, index++)
    {
        if (nand_block_bad_bmt(OFFSET(index)))
        {
            MSG(INFO, "Skip bad block: 0x%x\n", index);
            continue;
        }

        nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf);
        if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count)
        {
            MSG(INIT, "get bad index: 0x%x\n", bad_index);
            if (bad_index != 0xFFFF)
                MSG(INIT, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index);
            continue;
        }

        MSG(INIT, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index);

        if (!nand_block_bad_bmt(OFFSET(bad_index)))
        {
            MSG(INIT, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index);
            continue;           // no need to erase here, it will be erased later when trying to write BMT
        }

        if ((mapped = is_block_mapped(bad_index)) >= 0)
        {
            MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index);
            bmt->table[mapped].mapped_index = index;    // use new one instead.
        } else
        {
            bmt->table[bmt->mapped_count].bad_index = bad_index;
            bmt->table[bmt->mapped_count].mapped_index = index;
            bmt->mapped_count++;
        }

        MSG(INIT, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index);

    }

    MSG(INIT, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count);

    memset(oob_buf, 0xFF, sizeof(oob_buf));
    fill_nand_bmt_buffer(bmt, dat_buf, oob_buf);

    if (!write_bmt_to_flash(dat_buf, oob_buf))
    {
        MSG(INIT, "TRAGEDY: cannot find a place to write BMT!!!!\n");
    }

    return bmt;
}
예제 #2
0
/*************************************************************************
* Find an available block and erase.                                     *
* start_from_end: if true, find available block from end of flash.       *
*                 else, find from the beginning of the pool              *
* need_erase: if true, all unmapped blocks in the pool will be erased    *
*************************************************************************/
static int find_available_block(bool start_from_end)
{
    int i;
    int block = system_block_count;
    int direction;
    MSG("Try to find_available_block, pool_erase: %d\n", pool_erased);

    // erase all un-mapped blocks in pool when finding avaliable block
    if (!pool_erased)
    {
        for (i = 0; i < bmt_block_count; i++)
        {
	        if ((block + i) == bmt_block_index)    
	        {
	            MSG("Skip bmt block %d \n", block + i);
	            continue;
	        }            

	        if ((block + i) == bbt_block_index)    
	        {
	            MSG("Skip bbt block %d \n", block + i);
	            continue;
	        }  
	        
	        if (nand_block_bad_bmt(OFFSET(block + i), BAD_BLOCK_RAW) || nand_block_bad_bmt(OFFSET(block + i), BMT_BADBLOCK_GENERATE_LATER))
            {
                MSG("Skip bad block %d \n", block + i);
                continue;
            }

            if (is_block_mapped(block + i) >= 0)
            {
                MSG("Skip mapped block %d \n", block + i);
                continue;
            }

            if (nand_erase_bmt(OFFSET(block + i)))
            {
                MSG("Erase block %d fail\n", block + i);
                mark_block_bad_bmt(OFFSET(block + i), BMT_BADBLOCK_GENERATE_LATER);
            }
        }

        pool_erased = 1;
    }

    if (start_from_end)
    {
        block = total_block_count - 1;
        direction = -1;
    }
    else
    {
        block = system_block_count;
        direction = 1;
    }

    for (i = 0; i < bmt_block_count; i++, block += direction)
    {
        if (block == bmt_block_index)
        {
            MSG("Skip bmt block %d \n", block);
            continue;
        }

        if (block == bbt_block_index)
        {
            MSG("Skip bbt block %d \n", block);
            continue;
        }
        
        if (nand_block_bad_bmt(OFFSET(block), BAD_BLOCK_RAW) || nand_block_bad_bmt(OFFSET(block), BMT_BADBLOCK_GENERATE_LATER))
        {
            MSG("Skip bad block %d \n", block);
            continue;
        }

        if (is_block_mapped(block) >= 0)
        {
            MSG("Skip mapped block %d \n", block);
            continue;
        }

        MSG("Find block %d available\n", block);
        return block;
    }

    return 0;
}
예제 #3
0
/*************************************************************************
* Find an available block and erase.                                     *
* start_from_end: if true, find available block from end of flash.       *
*                 else, find from the beginning of the pool              *
* need_erase: if true, all unmapped blocks in the pool will be erased    *
*************************************************************************/
static int find_available_block(bool start_from_end)
{
    int i;                      // , j;
    int block = system_block_count;
    int direction;
    MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased);
    if (!pool_erased)
    {
        MSG(INIT, "Erase all un-mapped blocks in pool\n");
        for (i = 0; i < bmt_block_count; i++)
        {
            if (block == bmt_block_index)
            {
                MSG(INIT, "Skip bmt block 0x%x\n", block);
                continue;
            }

            if (nand_block_bad_bmt(OFFSET(block + i)))
            {
                MSG(INIT, "Skip bad block 0x%x\n", block + i);
                continue;
            }

            if (is_block_mapped(block + i) >= 0)
            {
                MSG(INIT, "Skip mapped block 0x%x\n", block + i);
                continue;
            }

            if (!nand_erase_bmt(OFFSET(block + i)))
            {
                MSG(INIT, "Erase block 0x%x failed\n", block + i);
                mark_block_bad_bmt(OFFSET(block + i));
            }
        }

        pool_erased = 1;
    }

    if (start_from_end)
    {
        block = total_block_count - 1;
        direction = -1;
    } else
    {
        block = system_block_count;
        direction = 1;
    }

    for (i = 0; i < bmt_block_count; i++, block += direction)
    {
        if (block == bmt_block_index)
        {
            MSG(INIT, "Skip bmt block 0x%x\n", block);
            continue;
        }

        if (nand_block_bad_bmt(OFFSET(block)))
        {
            MSG(INIT, "Skip bad block 0x%x\n", block);
            continue;
        }

        if (is_block_mapped(block) >= 0)
        {
            MSG(INIT, "Skip mapped block 0x%x\n", block);
            continue;
        }

        MSG(INIT, "Find block 0x%x available\n", block);
        return block;
    }

    return 0;
}
예제 #4
0
/*******************************************************************
* Reconstruct bmt, called when found bmt info doesn't match bad 
* block info in flash.
* 
* Return NULL for failure
*******************************************************************/
bmt_struct *reconstruct_bmt(bmt_struct * bmt)
{
    int i;
    int index = system_block_count;
    unsigned short bad_index;
    int mapped;

    // init everything in BMT struct 
    bmt->version = BMT_VERSION;
    bmt->bad_count = 0;
    bmt->mapped_count = 0;
    
    memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry));

    for (i = 0; i < bmt_block_count; i++, index++)
    {
        if (nand_block_bad_bmt(OFFSET(index)))
        {
            // MSG(INIT,  "Skip bad block: 0x%x\n", index);
            // bmt->bad_count++;
            continue;
        }

        // MSG(INIT,  "read page: 0x%x\n", PAGE_ADDR(index));
        nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf);
        /* if (mt6573_nand_read_page_hw(PAGE_ADDR(index), dat_buf))
        {
            MSG(INIT,  "Error when read block %d\n", bmt_block_index);
            continue;
        } */

        if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count)
        {
            // MSG(INIT, "get bad index: 0x%x\n", bad_index);
            if (bad_index != 0xFFFF)
                MSG(INIT,  "warning @ 0x%x\n", index);
            continue;
        }

        // MSG(INIT,  "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index);

        if (!nand_block_bad_bmt(OFFSET(bad_index)))
        {
            // MSG(INIT,  "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index);
            continue;       // no need to erase here, it will be erased later when trying to write BMT
        }


        if ( (mapped = is_block_mapped(bad_index)) >= 0)
        {
            // MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", 
            //     bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index);
            bmt->table[mapped].mapped_index = index;    // use new one instead.
        }
        else
        {
            // add mapping to BMT
            bmt->table[bmt->mapped_count].bad_index = bad_index;
            bmt->table[bmt->mapped_count].mapped_index = index;
            bmt->mapped_count++;
        }

        MSG(INIT,  "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index);

    }

    MSG(INIT,  "Scan replace pool done, mapped block: %d\n", bmt->mapped_count);
    // dump_bmt_info(bmt);

    // fill NAND BMT buffer
    memset(oob_buf, 0xFF, sizeof(oob_buf));
    fill_nand_bmt_buffer(bmt, dat_buf, oob_buf);

    // write BMT back
    if (!write_bmt_to_flash(dat_buf, oob_buf))
    {
        MSG(INIT,  "TRAGEDY\n");
    }

    return bmt;
}