⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yaffs_guts.c

📁 linux 镜像文件制作 用于压制yaffs2类型的文件镜像啊啊啊啊啊啊
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Verify the object header. oh must be valid, but obj and tags may be NULL in which * case those tests will not be performed. */static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck){	if (obj && yaffs_SkipVerification(obj->myDev))		return;	if (!(tags && obj && oh)) {		T(YAFFS_TRACE_VERIFY,				(TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR),				(__u32)tags, (__u32)obj, (__u32)oh));		return;	}	if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||			oh->type > YAFFS_OBJECT_TYPE_MAX)		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d header type is illegal value 0x%x"TENDSTR),			tags->objectId, oh->type));	if (tags->objectId != obj->objectId)		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d header mismatch objectId %d"TENDSTR),			tags->objectId, obj->objectId));	/*	 * Check that the object's parent ids match if parentCheck requested.	 *	 * Tests do not apply to the root object.	 */	if (parentCheck && tags->objectId > 1 && !obj->parent)		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),			tags->objectId, oh->parentObjectId));	if (parentCheck && obj->parent &&			oh->parentObjectId != obj->parent->objectId &&			(oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||			obj->parent->objectId != YAFFS_OBJECTID_DELETED))		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),			tags->objectId, oh->parentObjectId, obj->parent->objectId));	if (tags->objectId > 1 && oh->name[0] == 0) /* Null name */		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d header name is NULL"TENDSTR),			obj->objectId));	if (tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d header name is 0xFF"TENDSTR),			obj->objectId));}static int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn,					__u32 level, int chunkOffset){	int i;	yaffs_Device *dev = obj->myDev;	int ok = 1;	if (tn) {		if (level > 0) {			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {				if (tn->internal[i]) {					ok = yaffs_VerifyTnodeWorker(obj,							tn->internal[i],							level - 1,							(chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);				}			}		} else if (level == 0) {			yaffs_ExtendedTags tags;			__u32 objectId = obj->objectId;			chunkOffset <<=  YAFFS_TNODES_LEVEL0_BITS;			for (i = 0; i < YAFFS_NTNODES_LEVEL0; i++) {				__u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i);				if (theChunk > 0) {					/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */					yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags);					if (tags.objectId != objectId || tags.chunkId != chunkOffset) {						T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),							objectId, chunkOffset, theChunk,							tags.objectId, tags.chunkId));					}				}				chunkOffset++;			}		}	}	return ok;}static void yaffs_VerifyFile(yaffs_Object *obj){	int requiredTallness;	int actualTallness;	__u32 lastChunk;	__u32 x;	__u32 i;	yaffs_Device *dev;	yaffs_ExtendedTags tags;	yaffs_Tnode *tn;	__u32 objectId;	if (!obj)		return;	if (yaffs_SkipVerification(obj->myDev))		return;	dev = obj->myDev;	objectId = obj->objectId;	/* Check file size is consistent with tnode depth */	lastChunk =  obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;	x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;	requiredTallness = 0;	while (x > 0) {		x >>= YAFFS_TNODES_INTERNAL_BITS;		requiredTallness++;	}	actualTallness = obj->variant.fileVariant.topLevel;	if (requiredTallness > actualTallness)		T(YAFFS_TRACE_VERIFY,		(TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),		 obj->objectId, actualTallness, requiredTallness));	/* Check that the chunks in the tnode tree are all correct.	 * We do this by scanning through the tnode tree and	 * checking the tags for every chunk match.	 */	if (yaffs_SkipNANDVerification(dev))		return;	for (i = 1; i <= lastChunk; i++) {		tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant, i);		if (tn) {			__u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i);			if (theChunk > 0) {				/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */				yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags);				if (tags.objectId != objectId || tags.chunkId != i) {					T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),						objectId, i, theChunk,						tags.objectId, tags.chunkId));				}			}		}	}}static void yaffs_VerifyHardLink(yaffs_Object *obj){	if (obj && yaffs_SkipVerification(obj->myDev))		return;	/* Verify sane equivalent object */}static void yaffs_VerifySymlink(yaffs_Object *obj){	if (obj && yaffs_SkipVerification(obj->myDev))		return;	/* Verify symlink string */}static void yaffs_VerifySpecial(yaffs_Object *obj){	if (obj && yaffs_SkipVerification(obj->myDev))		return;}static void yaffs_VerifyObject(yaffs_Object *obj){	yaffs_Device *dev;	__u32 chunkMin;	__u32 chunkMax;	__u32 chunkIdOk;	__u32 chunkInRange;	__u32 chunkShouldNotBeDeleted;	__u32 chunkValid;	if (!obj)		return;	if (obj->beingCreated)		return;	dev = obj->myDev;	if (yaffs_SkipVerification(dev))		return;	/* Check sane object header chunk */	chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;	chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;	chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);	chunkIdOk = chunkInRange || obj->hdrChunk == 0;	chunkValid = chunkInRange &&			yaffs_CheckChunkBit(dev,					obj->hdrChunk / dev->nChunksPerBlock,					obj->hdrChunk % dev->nChunksPerBlock);	chunkShouldNotBeDeleted = chunkInRange && !chunkValid;	if (!obj->fake &&			(!chunkIdOk || chunkShouldNotBeDeleted)) {		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d has chunkId %d %s %s"TENDSTR),			obj->objectId, obj->hdrChunk,			chunkIdOk ? "" : ",out of range",			chunkShouldNotBeDeleted ? ",marked as deleted" : ""));	}	if (chunkValid && !yaffs_SkipNANDVerification(dev)) {		yaffs_ExtendedTags tags;		yaffs_ObjectHeader *oh;		__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);		oh = (yaffs_ObjectHeader *)buffer;		yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk, buffer,				&tags);		yaffs_VerifyObjectHeader(obj, oh, &tags, 1);		yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);	}	/* Verify it has a parent */	if (obj && !obj->fake &&			(!obj->parent || obj->parent->myDev != dev)) {		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),			obj->objectId, obj->parent));	}	/* Verify parent is a directory */	if (obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {		T(YAFFS_TRACE_VERIFY,			(TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),			obj->objectId, obj->parent->variantType));	}	switch (obj->variantType) {	case YAFFS_OBJECT_TYPE_FILE:		yaffs_VerifyFile(obj);		break;	case YAFFS_OBJECT_TYPE_SYMLINK:		yaffs_VerifySymlink(obj);		break;	case YAFFS_OBJECT_TYPE_DIRECTORY:		yaffs_VerifyDirectory(obj);		break;	case YAFFS_OBJECT_TYPE_HARDLINK:		yaffs_VerifyHardLink(obj);		break;	case YAFFS_OBJECT_TYPE_SPECIAL:		yaffs_VerifySpecial(obj);		break;	case YAFFS_OBJECT_TYPE_UNKNOWN:	default:		T(YAFFS_TRACE_VERIFY,		(TSTR("Obj %d has illegaltype %d"TENDSTR),		obj->objectId, obj->variantType));		break;	}}static void yaffs_VerifyObjects(yaffs_Device *dev){	yaffs_Object *obj;	int i;	struct ylist_head *lh;	if (yaffs_SkipVerification(dev))		return;	/* Iterate through the objects in each hash entry */	for (i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++) {		ylist_for_each(lh, &dev->objectBucket[i].list) {			if (lh) {				obj = ylist_entry(lh, yaffs_Object, hashLink);				yaffs_VerifyObject(obj);			}		}	}}/* *  Simple hash function. Needs to have a reasonable spread */static Y_INLINE int yaffs_HashFunction(int n){	n = abs(n);	return n % YAFFS_NOBJECT_BUCKETS;}/* * Access functions to useful fake objects. * Note that root might have a presence in NAND if permissions are set. */yaffs_Object *yaffs_Root(yaffs_Device *dev){	return dev->rootDir;}yaffs_Object *yaffs_LostNFound(yaffs_Device *dev){	return dev->lostNFoundDir;}/* *  Erased NAND checking functions */int yaffs_CheckFF(__u8 *buffer, int nBytes){	/* Horrible, slow implementation */	while (nBytes--) {		if (*buffer != 0xFF)			return 0;		buffer++;	}	return 1;}static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,				int chunkInNAND){	int retval = YAFFS_OK;	__u8 *data = yaffs_GetTempBuffer(dev, __LINE__);	yaffs_ExtendedTags tags;	int result;	result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);	if (tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)		retval = YAFFS_FAIL;	if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {		T(YAFFS_TRACE_NANDACCESS,		  (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND));		retval = YAFFS_FAIL;	}	yaffs_ReleaseTempBuffer(dev, data, __LINE__);	return retval;}static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,					const __u8 *data,					yaffs_ExtendedTags *tags,					int useReserve){	int attempts = 0;	int writeOk = 0;	int chunk;	yaffs_InvalidateCheckpoint(dev);	do {		yaffs_BlockInfo *bi = 0;		int erasedOk = 0;		chunk = yaffs_AllocateChunk(dev, useReserve, &bi);		if (chunk < 0) {			/* no space */			break;		}		/* First check this chunk is erased, if it needs		 * checking.  The checking policy (unless forced		 * always on) is as follows:		 *		 * Check the first page we try to write in a block.		 * If the check passes then we don't need to check any		 * more.	If the check fails, we check again...		 * If the block has been erased, we don't need to check.		 *		 * However, if the block has been prioritised for gc,		 * then we think there might be something odd about		 * this block and stop using it.		 *		 * Rationale: We should only ever see chunks that have		 * not been erased if there was a partially written		 * chunk due to power loss.  This checking policy should		 * catch that case with very few checks and thus save a		 * lot of checks that are most likely not needed.		 */		if (bi->gcPrioritise) {			yaffs_DeleteChunk(dev, chunk, 1, __LINE__);			/* try another chunk */			continue;		}		/* let's give it a try */		attempts++;#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED		bi->skipErasedCheck = 0;#endif		if (!bi->skipErasedCheck) {			erasedOk = yaffs_CheckChunkErased(dev, chunk);			if (erasedOk != YAFFS_OK) {				T(YAFFS_TRACE_ERROR,				(TSTR("**>> yaffs chunk %d was not erased"				TENDSTR), chunk));				/* try another chunk */				continue;			}			bi->skipErasedCheck = 1;		}		writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk,				data, tags);		if (writeOk != YAFFS_OK) {			yaffs_HandleWriteChunkError(dev, chunk, erasedOk);			/* try another chunk */			continue;		}		/* Copy the data into the robustification buffer */		yaffs_HandleWriteChunkOk(dev, chunk, data, tags);	} while (writeOk != YAFFS_OK &&		(yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));	if (!writeOk)		chunk = -1;	if (attempts > 1) {		T(YAFFS_TRACE_ERROR,			(TSTR("**>> yaffs write required %d attempts" TENDSTR),			attempts));		dev->nRetriedWrites += (attempts - 1);	}	return chunk;}/* * Block retiring for handling a broken block. */static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND){	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);	yaffs_InvalidateCheckpoint(dev);	if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) {		if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) {			T(YAFFS_TRACE_ALWAYS, (TSTR(				"yaffs: Failed to mark bad and erase block %d"				TENDSTR), blockInNAND));		} else {			yaffs_ExtendedTags tags;			int chunkId = blockInNAND * dev->nChunksPerBlock;			__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);			memset(buffer, 0xff, dev->nDataBytesPerChunk);			yaffs_InitialiseTags(&tags);			tags.sequenceNumber = YAFFS_SEQUENCE_BAD_BLOCK;			if (dev->writeChunkWithTagsToNAND(dev, chunkId -				dev->chunkOffset, buffer, &tags) != YAFFS_OK)				T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Failed to "					TCONT("write bad block marker to block %d")					TENDSTR), blockInNAND));			yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);		}	}	bi->blockState = YAFFS_BLOCK_STATE_DEAD;	bi->gcPrioritise = 0;	bi->needsRetiring = 0;	dev->nRetiredBlocks++;}/* * Functions for robustisizing TODO * */static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND,				const __u8 *data,				const yaffs_ExtendedTags *tags){}static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND,				const yaffs_ExtendedTags *tags){}void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi){	if (!bi->gcPrioritise) {		bi->gcPrioritise = 1;		dev->hasPendingPrioritisedGCs = 1;		bi->chunkErrorStrikes++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -