예제 #1
0
/*
 * 函数功能: 创建一个文件
 * 输入参数: 文件名称
 * 返回参数: 
 */
int uffs_mkfile(const char *name)
{
	uffs_Object *fp;
	int ret = 0;
	int err = 0;

	fp = uffs_GetObject();	

	if(fp != NULL) 
	{
		if(uffs_CreateObject(fp, name, UO_CREATE) != U_SUCC) 
		{
			err = fp->err;
			ret = -1;
			uffs_Perror(UFFS_ERR_NORMAL, "Create %s fail, err: %d", name, uffs_get_error());
		}
		else 
		{
			uffs_Perror(UFFS_ERR_NORMAL, "Create %s succ.", name);
			uffs_CloseObject(fp);
			ret = 0;
		}
		uffs_PutObject(fp);
	}
	else 
	{
		err = UEMFILE;
		ret = -1;
	}
	
	uffs_set_error(-err);
	return ret;
}
예제 #2
0
파일: uffs_tree.c 프로젝트: mazj/uffs
/** compare [name] with tree [node] represented object name by loading
	uffs_FileInfo from storage */
UBOOL uffs_TreeCompareFileName(uffs_Device *dev,
							   const char *name, u32 len, u16 sum,
							   TreeNode *node, int type)
{
	UBOOL matched = U_FALSE;
	uffs_FileInfo *fi;
	uffs_Buf *buf;
	u16 data_sum;

	buf = uffs_BufGetEx(dev, type, node, 0, 0);
	if (buf == NULL) {
		uffs_Perror(UFFS_MSG_SERIOUS, "can't get buf !\n ");
		goto ext;
	}
	fi = (uffs_FileInfo *)(buf->data);
	data_sum = uffs_MakeSum16(fi->name, fi->name_len);

	if (data_sum != sum) {
		uffs_Perror(UFFS_MSG_NORMAL,
					"the obj's sum in storage is different with given sum!");
		goto ext;
	}

	if (fi->name_len == len) {
		if(uffs_CompareFileName(fi->name, fi->name_len, name) == U_TRUE) {
			matched = U_TRUE;
		}
	}
ext:
	if (buf)
		uffs_BufPut(dev, buf);

	return matched;
}
예제 #3
0
파일: uffs_tree.c 프로젝트: mazj/uffs
/** 
 * \brief build tree structure from flash
 * \param[in] dev uffs device
 */
URET uffs_BuildTree(uffs_Device *dev)
{
	URET ret;

	/***** step one: scan all page spares, classify DIR/FILE/DATA nodes,
		check bad blocks/uncompleted(conflicted) blocks as well *****/

	/* if the disk is big and full filled of data this step could be
		the most time consuming .... */

	ret = _BuildTreeStepOne(dev);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_MSG_SERIOUS, "build tree step one fail!");
		return ret;
	}

	/***** step two: randomize the erased blocks, for ware-leveling purpose *****/
	/* this step is very fast :) */
	ret = _BuildTreeStepTwo(dev);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_MSG_SERIOUS, "build tree step two fail!");
		return ret;
	}

	/***** step three: check DATA nodes, find orphan nodes and erase them *****/
	/* if there are a lot of files and disk is fully filled, this step 
		could be very time consuming ... */
	ret = _BuildTreeStepThree(dev);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_MSG_SERIOUS, "build tree step three fail!");
		return ret;
	}
	
	return U_SUCC;
}
예제 #4
0
/*
 * 函数功能: 格式化分区
 * 输入参数: 分区名称
 * 返回参数: 
 */
