/** 
 * \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;
}