/** * \brief process bad block: erase bad block, mark it as 'bad' and put the node to bad block list. * \param[in] dev uffs device * \param[in] node bad block tree node (before the block turn 'bad', it must belong to something ...) */ void uffs_BadBlockProcess(uffs_Device *dev, TreeNode *node) { if (HAVE_BADBLOCK(dev)) { // mark the bad block uffs_FlashMarkBadBlock(dev, dev->bad.block); // and put it into bad block list if (node != NULL) uffs_TreeInsertToBadBlockList(dev, node); //clear bad block mark. dev->bad.block = UFFS_INVALID_BLOCK; } }
static void _ForceFormatAndCheckBlock(uffs_Device *dev, int block) { int i, j; uffs_Buf *buf = NULL; UBOOL bad = U_TRUE; URET ret; struct uffs_FlashOpsSt *ops = dev->ops; struct uffs_TagStoreSt ts; u8 *spare = NULL; buf = uffs_BufClone(dev, NULL); if (buf == NULL) { uffs_Perror(UFFS_MSG_SERIOUS, "Alloc page buffer fail ! Format stoped."); goto ext; } spare = (u8 *)uffs_PoolGet(SPOOL(dev)); if (spare == NULL) goto ext; //step 1: Erase, fully fill with 0x0, and check ret = uffs_FlashEraseBlock(dev, block); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; memset(buf->header, 0, dev->com.pg_size); memset(&ts, 0, sizeof(ts)); memset(spare, 0, dev->attr->spare_size); for (i = 0; i < dev->attr->pages_per_block; i++) { if (ops->WritePageWithLayout) ret = ops->WritePageWithLayout(dev, block, i, buf->header, dev->com.pg_size, NULL, &ts); else ret = ops->WritePage(dev, block, i, buf->header, dev->com.pg_size, spare, dev->attr->spare_size); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; } for (i = 0; i < dev->attr->pages_per_block; i++) { memset(buf->header, 0xFF, dev->com.pg_size); memset(&ts, 0xFF, sizeof(ts)); memset(spare, 0xFF, dev->attr->spare_size); if (ops->ReadPageWithLayout) { ret = ops->ReadPageWithLayout(dev, block, i, buf->header, dev->com.pg_size, NULL, &ts, NULL); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; for (j = 0; j < dev->com.pg_size; j++) if (buf->header[j] != 0) goto bad_out; for (j = 0; j < sizeof(ts); j++) if (((u8 *)&ts)[j] != 0) goto bad_out; } else { ret = ops->ReadPage(dev, block, i, buf->header, dev->com.pg_size, NULL, spare, dev->attr->spare_size); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; for (j = 0; j < dev->com.pg_size; j++) if (buf->header[j] != 0) goto bad_out; for (j = 0; j < dev->attr->spare_size; j++) if (spare[j] != 0) goto bad_out; } } //step 2: Erase, and check ret = uffs_FlashEraseBlock(dev, block); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; for (i = 0; i < dev->attr->pages_per_block; i++) { memset(buf->header, 0, dev->com.pg_size); memset(&ts, 0, sizeof(ts)); memset(spare, 0, dev->attr->spare_size); if (ops->ReadPageWithLayout) { ret = ops->ReadPageWithLayout(dev, block, i, buf->header, dev->com.pg_size, NULL, &ts, NULL); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; for (j = 0; j < dev->com.pg_size; j++) if (buf->header[j] != 0xFF) goto bad_out; for (j = 0; j < sizeof(ts); j++) if (((u8 *)&ts)[j] != 0xFF) goto bad_out; } else { ret = ops->ReadPage(dev, block, i, buf->header, dev->com.pg_size, NULL, spare, dev->attr->spare_size); if (UFFS_FLASH_IS_BAD_BLOCK(ret)) goto bad_out; for (j = 0; j < dev->com.pg_size; j++) if (buf->header[j] != 0xFF) goto bad_out; for (j = 0; j < dev->attr->spare_size; j++) if (spare[j] != 0xFF) goto bad_out; } } // format succ bad = U_FALSE; bad_out: if (bad == U_TRUE) uffs_FlashMarkBadBlock(dev, block); ext: if (buf) uffs_BufFreeClone(dev, buf); if (spare) uffs_PoolPut(SPOOL(dev), spare); return; }