/***************************************************************************** * name : flash_scan_bad * * description : scan bad block, if partition_name is NULL, scan all partitions * * input : char *partition_name: partition to scan * * other : No *****************************************************************************/ void flash_scan_bad(char *partition_name) { struct ptentry *ptn = NULL; struct ST_PART_TBL *part = (struct ST_PART_TBL *)SHM_MEM_PTABLE_ADDR; struct nand_spec spec; struct ptentry tn; if(nand_get_spec(&spec)) { cprintf("ERROR: nand get spec failed!\n"); return; } partition_name = bsp_nand_argument_check(partition_name); /* scan all partitions */ if(!partition_name) { part++; while(0 != strcmp(PTABLE_END_STR, part->name)) { if(DATA_VALID == ptable_get_validity(part)) { /* coverity[buffer_size_warning] */ strncpy(tn.name, part->name, 16); tn.start = part->offset; tn.length = part->capacity; /* coverity[uninit_use_in_call] */ get_partition_badblock(&tn, &spec); } part++; } } else /* scan one partition */ { ptn = flash_find_ptn(partition_name); if(!ptn) { cprintf("ERROR: wrong partition name: %s\n", partition_name); return; } /* coverity[uninit_use_in_call] */ get_partition_badblock(ptn, &spec); } cprintf("\n\n"); return; }
/***************************************************************************** * name : flash_erase_force * * description : Erase nand block force, even if it's bad. * * input : char *partition_name: partition to be erase * * other : No *****************************************************************************/ void flash_erase_force(char *partition_name) { unsigned i = 0; unsigned ret = ERROR; unsigned block_start = 0; unsigned block_end= 0; struct nand_spec spec; struct ptentry *ptn = NULL; ret = nand_get_spec(&spec); if(ret) { cprintf("ERROR: nand get spec failed!\n"); goto EXIT; } partition_name = bsp_nand_argument_check(partition_name); if(NULL == partition_name) { cprintf("ERROR: no partition name!\n"); goto EXIT; } ptn = flash_find_ptn(partition_name); if(!ptn) { cprintf("ERROR: wrong partition name: %s\n", partition_name); goto EXIT; } /* coverity[uninit_use] */ block_start = (ptn->start + spec.blocksize- 1) / spec.blocksize; block_end = (ptn->start + ptn->length + spec.blocksize - 1) / spec.blocksize; for (i = block_start; i < block_end; i++) { ret = nand_erase(i); if(ret) { cprintf("ERROR: nand erase error, block id = %d, ret = %d.\n", i, ret); } } cprintf("Erase %s force finished!\n", partition_name); return; EXIT: cprintf("ret = 0x%x!\n", ret); return; }
/***************************************************************************** * name : flash_erase * * description : Erase nand block * * input : ptentry *ptn: partition to be erase * * return : NANDF_OK: erase OK * NANDF_ERROR_INIT: Init failed * NANDF_ERROR_ARGS: Input error * NANDF_BAD_BLOCK: the block to be erase is a bad block * NANDF_ERROR_ERASE: erase failed, and mark the block as a bad block * NANDF_ERROR_ERASE_MARKBAD: erase failed, and mark bad block failed * NANDF_ERROR_SEMTAKE: apply semphore failed * NANDF_ERROR_SEMGIVE: release semphore failed * * other : No *****************************************************************************/ int flash_erase(ptentry *ptn) { int ret = ERROR; unsigned i = 0; unsigned block_start = 0; unsigned block_end= 0; unsigned bad_flag; struct nand_spec spec; ret = nand_get_spec(&spec); if(ret) { cprintf("ERROR: nand get spec failed!\n"); return ERROR; } /* coverity[uninit_use] */ block_start = (ptn->start + spec.blocksize- 1) / spec.blocksize; block_end = (ptn->start + ptn->length + spec.blocksize - 1) / spec.blocksize; for (i = block_start; i < block_end; i++) { ret = (s32)nand_isbad(i, &bad_flag); if(NANDC_OK != ret || NANDC_BAD_BLOCK == bad_flag) { cprintf("block %d is bad, not erase, ret=%x\n", i, ret); continue; } ret = (s32)nand_erase(i); if(ret) { cprintf("erase block %d failed, ret=%x\n", i, ret); } } return OK; }
/** * 作用:nandc模块提供对外扫描坏块的函数接口 * * 参数: * @start ---flash开始的地址 * @length ---扫描的长度 * @if_erase ---如果检测是好块根据此参数来决定是否擦除此块 * 描述:扫描flash是否是坏块,根据参数来决定是否擦除 */ u32 nand_scan_bad(FSZ start, FSZ length, u32 if_erase) { u32 addr_block_align; u32 length_block_align; u32 blk_id, is_bad, times, ret; struct nand_spec spec; /*因为是在fastboot中实现,内存的释放是没有实现的,使用静态变量表示一次分配以后都不分配了*/ static u32 block_buf = 0 ; memset(&spec, 0, sizeof(struct nand_spec)); /*通过此函数得到nandflash的规格参数,知道blocksize的大小*/ if(NAND_OK != nand_get_spec(&spec)) { NAND_TRACE(("nand_scan_bad: nand_get_spec failed\n")); return NAND_ERROR; } /*扫描块时要块对齐*/ addr_block_align = start - start%(spec.blocksize); /*得到要扫描的块长度*/ length_block_align = nandc_alige_size(start + length, spec.blocksize) - addr_block_align; /*如果没有分配内存就分配内存*/ if(!block_buf) { block_buf = (u32)himalloc(spec.blocksize); if(NULL == (void*)block_buf)//pclint 58 { NAND_TRACE(("nand_scan_bad: himalloc failed\n")); goto ERRO; } } /*还有块长度需要扫描*/ while(length_block_align > 0) { /*得到块号地址*/ blk_id = addr_block_align/spec.blocksize; if(NAND_OK != nand_isbad(blk_id, &is_bad)) { NAND_TRACE(("nand_scan_bad: nand_isbad failed\n")); goto ERRO; } if(NANDC_GOOD_BLOCK == is_bad) { times = 1; /*读整块数据如果没有出错的话表示是好坏*/ while((NANDC_E_READ == nand_read((FSZ)addr_block_align, block_buf, spec.blocksize, 0)) && (times)) { times--; } if(0 == times) { NAND_TRACE(("nand_scan_bad: find and read error, address:0x%x\n",addr_block_align)); ret = nand_bad(blk_id); if(ret) { NAND_TRACE(("nand_scan_bad:nand check bad failed, ret = 0x%x\n",ret)); } } /*是好块如果要擦除的话就擦除*/ else if(NANDC_TRUE == if_erase) { ret = nand_erase(blk_id); if(ret) { NAND_TRACE(("nand_scan_bad:nand erase failed, ret = 0x%x\n",ret)); } } else { } } else { NAND_TRACE(("nand_scan_bad:find bad block: 0x%x\n",addr_block_align)); } length_block_align -= spec.blocksize; addr_block_align += spec.blocksize; } return NAND_OK; ERRO: return NAND_ERROR; }