int uffs_format(const char *name)
{
	int ret;
	const char *mount = "/";
	uffs_Device *dev;

	if(name) 
	{
		mount = name;
	}

	dev = uffs_GetDeviceFromMountPoint(mount);
	if(dev == NULL) 
	{
		uffs_Perror(UFFS_ERR_NORMAL, "Can't get device from mount point.");
	}
	else 
	{
		if(dev->ref_count == 1) 
		{
			ret = uffs_FormatDevice(dev);
			uffs_Perror(UFFS_ERR_NORMAL, "Format %s.",ret==RT_EOK?"succ":"fail");
		}
		else 
		{
			uffs_Perror(UFFS_ERR_NORMAL, "dev->ref_count: %d, can't format this device.", dev->ref_count);
		}
		uffs_PutDevice(dev);
	}
	return TRUE;	
}
예제 #5
0
파일: uffs_tree.c 프로젝트: mazj/uffs
/* calculate file length, etc */
static URET _BuildTreeStepThree(uffs_Device *dev)
{
	int i;
	u16 x;
	TreeNode *work;
	TreeNode *node;
	struct uffs_TreeSt *tree;
	uffs_Pool *pool;
	u16 blockSave;

	TreeNode *cache = NULL;
	u16 cacheSerial = INVALID_UFFS_SERIAL;

	tree = &(dev->tree);
	pool = TPOOL(dev);

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

	for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) {
		x = tree->data_entry[i];
		while (x != EMPTY_NODE) {
			work = FROM_IDX(x, pool);
			if (work->u.data.parent == cacheSerial) {
				node = cache;
			}
			else {
				node = uffs_TreeFindFileNode(dev, work->u.data.parent);
				cache = node;
				cacheSerial = work->u.data.parent;
			}
			if (node == NULL) {
				x = work->hash_next;
				//this data block does not belong to any file ?
				//should be erased.
				uffs_Perror(UFFS_MSG_NORMAL,
					"find a orphan data block:%d, "
					"parent:%d, serial:%d, will be erased!",
					work->u.data.block,
					work->u.data.parent, work->u.data.serial);

				uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, work);
				blockSave = work->u.data.block;
				work->u.list.block = blockSave;
				uffs_FlashEraseBlock(dev, blockSave);
				if (HAVE_BADBLOCK(dev))
					uffs_BadBlockProcess(dev, work);
				else
					uffs_TreeInsertToErasedListTail(dev, work);
			}
			else {
				node->u.file.len += work->u.data.len;
				x = work->hash_next;
			}
		}
	}

	return U_SUCC;
}
예제 #6
0
파일: uffs_fs.c 프로젝트: mazj/uffs
/**
 * \brief check if there are anyone holding buf of this obj.
 *        If no one holding the buffers, expire the buffer.
 * \return
 *		0	: no one holding any buf of this obj
 *		>0	: the ref_count of buf which refer to this obj.
 */
int _CheckObjBufRef(uffs_Object *obj)
{
	uffs_Device *dev = obj->dev;
	uffs_Buf *buf;
	TreeNode *node = obj->node;
	u16 parent, serial, last_serial;

	// check the DIR or FILE block
	for (buf = uffs_BufFind(dev, obj->parent, obj->serial, UFFS_ALL_PAGES);
		 buf != NULL;
		 buf = uffs_BufFindFrom(dev, buf->next, obj->parent, obj->serial, UFFS_ALL_PAGES))
	{
		if (buf->ref_count > 0) {
			// oops ...
			uffs_Perror(UFFS_MSG_SERIOUS, "someone still hold buf parent = %d, serial = %d, ref_count",
				obj->parent, obj->serial, buf->ref_count);

			return buf->ref_count;
		}
		else {
			buf->mark = UFFS_BUF_EMPTY;
		}
	}

	if (buf == NULL || buf->ref_count == 0) {
		// check the DATA block
		if (obj->type == UFFS_TYPE_FILE && node->u.file.len > 0) {

			parent = obj->serial;
			last_serial = GetFdnByOfs(obj, node->u.file.len - 1);
			for (serial = 1; serial <= last_serial; serial++) {

				for (buf = uffs_BufFind(dev, parent, serial, UFFS_ALL_PAGES);
					 buf != NULL;
					 buf = uffs_BufFindFrom(dev, buf->next, parent, serial, UFFS_ALL_PAGES))
				{
					if (buf->ref_count != 0) {
						// oops ...
						uffs_Perror(UFFS_MSG_SERIOUS, "someone still hold buf parent = %d, serial = %d, ref_count",
							parent, serial, buf->ref_count);

						return buf->ref_count;
					}
					else {
						buf->mark = UFFS_BUF_EMPTY;
					}
				}
			}
		}
	}

	return 0;
}
예제 #7
0
파일: uffs_tree.c 프로젝트: mazj/uffs
/** 
 * \brief initialize tree buffers
 * \param[in] dev uffs device
 */
