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

📄 tfs.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (!tfp->flag)
			return(TFSERR_BADFLAG);
		fstr++;
	}
	return(TFS_OKAY);
}

/* hdrcrc():
 * The crc of the file header was originally calculated (in tfsadd())
 * with the header crc and next pointer nulled out; so a copy must
 * be made and these two fields cleared.  Also, note that the
 * TFS_NSTALE and TFS_ACTIVE flags are forced to be set in the copy.
 * This is done because it is possible that either of these bits may
 * have been cleared due to other TFS interaction; hence, they need
 * to be set prior to crc calculation.
 * Note also that earlier versions of TFS deleted a file by clearing
 * the entire flags field.  This made it impossible to do a header crc
 * check on a deleted file; deletion has been changed to simply clear
 * the TFS_ACTIVE bit in the flags, so now a deleted file's header can
 * can be crc tested by simply forcing the TFS_ACTIVE bit high as was
 * mentioned above.
 */
ulong
tfshdrcrc(TFILE *hdr)
{
	TFILE hdrcpy;

	hdrcpy = *hdr;
	hdrcpy.next = 0;
	hdrcpy.hdrcrc = 0;
	hdrcpy.flags |= (TFS_NSTALE | TFS_ACTIVE);
	return(crc32((uchar *)&hdrcpy,TFSHDRSIZ));
}

/* validtfshdr():
 *	Return 1 if the header pointed to by the incoming header pointer is valid.
 *	Else return 0.  The header crc is calculated based on the hdrcrc
 *	and next members of the structure being zero.
 *	Note that if the file is deleted, then just ignore the crc and return 1.
 */
int
validtfshdr(TFILE *hdr)
{
	/* A few quick checks... */
	if (!hdr || hdr->hdrsize == ERASED16)
		return(0);

	if (tfshdrcrc(hdr) == hdr->hdrcrc) {
		return(1);
	}
	else {
		/* Support transition to new deletion flag method...
		 */
		if ((hdr->flags == 0) && tfsOldDelFlagCheckActive)
			return(1);					

		printf("Bad TFS hdr crc @ 0x%lx\n",(ulong)hdr);
		return(0);
	}
}

/* nextfp():
 *	Used as a common means of retrieving the next file header pointer.  It
 *	does some sanity checks based on the fact that all pointers must fall
 *	within the TFSSTART<->TFSEND memory range and since each file is placed
 *	just after the previous one in linear memory space, fp->next should
 *	always be greater than fp.
 */
TFILE *
nextfp(TFILE *fp, TDEV *tdp)
{
	if (!tdp)
		tdp = gettfsdev(fp);

	/* Make some basic in-range checks...
	 */
	if ((!tdp) || (fp < (TFILE *)tdp->start) || (fp > (TFILE *)tdp->end) ||
		(fp->next < (TFILE *)tdp->start) || (fp->next > (TFILE *)tdp->end)  ||
		(fp->next <= fp)) {
		printf("Bad TFS hdr ptr @ 0x%lx\n",(ulong)fp);
		return(0);
	}
	return(fp->next);
}

/* tfsflasherased():
 *	Jump to the point in flash after the last file in TFS, then verify
 *	that all remaining flash  that is dedicated to TFS is erased (0xff).
 *	If erased, return 1; else return 0.
 */
int
tfsflasherased(TDEV *tdp, int verbose)
{
	ulong	*lp;
	TFILE	*tfp;

	tfp = (TFILE *)tdp->start;
	while(validtfshdr(tfp))
		tfp = nextfp(tfp,tdp);

	lp = (ulong *)tfp;
	while (lp < (ulong *)tdp->end) {
		if (*lp != ERASED32) {
			if (verbose)
				printf("End of TFS on %s not erased at 0x%lx\n",
					tdp->prefix,(ulong)lp);
			return(0);
		}
#ifdef WATCHDOG_ENABLED
		if (((ulong)lp & 0x3f) == 0)
			WATCHDOG_MACRO;
#endif
		lp++;
	}
	return(1);
}

