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

📄 tfs.c

📁 uCOS-II for AT91M55800A完整实例
💻 C
📖 第 1 页 / 共 4 页
字号:
				}				else {					tinfo->deadftot++;					tinfo->deaddata += TFS_SIZE(tfp);					tinfo->deadovrhd += TFSHDRSIZ;				}				tfp = nextfp(tfp,tdp);			}		}	}	tinfo->memused = tinfo->livedata + tinfo->liveovrhd +			tinfo->deaddata + tinfo->deadovrhd + tinfo->pso + tinfo->sos;	tinfo->memfree = tinfo->memtot - tinfo->memused; 	/* Remaining space may not even be big enough to contain the	 * file overhead, if this is the case, show a remaining space	 * of zero rather than a negative number...	 */	tinfo->memfordata =		tinfo->memfree - (devtot * (TFSHDRSIZ + sizeof(struct defraghdr)));	if (tinfo->memfordata < 0)		tinfo->memfordata = 0;	if (verbose) {		printf("\n Total memory: %d bytes (used=%d, avail=%d (%d for data)).\n",			tinfo->memtot,tinfo->memused,tinfo->memfree, tinfo->memfordata);		printf(" Per-device overhead: %d bytes ",tinfo->pso+tinfo->sos);		printf("(defrag-state=%d spare-sector=%d).\n",tinfo->pso,tinfo->sos);		printf(" File data space: %d bytes (live=%d, dead=%d).\n",			tinfo->livedata+tinfo->deaddata,			tinfo->livedata,tinfo->deaddata);		printf(" File overhead space: %d bytes (live=%d, dead=%d).\n",			tinfo->liveovrhd+tinfo->deadovrhd,			tinfo->liveovrhd,tinfo->deadovrhd);		printf(" File count: %d (live=%d, dead=%d).\n",			tinfo->liveftot+tinfo->deadftot,tinfo->liveftot,tinfo->deadftot);		printf(" Defrag will release %d bytes\n",			tinfo->deadovrhd+tinfo->deaddata);		printf("\n");	}	return(tinfo->liveftot + tinfo->deadftot);}/* tfscheck(): *	Step through each file in a particular device making a few checks... *	- First look at the header.  If hdrsize is erased, it "should" indicate *	  the end of the linear list of files.  To be anal about it, verify that *	  the entire header is erased.  If it is, we truly are at the end of the *	  list; otherwise, header error. *	- Second, do a crc32 on the header.  *	- Third, if the file is not deleted, then do a crc32 on the data portion *	  of the file (if the file is deleted, then it really doesn't matter if *	  there is a crc32 error on that data). *	- Finally, if the header is not corrupted, index to the next pointer and *	  continue.  If the header is corrupt, see if enough information *	  in the header is valid to allow us to step to the next file.  Do this *	  by calculating where the next pointer should be (using current pointer, *	  file+header size and mod16 adjustment) and then see if that matches the *	  value stored in the actual "next" pointer.  If yes, go to next file; *	  else break out of the loop. *	 *	The purpose is to do more sophisticated file system checks than are *	done in normal TFS operations. */#define TFS_CORRUPT		1#define HDR_CORRUPT		2#define DATA_CORRUPT	4inttfscheck(TDEV *tdp, int verbose){	ulong	hdrcrc;	int		tfscorrupt, filtot;	TFILE	*fp, *fp1, hdrcpy;	if (!tdp)		return(TFSERR_BADARG);	if (verbose)		printf("TFS device %s check:\n",tdp->prefix);	filtot = tfscorrupt = 0;	fp = (TFILE *)tdp->start;	while(1) {		tfscorrupt &= ~(HDR_CORRUPT | DATA_CORRUPT);		/* If hdrsize is ERASED16, then verify that the whole header is		 * also ERASED16, if yes, we're at the end of the linear list of		 * files; otherwise, we have a corrupt header.		 */		if (fp->hdrsize == ERASED16) {			int		i;			ushort	*sp;			/* If this is right at the edge of the end of the TFS device,			 * then break with no further checks to this header.			 */			if ((fp+1) > (TFILE *)tdp->end)				break;			/* Make sure the entire header is erased... */			sp = (ushort *)fp;			for(i=0;i<TFSHDRSIZ;i+=2,sp++) {				if (*sp != ERASED16) {					if (verbose)						printf(" Corrupt hdr @ 0x%lx",(ulong)fp);					tfscorrupt = HDR_CORRUPT | TFS_CORRUPT;				}			}			if (!(tfscorrupt & HDR_CORRUPT))				break;			else				goto nextfile;		}		/* Run a crc check on the header even if file is deleted...			*/		hdrcpy = *fp;		hdrcrc = fp->hdrcrc;		hdrcpy.next = 0;		hdrcpy.hdrcrc = 0;		hdrcpy.flags |= (TFS_NSTALE | TFS_ACTIVE);		if (crc32((uchar *)&hdrcpy,TFSHDRSIZ) != hdrcrc) {			if (verbose)				printf(" CRC error in hdr @ 0x%lx",(ulong)fp);			tfscorrupt = HDR_CORRUPT | TFS_CORRUPT;			goto nextfile;		}		/* If file exists, and it's not IPMOD, run a crc check on data...	*/		if (TFS_FILEEXISTS(fp) && !(fp->flags & TFS_IPMOD)) { 			filtot++;			if (verbose)				printf(" %s...",fp->name);					if ((!(fp->flags & TFS_IPMOD)) &&				(crc32(TFS_BASE(fp),fp->filsize) != fp->filcrc)) {					if (verbose)						printf(" CRC error in data");					tfscorrupt = DATA_CORRUPT | TFS_CORRUPT;			}			else {				if (verbose)					printf(" ok");			}		}		/* Prior to incrementing to the next file pointer, if the header		 * is corrupted, attempt to salvage the next pointer...		 * If the value of the next pointer matches what is	calculated		 * from the file size and header size, then assume it is ok		 * and allow the tfscheck() loop to continue; otherwise break.		 */nextfile:		if (tfscorrupt & HDR_CORRUPT) {			if (fp->next) {				ulong modnext;								modnext = (ulong)((int)(fp+1) + fp->filsize);				if (modnext & 0xf) {					modnext += 16;					modnext &= ~0xf;				}				if (verbose)					printf(" (next ptr ");				if (fp->next != (TFILE *)modnext) {					if (verbose)						printf("damaged)\n");					break;				}				else {					if (verbose)						printf("salvaged)");				}			}		}		fp1 = nextfp(fp,tdp);		if (!fp1) {			tfscorrupt = HDR_CORRUPT | TFS_CORRUPT;			break;		}		if ((verbose) && (TFS_FILEEXISTS(fp) || tfscorrupt))			putchar('\n');		fp = fp1;	}	if (tfscorrupt || !tfsflasherased(tdp,verbose))		return(TFSERR_CORRUPT);	if (verbose)		printf(" PASSED\n");	return (TFS_OKAY);}voidtfsclear(TDEV *tdp){	int i;	/* Clear the fileslot[] table indicating that no files are opened.	 * Only clear the slots applicable to the incoming TDEV pointer.	 */	for (i = 0; i < TFS_MAXOPEN; i++) {		ulong offset;		offset = tfsSlots[i].offset;		if (offset != (ulong)-1) {			if ((tdp == (TDEV *)0) ||				((offset >= tdp->start) && (offset <= tdp->end)))				tfsSlots[i].offset = -1;		}	}	/* If the incoming TDEV pointer is NULL, then we can assume a global	 * clear and go ahead and cleanup everything; otherwise, we just return	 * here.	 */	if (tdp != (TDEV *)0)		return;	/* Turn off tracing. */	tfsTrace = 0;	/* Init the time retrieval function pointers to their dummy values. */	tfsGetAtime = dummyAtime;	tfsGetLtime = dummyLtime;	/* Default to using standard docommand() within scripts. */	tfsDocommand = docommand;	/* Start off with a buffer for 16 files.  This is probably more than	 * will be used, so it avoids reallocations in tfsreorder().	 */	tfsAlistSize = 16;	tfsAlist = (TFILE **)malloc((tfsAlistSize+1) * sizeof(TFILE **));	if (!tfsAlist) {		printf("tfsclear(): tfsAlist allocation failed\n");		tfsAlistSize = 0;	}}/* tfsstalecheck(): *	Called at startup to clean up any file that may be in STALE mode. *	A file is stale if it was in the process of being modified *	and a power hit occurred.  Refer to notes in tfsadd() for details. *	There are a few cases to be covered here... *	1. there is no stale file; so there is nothing to do. *	2. there is a stale file, but no other file with the same name... *		In this case, the stale file must be copied to another file (with the *		TFS_NSTALE flag set) and the stale file is deleted. *	3. there is stale file and another file with the same name... *		In this case, the stale file is simply deleted because the other file *		with the same name is newer. */ static voidtfsstalecheck(){	int		err;	ulong	flags;	TDEV	*tdp;	TFILE	*tfp, *tfpa;	char	buf[16];	tfpa = (TFILE *)0;	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {		tfp = (TFILE *)tdp->start;		tfpa = (TFILE *)0;		while(validtfshdr(tfp)) {			if (TFS_FILEEXISTS(tfp)) {				if (tfpa) {					if (!strcmp(TFS_NAME(tfp),TFS_NAME(tfpa))) {						_tfsunlink(TFS_NAME(tfpa));						return;					}				}				else if (TFS_STALE(tfp)) {					tfpa = tfp;				}			}			tfp = nextfp(tfp,tdp);		}	}	if (tfpa) {		flags = TFS_FLAGS(tfpa) | TFS_NSTALE;		err = tfsadd(TFS_NAME(tfpa),TFS_INFO(tfpa),tfsflagsbtoa(flags,buf),			(char *)(TFS_BASE(tfpa)),TFS_SIZE(tfpa));		if (err != TFS_OKAY)			printf("%s: %s\n",TFS_NAME(tfpa),tfserrmsg(err));				_tfsunlink(TFS_NAME(tfpa));	}}/* tfsoldstyleflagcheck(): *	This function is called once at startup to make a clean transition *	to a version of TFS that deletes a file by ONLY clearing the TFS_ACTIVE *	bit in the flags field (older method cleared the whole flag). *	This new deletion method makes it possible to run a crc32 check on the *	header of a deleted file; this change was made around Sept 1999. */voidtfsoldstyleflagcheck(void){#ifdef INCLUDE_OLDSTYLE_FLAGCHECK	static	int alreadyran;	int		printonce;	TDEV	*tdp;	TFILE	*tfp;	/* This should only occur once at startup. */	if (alreadyran)		return;	printonce = 1;	tfsOldDelFlagCheckActive = 1;	for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {		tfp = (TFILE *)tdp->start;		while(validtfshdr(tfp)) {			/* If old-style deletion flag is detected, just run tfsclean	*/			/* (with tfsOldDelFlagCheckActive set) on the device to			*/			/* eliminate the delted file.									*/			if (tfp->flags == 0) {					if (printonce) {					printf("Cleaning up old style deletion flags...\n");					printonce = 0;				}				tfsautoclean(0,0,0,0,tdp,0,1);				break;				}			tfp = nextfp(tfp,tdp);		}	}	tfsOldDelFlagCheckActive = 0;	alreadyran = 1;#endif}/* tfsdevtblinit(): *	Transfer the information in tfsdevtbl (in tfsdev.h) to tfsDeviceTbl[]. *	In most cases, this will be a simple copy.  If the device flag is set *	to indicate that the initalization is dynamic, then use the flash  *	ops to retrieve the information from the specified bank. * *	For dynamic configuration, the "start" member of the tfsdev structure *	must be set in tfsdev.h and the "devinfo & TFS_DEVINFO_BANKMASK" area *	must contain the number of the last flash bank that is to be part of *	the TFS device.  Typically this value is the same bank number as the *	starting bank, but it could span across multiple contiguous banks *	if the hardware is set up that way. * *	To support the use of top-boot devices, plus the TFS requirement that *	the SPARE sector be at-least as large as any other sector in the device, *	this code will automatically step down the sector list until it finds *	the first large sector below all the small ones usually at the top of *	a top-boot device.  The call to lastlargesector() takes care of this. * *	NOTE: *	 This dynamic configuration assumes that the end of the TFS space is *	 just below the beginning of the spare space. * */voidtfsdevtblinit(void){	int		i, startsector, endsector, bank;	TDEV	*tDp, *tdp;	for(i=0;i<TFSDEVTOT;i++) {		tdp = &tfsdevtbl[i];		tDp = &tfsDeviceTbl[i];		*tDp = *tdp;		if (i == TFSDEVTOT-1)			break;		if (tdp->devinfo & TFS_DEVINFO_DYNAMIC) {			bank = tDp->devinfo & TFS_DEVINFO_BANKMASK;			/* The spare sector may not be the last sector in the device...			 * device.  Especially if the device is TopBoot type.			 */			if (lastlargesector(bank,&endsector,				(int *)&tDp->sparesize,(uchar **)&tDp->spare) == -1)				break;			tDp->end = tDp->spare - 1;			if (addrtosector((uchar *)tDp->start,&startsector,0,0) == -1)				break;			tDp->sectorcount = endsector - startsector;		}	}}/* tfsstartup(): *	Called at system startup to get things properly initialized. */voidtfsstartup(){	tfsdevtblinit();	tfsclear((TDEV *)0);	tfsfixup(3,0);	tfsstalecheck();	tfsoldstyleflagcheck();}/* tfsexec: Treat the file as machine code that is COFF or ELF. */static inttfsexec(fp,verbose)int	verbose;TFILE *fp;{	extern	int ctxMON(), ctxAPP();	int err, (*entry)(), octx;	long	address;	err = tfsloadebin(fp,verbose,&address,0);	if (err != TFS_OKAY)		return(err);	entry = (int(*)())address;	octx = ctxAPP();	/* Change context to APPLICATION. */	entry();			/* Call entrypoint (may not return). */	ctxMON(octx);		/* Change context to APPLICATION. */	return(TFS_OKAY);}/* tfsmemset(): *	Superset of memset().  Includes verbose option plus verification after *	set. */inttfsmemset(uchar *to,uchar val,int count,int verbose,int verifyonly){	int		failed;	uchar	*end;	failed = 0;	if (verbose) {		printf("%s %7d bytes  at  0x%08lx to 0x%02x",			verifyonly ? "vrfy" : "set ",count,(ulong)to,val);	}	if (count == 0)		goto done;	end = to+count;	if (verifyonly) {		while(to < end) {			if (*to++ != val) {				failed = 1;				break;			}		}	}	else {		while(to < end) {			*to = val;			if (*to++ != val) {				failed = 1;				break;			}		}	}done:	if (verbose) {		if (failed)			printf(" failed");		else if (verifyonly)			printf(" OK");		printf("\n");	}	if (failed)		return(TFSERR_MEMFAIL);	else		return(TFS_OKAY);}/* tfsmemcpy(): *	Superset of memcpy().  Includes verbose option plus verification after *	copy.  Takes advantage of address alignment when possible. */inttfsmemcpy(uchar *to,uchar *from,int count,int verbose,int verifyonly){	int	err;	register uchar	*end;	if (verbose)		printf("%s %7d bytes from 0x%08lx to 0x%08lx",			verifyonly ? "vrfy" : "copy", count,(ulong)from,(ulong)to);	if (verifyonly) {		while(count) {			if (*to != *from)				break;			to++;			from++;			count--;		}		if (count) {			if (verbose) {				printf(" FAILED\n");				printf("            (0x%02x @ 0x%08lx should be 0x%02x)\n",					*to,(ulong)to,*from);			}			return(TFSERR_MEMFAIL);		}		else			if (verbose)				printf(" OK\n");			return(TFS_OKAY);	}	if (count == 0)		goto done;	if (to != from) {		err = 0;		if (!((int)to & 3) && !((int)from & 3) && !(count & 3)) {			register ulong	*lto, *lfrom, *lend;				count >>= 2;			lto = (ulong *)to;			lfrom = (ulong *)from;			lend = lto + count;			while(lto < lend) {				*lto = *lfrom;				if (*lto != *lfrom) {					err = 1;					break;				}				lto++;				lfrom++;			}		}		else if (!((int)to & 1) && !((int)from & 1) && !(count & 1)) {

⌨️ 快捷键说明

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