URET uffs_TreeInit(uffs_Device *dev)
{
	int size;
	int num;
	uffs_Pool *pool;
	int i;

	size = sizeof(TreeNode);
	num = dev->par.end - dev->par.start + 1;
	
	pool = &(dev->mem.tree_pool);

	if (dev->mem.tree_nodes_pool_size == 0) {
		if (dev->mem.malloc) {
			dev->mem.tree_nodes_pool_buf = dev->mem.malloc(dev, size * num);
			if (dev->mem.tree_nodes_pool_buf)
				dev->mem.tree_nodes_pool_size = size * num;
		}
	}
	if (size * num > dev->mem.tree_nodes_pool_size) {
		uffs_Perror(UFFS_MSG_DEAD,
					"Tree buffer require %d but only %d available.",
					size * num, dev->mem.tree_nodes_pool_size);
		memset(pool, 0, sizeof(uffs_Pool));
		return U_FAIL;
	}
	uffs_Perror(UFFS_MSG_NOISY, "alloc tree nodes %d bytes.", size * num);
	
	uffs_PoolInit(pool, dev->mem.tree_nodes_pool_buf,
					dev->mem.tree_nodes_pool_size, size, num, U_FALSE);

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

	for (i = 0; i < DIR_NODE_ENTRY_LEN; i++) {
		dev->tree.dir_entry[i] = EMPTY_NODE;
	}

	for (i = 0; i < FILE_NODE_ENTRY_LEN; i++) {
		dev->tree.file_entry[i] = EMPTY_NODE;
	}

	for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) {
		dev->tree.data_entry[i] = EMPTY_NODE;
	}

	dev->tree.max_serial = ROOT_DIR_SERIAL;
	
	return U_SUCC;
}
예제 #8
0
파일: uffs_tree.c 프로젝트: mazj/uffs
static URET _ScanAndFixUnCleanPage(uffs_Device *dev, uffs_BlockInfo *bc)
{
	int page;
	uffs_Tags *tag;
	struct uffs_MiniHeaderSt header;

	/* in most case, the valid block contents fewer free page,
		so it's better scan from the last page ... to page 1.
		note: scanning page 0 is not necessary, will check it later.

		The worse case: read (pages_per_block - 1) * (mini header + spares) !
		most case: read one spare.
	*/
	for (page = dev->attr->pages_per_block - 1; page > 0; page--) {
		uffs_BlockInfoLoad(dev, bc, page);
		tag = GET_TAG(bc, page);

		if (TAG_IS_SEALED(tag))
			break;	// tag sealed, no unclean page in this block.

		if (TAG_IS_DIRTY(tag) || TAG_IS_VALID(tag)) {  // tag not sealed but dirty/valid ?
			uffs_Perror(UFFS_MSG_NORMAL,
					"unclean page found, block %d page %d",
					bc->block, page);

			// ok, an unclean page found.
			// This unclean page can be identified by tag.
			// We can leave it as it is, but performing a block recover would be good ?
			// There won't be another unclean page in this block ... stop here.
			break;
		}

		// now we have a clean tag (all 0xFF ?). Need to check mini header to see if it's an unclean page.
		if (uffs_LoadMiniHeader(dev, bc->block, page, &header) == U_FAIL)
			return U_FAIL;

		if (header.status != 0xFF) {
			// page data is dirty? this is an unclean page and we should explicitly mark tag as 'dirty and invalid'.
			// This writing does not violate "no partial program" claim, because we are writing to a clean page spare.
			uffs_Perror(UFFS_MSG_NORMAL,
						"unclean page found, block %d page %d, mark it.",
						bc->block, page);
			uffs_FlashMarkDirtyPage(dev, bc, page);
		}
	}

	return U_SUCC;
}
예제 #9
0
URET uffs_InitDevice(uffs_Device *dev)
{
    URET ret;

    ret = uffs_InitDeviceConfig(dev);
    if (ret != U_SUCC)
        return U_FAIL;

    if (dev->mem.init) {
        if (dev->mem.init(dev) != U_SUCC) {
            uffs_Perror(UFFS_MSG_SERIOUS, "Init memory allocator fail.");
            return U_FAIL;
        }
    }

    memset(&(dev->st), 0, sizeof(uffs_FlashStat));

    uffs_DeviceInitLock(dev);
    uffs_BadBlockInit(dev);


    if (uffs_FlashInterfaceInit(dev) != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS, "Can't initialize flash interface !");
        goto fail;
    }

    uffs_Perror(UFFS_MSG_NOISY, "init page buf");
    ret = uffs_BufInit(dev, dev->cfg.page_buffers, dev->cfg.dirty_pages);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_DEAD, "Initialize page buffers fail");
        goto fail;
    }
    uffs_Perror(UFFS_MSG_NOISY, "init block info cache");
    ret = uffs_BlockInfoInitCache(dev, dev->cfg.bc_caches);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_DEAD, "Initialize block info fail");
        goto fail;
    }

    ret = uffs_TreeInit(dev);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS, "fail to init tree buffers");
        goto fail;
    }

    ret = uffs_BuildTree(dev);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS, "fail to build tree");
        goto fail;
    }

    return U_SUCC;