static int
tfsftot(TDEV *tdpin)
{
	int		ftot;
	TFILE	*tfp;
	TDEV	*tdp;

	ftot = 0;
	for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		if (!tdpin || (tdpin == tdp)) {
			tfp = (TFILE *)tdp->start;
			while(validtfshdr(tfp)) {
				if (TFS_FILEEXISTS(tfp))
					ftot++;
				tfp = nextfp(tfp,tdp);
			}
		}
	}
	return(ftot);
}

/* tfsmemuse():
 *	Step through one (or all) TFS devices and tally up various memory usage
 *	totals.  See definition of tfsmem structure for more details.
 *	If incoming tdpin pointer is NULL, then tally up for all TFS devices;
 *	otherwise, tally up for only the one device pointed to by tdpin.
 */
int
tfsmemuse(TDEV *tdpin, TINFO *tinfo, int verbose)
{
	int		devtot;
	char	*cfgerr;
	TFILE	*tfp;
	TDEV	*tdp;

	/* Start by clearing incoming structure...
	 */
	tinfo->pso = 0;
	tinfo->sos = 0;
	tinfo->memtot = 0;
	tinfo->liveftot = 0;
	tinfo->deadftot = 0;
	tinfo->livedata = 0;
	tinfo->deaddata = 0;
	tinfo->liveovrhd = 0;
	tinfo->deadovrhd = 0;

	if (verbose) {
		printf("TFS Memory Usage...\n     ");
		printf(" name    start       end       spare     spsize  scnt type\n");
	}
	devtot = 0;
	for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		if (!tdpin || (tdpin == tdp)) {
			devtot++;
			tfp = (TFILE *)tdp->start;

			cfgerr = (char *)0;

			/* Do some sanity checks on the configuration...
			 */
			if ((tdp->spare >= tdp->start) && (tdp->spare <= tdp->end)) {
				cfgerr = "spare within storage space";
			}
			if (cfgerr) {
				printf("Bad %s TFS config: %s.\n",tdp->prefix,cfgerr);
			}
			if (verbose) {
				printf("%10s: 0x%08lx|0x%08lx|",
					tdp->prefix,(ulong)(tdp->start),(ulong)(tdp->end));

				if (TFS_DEVTYPE_ISRAM(tdp))
					printf("  - NA -  | - NA - | NA ");
				else
					printf("0x%08lx|0x%06lx|%4ld",(ulong)(tdp->spare),
						tdp->sparesize,tdp->sectorcount);

				printf("|0x%lx\n",(ulong)(tdp->devinfo));
			}
			tinfo->memtot += ((tdp->end - tdp->start) + 1) + tdp->sparesize;
			tinfo->pso += (tdp->sectorcount * 4) + 16;
			tinfo->sos += tdp->sparesize;
			while(validtfshdr(tfp)) {
				if (TFS_FILEEXISTS(tfp)) {
					tinfo->liveftot++;
					tinfo->livedata += TFS_SIZE(tfp);
					tinfo->liveovrhd += (TFSHDRSIZ + DEFRAGHDRSIZ);
				}
				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 + DEFRAGHDRSIZ));
	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	4

int
tfscheck(TDEV *tdp, int verbose)
{
	int		tfscorrupt, filtot;
	TFILE	*fp, *fp1;

	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;
					break;
				}
			}
			if (!(tfscorrupt & HDR_CORRUPT))
				break;
			else
				goto nextfile;
		}

		/* Run a crc check on the header even if file is deleted...
		 */
		if (tfshdrcrc(fp) != fp->hdrcrc) {
			if (verbose)
				printf(" CRC error in hdr @ 0x%lx\n",(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;
	}
	tfsflasherased(tdp,verbose);
	if (tfscorrupt)
		return(TFSERR_CORRUPT);
	if (verbose)
		printf(" PASSED\n");
	return (TFS_OKAY);
}

void
tfsclear(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().
	 *
	 * Note that this function may be called as a result of the monitor
	 * doing an application exit.  In that case, the heap is not
	 * re-initialized; hence, tfsAlist may already be allocated.
	 * If it is, then just leave it alone...
	 */
	if (tfsAlist == 0) {
		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

⌨️ 快捷键说明

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