Example #1
0
byte UFFS_PrintDiskInfo(const CLS1_StdIOType *io)
{
	uffs_MountTable *m;
	//uffs_Device *d;
	int i, b = 0, g = 0;
	MSGLN("UFFS disk info:");
	m = get_flash_mount_table();
	while (m->dev)
	{
		MSGLN("Mount point: %s, start: %d, end: %d",
				m->mount, m->start_block, m->end_block);
		MSGLN("Space: %ld Used: %ld Free: %ld",
				uffs_space_total(m->mount), 
				uffs_space_used(m->mount), 
				uffs_space_free(m->mount));
		for(i = m->start_block; i <= m->end_block; i++)
		{
			if(uffs_FlashIsBadBlock(m->dev, i))
				b++;
			else
				g++;
		}
		MSGLN("Blocks: %d good: %d bad: %d (%d %%)", m->end_block - m->start_block + 1, g, b, b*100/(b+g));
		m++;
	}

	return ERR_OK;
}
static void DumpBlock(struct uffs_DeviceSt *dev, int block, dump_msg_cb *dump)
{
	int i;
	struct uffs_StorageAttrSt *attr = dev->attr;
	uffs_Tags tag;
	URET ret;

	dump(dev, "--- Block %d ---\n", block);

	if (uffs_FlashIsBadBlock(dev, block)) {
		dump(dev, "Bad block\n\n");
		return;
	}

	for (i = 0; i < attr->pages_per_block; i++) {

		memset(&tag, 0xFF, sizeof(tag));
		ret = uffs_FlashReadPageTag(dev, block, i, &tag);

		if (ret == UFFS_FLASH_IO_ERR) {
			dump(dev, "page %d tag I/O error\n", i);
			continue;
		}
		else if (ret == UFFS_FLASH_ECC_FAIL) {
			dump(dev, "page %d tag ECC error\n", i);
			continue;
		}
		else if (ret == UFFS_FLASH_NO_ERR || ret == UFFS_FLASH_ECC_OK) {
			if (ret == UFFS_FLASH_ECC_OK)
				dump(dev, "page %d tag has bit flip, corrected by ECC\n", i);

			if (DumpTag(dev, block, i, &tag, dump) == 0)
				continue;
			else
				break;
		}
		else {
			dump(dev, "read page %d tag return unexpected: %d\n", i, ret);
			continue;
		}
	}
	dump(dev, "\n");
}
URET uffs_FormatDevice(uffs_Device *dev, UBOOL force)
{
	u16 i, slot;
	URET ret = U_SUCC;
	
	if (dev == NULL)
		return U_FAIL;

	if (dev->ops == NULL) 
		return U_FAIL;

	uffs_GlobalFsLockLock();

	ret = uffs_BufFlushAll(dev);

	if (dev->ref_count > 1 && !force) {
		uffs_Perror(UFFS_MSG_NORMAL,
					"can't format when dev->ref_count = %d",
					dev->ref_count);
		ret = U_FAIL;
	}

	if (ret == U_SUCC && force) {
		uffs_DirEntryBufPutAll(dev);
		uffs_PutAllObjectBuf(dev);
		uffs_FdSignatureIncrease();
	}

	if (ret == U_SUCC &&
		uffs_BufIsAllFree(dev) == U_FALSE &&
		!force)
	{
		uffs_Perror(UFFS_MSG_NORMAL, "some page still in used!");
		ret = U_FAIL;
	}

	if (!force) {
		for (slot = 0; ret == U_SUCC && slot < dev->cfg.dirty_groups; slot++) {
			if (dev->buf.dirtyGroup[slot].count > 0) {
				uffs_Perror(UFFS_MSG_SERIOUS, "there still have dirty pages!");
				ret = U_FAIL;
			}
		}
	}

	if (ret == U_SUCC)
		uffs_BufSetAllEmpty(dev);


	if (ret == U_SUCC && uffs_BlockInfoIsAllFree(dev) == U_FALSE && !force) {
		uffs_Perror(UFFS_MSG_NORMAL,
					"there still have block info cache ? fail to format");
		ret = U_FAIL;
	}

	if (ret == U_SUCC)
		uffs_BlockInfoExpireAll(dev);

	for (i = dev->par.start; ret == U_SUCC && i <= dev->par.end; i++) {
		if (uffs_FlashIsBadBlock(dev, i) == U_FALSE) {
			uffs_FlashEraseBlock(dev, i);
			if (HAVE_BADBLOCK(dev))
				uffs_BadBlockProcess(dev, NULL);
		}
		else {
#ifdef CONFIG_ENABLE_BAD_BLOCK_VERIFY
			_ForceFormatAndCheckBlock(dev, i);
#endif
		}
	}

	if (ret == U_SUCC && uffs_TreeRelease(dev) == U_FAIL) {
		ret = U_FAIL;
	}

	if (ret == U_SUCC && uffs_TreeInit(dev) == U_FAIL) {
		ret = U_FAIL;
	}

	if (ret == U_SUCC && uffs_BuildTree(dev) == U_FAIL) {
		ret = U_FAIL;
	}

	uffs_GlobalFsLockUnlock();

	return ret;
}
Example #4
0
static URET _BuildTreeStepOne(uffs_Device *dev)
{
	int block_lt;
	uffs_BlockInfo *bc = NULL;
	TreeNode *node;
	struct uffs_TreeSt *tree;
	uffs_Pool *pool;
	struct uffs_MiniHeaderSt header;
	URET ret = U_SUCC;
	struct BlockTypeStatSt st = {0, 0, 0};
	
	tree = &(dev->tree);
	pool = TPOOL(dev);

	tree->bad = NULL;
	tree->bad_count = 0;
	tree->erased = NULL;
	tree->erased_tail = NULL;
	tree->erased_count = 0;

	uffs_Perror(UFFS_MSG_NOISY, "build tree step one");

//	printf("s:%d e:%d\n", dev->par.start, dev->par.end);
	for (block_lt = dev->par.start; block_lt <= dev->par.end; block_lt++) {
		bc = uffs_BlockInfoGet(dev, block_lt);
		if (bc == NULL) {
			uffs_Perror(UFFS_MSG_SERIOUS, "step one:fail to get block info");
			ret = U_FAIL;
			break;
		}
		node = (TreeNode *)uffs_PoolGet(pool);
		if (node == NULL) {
			uffs_Perror(UFFS_MSG_SERIOUS, "insufficient tree node!");
			ret = U_FAIL;
			break;
		}

		// Need to check bad block at first !
		if (uffs_FlashIsBadBlock(dev, block_lt) == U_TRUE) {
			node->u.list.block = block_lt;
			uffs_TreeInsertToBadBlockList(dev, node);
			uffs_Perror(UFFS_MSG_NORMAL, "found bad block %d", block_lt);
		}
		else if (uffs_IsPageErased(dev, bc, 0) == U_TRUE) { //@ read one spare: 0
			// page 0 tag shows it's an erased block, we need to check the mini header status to make sure it is clean.
			if (uffs_LoadMiniHeader(dev, block_lt, 0, &header) == U_FAIL) {
				uffs_Perror(UFFS_MSG_SERIOUS,
							"I/O error when reading mini header !"
							"block %d page %d",
							block_lt, 0);
				ret = U_FAIL;
				break;
			}

			if (header.status != 0xFF) {
				// page 0 tag is clean but page data is dirty ???
				// this block should be erased immediately !
				uffs_FlashEraseBlock(dev, block_lt);
			}
			node->u.list.block = block_lt;
			if (HAVE_BADBLOCK(dev)) {
				uffs_Perror(UFFS_MSG_NORMAL,
							"New bad block (%d) discovered.", block_lt);
				uffs_BadBlockProcess(dev, node);
			}
			else {
				// page 0 is clean does not means all pages in this block are clean,
				// need to check this block later before use it.
				uffs_TreeInsertToErasedListTailEx(dev, node, 1);
			}
		}
		else {
			
			// this block have valid data page(s).

			ret = _ScanAndFixUnCleanPage(dev, bc);
			if (ret == U_FAIL)
				break;

			ret = _BuildValidTreeNode(dev, node, bc, &st);
			if (ret == U_FAIL)
				break;

		}
		uffs_BlockInfoPut(dev, bc);
	} //end of for

	if(ret == U_FAIL) 
		uffs_BlockInfoPut(dev, bc);

	uffs_Perror(UFFS_MSG_NORMAL,
				"DIR %d, FILE %d, DATA %d", st.dir, st.file, st.data);

	return ret;
}