fail:
    uffs_DeviceReleaseLock(dev);

    return U_FAIL;
}
/** Mark this block as bad block */
URET uffs_FlashMarkBadBlock(uffs_Device *dev, int block)
{
	int ret;
	uffs_BlockInfo *bc;

	uffs_Perror(UFFS_MSG_NORMAL, "Mark bad block: %d", block);

	bc = uffs_BlockInfoGet(dev, block);
	if (bc) {
		uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES);	// expire this block, just in case it's been cached before
		uffs_BlockInfoPut(dev, bc);
	}

	if (dev->ops->MarkBadBlock)
		return dev->ops->MarkBadBlock(dev, block) == 0 ? U_SUCC : U_FAIL;

#ifdef CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD
	ret = dev->ops->EraseBlock(dev, block);
	if (ret != UFFS_FLASH_IO_ERR) {
		// note: even EraseBlock return UFFS_FLASH_BAD_BLK,
		//			we still process it ... not recommended for most NAND flash.
#endif
	if (dev->ops->WritePageWithLayout)
		ret = dev->ops->WritePageWithLayout(dev, block, 0, NULL, 0, NULL, NULL);
	else
		ret = dev->ops->WritePage(dev, block, 0, NULL, 0, NULL, 0);

#ifdef CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD
	}
#endif

	return ret == UFFS_FLASH_NO_ERR ? U_SUCC : U_FAIL;
}
예제 #11
0
/*
 * Release resources
 */
int femu_ReleaseFlash(uffs_Device *dev)
{
	uffs_FileEmu *emu;

	emu = (uffs_FileEmu *)(dev->attr->_private);

	emu->initCount--;

	if (emu->initCount == 0) {

		uffs_Perror(UFFS_ERR_NORMAL,  "femu device release.");

		if (emu->fp) {
			fclose(emu->fp);
			emu->fp = NULL;
		}

		if (emu->em_monitor_page)
			free(emu->em_monitor_page);
		if (emu->em_monitor_spare) 
			free(emu->em_monitor_spare);
		emu->em_monitor_page = NULL;
		emu->em_monitor_spare = NULL;
	}

	return 0;
}
예제 #12
0
/**
 * \brief Find a cached block in cache pool,
 *			if the cached block exist then return the pointer,
 *			if the block does not cached already, find a non-used cache.
 *			if all of cached are used out, return NULL.
 * \param[in] dev uffs device
 * \param[in] block block number to be found
 * \return found block cache buffer
 * \retval NULL caches used out
 * \retval non-NULL buffer pointer of given block
 */
uffs_BlockInfo * uffs_BlockInfoGet(uffs_Device *dev, int block)
{
    uffs_BlockInfo *work;
    int i;

    //search cached block
    if ((work = uffs_BlockInfoFindInCache(dev, block)) != NULL) {
        _MoveBcToTail(dev, work);
        return work;
    }

    //can't find block from cache, need to find a free(unlocked) cache
    for (work = dev->bc.head; work != NULL; work = work->next) {
        if(work->ref_count == 0) break;
    }
    if (work == NULL) {
        //caches used out !
        uffs_Perror(UFFS_MSG_SERIOUS,  "insufficient block info cache");
        return NULL;
    }

    work->block = block;
    work->expired_count = dev->attr->pages_per_block;
    for (i = 0; i < dev->attr->pages_per_block; i++) {
        work->spares[i].expired = 1;

        // TODO: init tag
    }

    work->ref_count = 1;

    _MoveBcToTail(dev, work);

    return work;
}
예제 #13
0
파일: uffs_public.c 프로젝트: mihadyuk/uffs
/** 
 * create a new file on a free block
 * \param[in] dev uffs device
 * \param[in] parent parent dir serial num
 * \param[in] serial serial num of this new file
 * \param[in] bc block information
 * \param[in] fi file information
 * \note parent, serial, bc must be provided before,
 *		 and all information in fi should be filled well before.
 */
URET uffs_CreateNewFile(uffs_Device *dev,
						u16 parent, u16 serial,
						uffs_BlockInfo *bc, uffs_FileInfo *fi)
{
	uffs_Tags *tag;
	uffs_Buf *buf;

	uffs_BlockInfoLoad(dev, bc, 0);

	tag = GET_TAG(bc, 0);
	TAG_PARENT(tag) = parent;
	TAG_SERIAL(tag) = serial;
	TAG_DATA_LEN(tag) = sizeof(uffs_FileInfo);

	buf = uffs_BufGet(dev, parent, serial, 0);
	if (buf == NULL) {
		uffs_Perror(UFFS_MSG_SERIOUS, "get buf fail.");
		return U_FAIL;
	}

	memcpy(buf->data, fi, TAG_DATA_LEN(tag));
	buf->data_len = TAG_DATA_LEN(tag);

	return uffs_BufPut(dev, buf);
}
예제 #14
0
static URET femu_releaseDevice(uffs_Device *dev)
{
	uffs_FileEmu *emu;

	uffs_Perror(UFFS_ERR_NORMAL,  "femu device release.");

	emu = (uffs_FileEmu *)(dev->attr->_private);

	emu->initCount--;
	if (emu->initCount == 0) {
		if (emu->fp) {
			fclose(emu->fp);
			emu->fp = NULL;
		}

		memset(emu, 0, sizeof(uffs_FileEmu));

		if (emu->em_monitor_page)
			free(emu->em_monitor_page);
		if (emu->em_monitor_spare) 
			free(emu->em_monitor_spare);
		emu->em_monitor_page = NULL;
		emu->em_monitor_spare = NULL;
	}

	return U_SUCC;
}
예제 #15
0
파일: uffs_fs.c 프로젝트: mazj/uffs
/**
 * write data to obj, from obj->pos
 *
 * \param[in] obj file obj
 * \param[in] data data pointer
 * \param[in] len length of data to be write
 *
 * \return bytes wrote to obj
 */
int uffs_WriteObject(uffs_Object *obj, const void *data, int len)
{
	uffs_Device *dev = obj->dev;
	TreeNode *fnode = NULL;
	int remain;
	u32 pos;
	int wrote = 0;

	if (obj == NULL) 
		return 0;

	if (obj->dev == NULL || obj->open_succ != U_TRUE) {
		obj->err = UEBADF;
		return 0;
	}

	if (obj->type == UFFS_TYPE_DIR) {
		uffs_Perror(UFFS_MSG_NOISY, "Can't write to an dir object!");
		obj->err = UEACCES;
		return 0;
	}

	if (obj->oflag == UO_RDONLY) {
		obj->err = UEACCES;  // can't write to 'read only' mode opened file
		return 0;
	}

	fnode = obj->node;

	uffs_ObjectDevLock(obj);

	if (obj->oflag & UO_APPEND)
		obj->pos = fnode->u.file.len;
	else {
		if (obj->pos > fnode->u.file.len) {
			// current pos pass over the end of file, need to fill the gap with '\0'
			pos = obj->pos;	// save desired pos
			obj->pos = fnode->u.file.len; // filling gap from the end of the file.
			remain = do_WriteObject(obj, NULL, pos - fnode->u.file.len);  // Write filling bytes. Note: the filling data does not count as 'wrote' in this write operation.
			obj->pos = pos - remain;
			if (remain > 0)	// fail to fill the gap ? stop.
				goto ext;
		}
	}

	remain = do_WriteObject(obj, data, len);
	wrote = len - remain;
	obj->pos += wrote;

ext:
	if (HAVE_BADBLOCK(dev))
		uffs_BadBlockRecover(dev);

	uffs_ObjectDevUnLock(obj);

	uffs_Assert(fnode == obj->node, "obj->node change!\n");

	return wrote;
}
예제 #16
0
/**
 * \brief load page spare data to given block info structure
 *			with given page number
 * \param[in] dev uffs device
 * \param[in] work given block info to be filled with
 * \param[in] page given page number to be read from,
 *			  if #UFFS_ALL_PAGES is presented, it will read
 *			  all pages, otherwise it will read only one given page.
 * \return load result
 * \retval U_SUCC successful
 * \retval U_FAIL fail to load
 * \note work->block must be set before load block info
 */
URET uffs_BlockInfoLoad(uffs_Device *dev, uffs_BlockInfo *work, int page)
{
    int i, ret;
    uffs_PageSpare *spare;

    if (page == UFFS_ALL_PAGES) {
        for (i = 0; i < dev->attr->pages_per_block; i++) {
            spare = &(work->spares[i]);
            if (spare->expired == 0)
                continue;

            ret = uffs_FlashReadPageTag(dev, work->block, i,
                                        &(spare->tag));
            if (UFFS_FLASH_HAVE_ERR(ret)) {
                uffs_Perror(UFFS_MSG_SERIOUS,
                            "load block %d page %d spare fail.",
                            work->block, i);
                return U_FAIL;
            }
            spare->expired = 0;
            work->expired_count--;
        }
    }
    else {
        if (page < 0 || page >= dev->attr->pages_per_block) {
            uffs_Perror(UFFS_MSG_SERIOUS, "page out of range !");
            return U_FAIL;
        }
        spare = &(work->spares[page]);
        if (spare->expired != 0) {
            ret = uffs_FlashReadPageTag(dev, work->block, page,
                                        &(spare->tag));
            if (UFFS_FLASH_HAVE_ERR(ret)) {
                uffs_Perror(UFFS_MSG_SERIOUS,
                            "load block %d page %d spare fail.",
                            work->block, page);
                return U_FAIL;
            }
            spare->expired = 0;
            work->expired_count--;
        }
    }
    return U_SUCC;
}
예제 #17
0
static URET femu_initDevice(uffs_Device *dev)
{
	uffs_Perror(UFFS_ERR_NORMAL,  "femu device init.");

	dev->ops = &emu_flash_ops;							/* EMU device operations */

	CheckInit(dev);

	return U_SUCC;
}
/** put a new block to the bad block waiting list */
void uffs_BadBlockAdd(uffs_Device *dev, int block)
{
	if (dev->bad.block == block)
		return;

	if (dev->bad.block != UFFS_INVALID_BLOCK)
		uffs_Perror(UFFS_ERR_SERIOUS, "Can't add more then one bad block !");
	else
		dev->bad.block = block;
}
예제 #19
0
URET uffs_InitDevice(uffs_Device *dev)
{
	URET ret;

	if (dev->mem.init) {
		if (dev->mem.init(dev) != U_SUCC) {
			uffs_Perror(UFFS_ERR_SERIOUS, "Init memory allocator fail.");
			return U_FAIL;
		}
	}

	memset(&(dev->st), 0, sizeof(uffs_FlashStat));

	uffs_DeviceInitLock(dev);
	uffs_BadBlockInit(dev);

	if (uffs_FlashInterfaceInit(dev) != U_SUCC) {
		uffs_Perror(UFFS_ERR_SERIOUS, "Can't initialize flash interface !");
		goto fail;
	}

	uffs_Perror(UFFS_ERR_NOISY, "init page buf");
	ret = uffs_BufInit(dev, MAX_PAGE_BUFFERS, MAX_DIRTY_PAGES_IN_A_BLOCK);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_ERR_DEAD, "Initialize page buffers fail");
		goto fail;
	}
	uffs_Perror(UFFS_ERR_NOISY, "init block info cache");
	ret = uffs_BlockInfoInitCache(dev, MAX_CACHED_BLOCK_INFO);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_ERR_DEAD, "Initialize block info fail");
		goto fail;
	}

	ret = uffs_TreeInit(dev);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_ERR_SERIOUS, "fail to init tree buffers");
		goto fail;
	}

	ret = uffs_BuildTree(dev);
	if (ret != U_SUCC) {
		uffs_Perror(UFFS_ERR_SERIOUS, "fail to build tree");
		goto fail;
	}

	return U_SUCC;

fail:
	uffs_DeviceReleaseLock(dev);

	return U_FAIL;
}
예제 #20
0
void uffs_DeviceUnLock(uffs_Device *dev)
{
	dev->lock.counter--;

	if (dev->lock.counter != 0) {
		uffs_Perror(UFFS_MSG_NORMAL,
					"Unlock device, counter %d NOT zero?!", dev->lock.counter);
	}
	
	uffs_SemSignal(dev->lock.sem);
}
예제 #21
0
파일: uffs_public.c 프로젝트: mihadyuk/uffs
UBOOL uffs_IsSrcNewerThanObj(int src, int obj)
{
	switch (src - obj) {
	case 0:
		uffs_Perror(UFFS_MSG_SERIOUS,
					"the two block have the same time stamp ?");
		break;
	case 1:
	case -2:
		return U_TRUE;
	case -1:
	case 2:
		return U_FALSE;
	default:
		uffs_Perror(UFFS_MSG_SERIOUS,  "time stamp out of range !");
		break;
	}

	return U_FALSE;
}
예제 #22
0
void uffs_DeviceLock(uffs_Device *dev)
{
	uffs_SemWait(dev->lock.sem);
	
	if (dev->lock.counter != 0) {
		uffs_Perror(UFFS_MSG_NORMAL,
					"Lock device, counter %d NOT zero?!", dev->lock.counter);
	}

	dev->lock.counter++;
}
예제 #23
0
URET uffs_InitMountTable(void)
{
	struct uffs_MountTableEntrySt *tbl = uffs_GetMountTable();
	struct uffs_MountTableEntrySt *work;
	int dev_num = 0;

	for (work = tbl; work; work = work->next) {
		uffs_Perror(UFFS_ERR_NOISY, "init device for mount point %s ...", work->mount);
		if (work->dev->Init(work->dev) == U_FAIL) {
			uffs_Perror(UFFS_ERR_SERIOUS, "init device for mount point %s fail", work->mount);
			return U_FAIL;
		}

		work->dev->par.start = work->start_block;
		if (work->end_block < 0) 
		{
			work->dev->par.end = work->dev->attr->total_blocks + work->end_block;
		}
		else 
		{
			work->dev->par.end = work->end_block;
		}
		uffs_Perror(UFFS_ERR_NOISY, "mount partiton: %d,%d",
			work->dev->par.start, work->dev->par.end);

		if (uffs_InitDevice(work->dev) != U_SUCC) 
		{
			uffs_Perror(UFFS_ERR_SERIOUS, "init device fail !");
			return U_FAIL;
		}
		work->dev->dev_num = dev_num++;
	}

	if (uffs_InitObjectBuf() == U_SUCC) {
		if (uffs_InitDirEntryBuf() == U_SUCC) {
			return U_SUCC;
		}
	}

	return U_FAIL;
}
예제 #24
0
URET uffs_ReleaseDevice(uffs_Device *dev)
{
    URET ret;

    ret = uffs_BlockInfoReleaseCache(dev);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS,  "fail to release block info.");
        goto ext;
    }

    ret = uffs_BufReleaseAll(dev);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS,  "fail to release page buffers");
        goto ext;
    }

    ret = uffs_TreeRelease(dev);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS, "fail to release tree buffers!");
        goto ext;
    }

    ret = uffs_FlashInterfaceRelease(dev);
    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS, "fail to release tree buffers!");
        goto ext;
    }

    if (dev->mem.release)
        ret = dev->mem.release(dev);

    if (ret != U_SUCC) {
        uffs_Perror(UFFS_MSG_SERIOUS, "fail to release memory allocator!");
    }

    uffs_DeviceReleaseLock(dev);

ext:
    return ret;

}
예제 #25
0
파일: uffs_buf.c 프로젝트: hmgle/rt-thread
/**
 * \brief flush all buffers
 */
URET uffs_BufFlushAll(struct uffs_DeviceSt *dev)
{
    int slot;
    for (slot = 0; slot < dev->cfg.dirty_groups; slot++) {
        if(_BufFlush(dev, FALSE, slot) != U_SUCC) {
            uffs_Perror(UFFS_MSG_NORMAL,
                        "fail to flush buffer(slot %d)", slot);
            return U_FAIL;
        }
    }
    return U_SUCC;
}
예제 #26
0
파일: uffs_tree.c 프로젝트: mazj/uffs
static URET _BuildTreeStepTwo(uffs_Device *dev)
{
	//Randomise the start point of erased block to implement wear levelling
	u32 startCount = 0;
	u32 endPoint;
	TreeNode *node;

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

	endPoint = uffs_GetCurDateTime() % (dev->tree.erased_count + 1);
	while (startCount < endPoint) {
		node = uffs_TreeGetErasedNodeNoCheck(dev);
		if (node == NULL) {
			uffs_Perror(UFFS_MSG_SERIOUS, "No erased block ?");
			return U_FAIL;
		}
		uffs_TreeInsertToErasedListTailEx(dev, node, -1);
		startCount++;
	}

	return U_SUCC;
}
예제 #27
0
파일: uffs_tree.c 프로젝트: mazj/uffs
static u16 _GetParentFromNode(u8 type, TreeNode *node)
{
	switch (type) {
	case UFFS_TYPE_DIR:
		return node->u.dir.parent;
	case UFFS_TYPE_FILE:
		return node->u.file.parent;
	case UFFS_TYPE_DATA:
		return node->u.data.parent;
	}
	uffs_Perror(UFFS_MSG_SERIOUS, "unkown type, X-parent");
	return INVALID_UFFS_SERIAL;
}
void uffs_MemSetupStaticAllocator(uffs_MemAllocator *allocator,
								  void *pool, int size)
{
	allocator->buf_start = (char *)pool;
	allocator->buf_size = size;
	allocator->pos = 0;
	allocator->malloc = static_malloc;
	allocator->free = NULL;  //never free memory for static memory allocator

	uffs_Perror(UFFS_MSG_NOISY,
				"System static memory: %d bytes", allocator->buf_size);
	
}
static void * static_malloc(struct uffs_DeviceSt *dev, unsigned int size)
{
	struct uffs_memAllocatorSt *mem = &dev->mem;
	void *p = NULL;

	size += (size % sizeof(long) ? sizeof(long) - (size % sizeof(long)) : 0);

	if (mem->buf_size - mem->pos < (int)size) {
		uffs_Perror(UFFS_MSG_SERIOUS,
					"Memory alloc failed! (alloc %d, free %d)",
					size, mem->buf_size - mem->pos);
	}
	else {
		p = mem->buf_start + mem->pos;
		mem->pos += size;
		uffs_Perror(UFFS_MSG_NOISY,
					"0x%p: Allocated %d, free %d",
					p, size, mem->buf_size - mem->pos);
	}

	return p;
}
예제 #30
0
파일: uffs_tree.c 프로젝트: mazj/uffs
static u16 _GetSerialFromNode(u8 type, TreeNode *node)
{
	switch (type) {
	case UFFS_TYPE_DIR:
		return node->u.dir.serial;
	case UFFS_TYPE_FILE:
		return node->u.file.serial;
	case UFFS_TYPE_DATA:
		return node->u.data.serial;
	}
	uffs_Perror(UFFS_MSG_SERIOUS, "unkown type, X-serial");
	return INVALID_UFFS_SERIAL;
}