tfsclean1.c

来自「umon bootloader source code, support mip」· C语言 代码 · 共 2,107 行 · 第 1/5 页

C
2,107
字号
			case SCANNING_ACTIVE_SECTOR_5:
				defrag_state = SCANNING_ACTIVE_SECTOR;
				break;
		}
	}
	else {
		defrag_state = SECTOR_DEFRAG_INACTIVE;
	}

	if (verbose || restart || (!MFLAGS_NODEFRAGPRN())) {
		printf("TFS device '%s' powersafe defragmentation\n",tdp->prefix);
		if ((restart) && pollConsole("ok?")) {
			printf("aborted\n");
			return(TFS_OKAY);
		}
	}

	if (addrtosector((char *)tdp->start,&firstsnum,0,0) < 0)
		return(TFSERR_MEMFAIL);
	lastsnum = firstsnum + tdp->sectorcount - 1;
	if (addrtosector((char *)tdp->end,&sectorcheck,0,0) < 0)
		return(TFSERR_MEMFAIL);
	if (lastsnum != sectorcheck) {
		/* If this error occurs, it is an indication that TFS was not
		 * properly configured in config.h, this error should not occur
		 * if TFS is properly configured.
		 */
		printf("%s: SECTORCOUNT != TFSSTART <-> TFSEND\n", tdp->prefix);
		printf("First TFS sector = %d, last = %d\n",firstsnum,sectorcheck);
		return(TFSERR_MEMFAIL);
	}

	if (defrag_state == SECTOR_DEFRAG_INACTIVE) {
		activesnum = firstsnum;
	}

	/* Retrieve information about last sector:
	 */
	if (sectortoaddr(lastsnum,&lastssize,&lastsbase) == -1)
		return(TFSERR_MEMFAIL);

	/* Establish a pointer to a table of CRCs that will contain
	 * one 32-bit CRC for each sector (prior to starting the defrag).
	 */
	crctbl = defragCrcTable(tdp);

	/* Retrieve the number of "dead" and "living" files:
	 * If there are no dead files, then there is no need to defrag.
	 * If there are no "living" files, then we can just init the flash.
	 */
	ftot = dtot = 0;
	if (restart && defragValidDSI(tdp,0)) {
		dht = (struct defraghdr *)crctbl - 1;
		ftot = dht->idx + 1;
	}
	else {
		tfp = (TFILE *)tdp->start;
		while(validtfshdr(tfp)) {
			if (TFS_FILEEXISTS(tfp))
				ftot++;
			else
				dtot++;
			tfp = nextfp(tfp,tdp);
		}
		if (dtot == 0) {
			if (verbose)
				printf("No dead files in %s.\n",tdp->prefix);
			if (tfsflasherased(tdp,verbose))
				return(0);
			if (verbose)
				printf("Cleaning up end of flash...\n");
		}
	}
	if (ftot == 0) {
		if (verbose)
			printf("No active files detected, erasing all %s flash...\n",
				tdp->prefix);
		_tfsinit(tdp);
		return(0);
	}

	/* Now that we know how many files are in TFS, we can establish 
	 * a pointer to the defrag header table, and the size of the table...
	 */
	dht = (struct defraghdr *)crctbl - ftot;
	dhstsize = (ulong)(tdp->end+1) - (ulong)dht;
	dhstsize += 4; /* Account for the CRC of the state tables. */

	if (defrag_state == SECTOR_DEFRAG_INACTIVE) {
		ulong	crc;

		if (verbose) {
			printf("TFS defrag: building DSI space...\n");
		}

		/* We start by making sure that the space needed by the
		 * defrag header and state table at the end of the last
		 * sector is clear...
		 */
		if (!flasherased((uchar *)dht, (uchar *)(tdp->end))) {
			if (defragEraseSpare(tdp) < 0)
				return(TFSERR_FLASHFAILURE);

			if (defragFwrite(9,(uchar *)(tdp->spare),lastsbase,
				lastssize-dhstsize) == -1) {
				return(TFSERR_FLASHFAILURE);
			}
			if (defragSerase(5,lastsnum) < 0) {
				return(TFSERR_FLASHFAILURE);
			}
			if (defragFwrite(10,lastsbase,(uchar *)(tdp->spare),
				lastssize) == -1) {
				return(TFSERR_FLASHFAILURE);
			}
		}

		/* Erase the spare then copy the portion of the last TFS
		 * sector that does not overlap with the defrag header and
		 * state table area to the spare.  We do this so that the spare
		 * sector contains a defrag header and state table area that
		 * is erased.
		 */
		if (defragEraseSpare(tdp) < 0)
			return(TFSERR_FLASHFAILURE);
	
		if (defragFwrite(11,(uchar *)tdp->spare,
			lastsbase,lastssize-dhstsize) == -1) {
			return(TFSERR_FLASHFAILURE);
		}

		/* At this point we have a valid copy of the last sector in
		 * the spare.  If any portion of the last sector is not identical
		 * to what is in the spare, then we need to erase the last sector
		 * and re-copy what is in the spare to the last sector.  This is
		 * necessary because an interrupt may have occurred while writing
		 * to the last sector, and it may have corrupted something.
		 */

		if ((memcmp(lastsbase,(char *)(tdp->spare),lastssize-dhstsize)) ||
			(!flasherased((uchar *)dht,(uchar *)tdp->end))) {
			if (defragSerase(6,lastsnum) < 0) {
				return(TFSERR_FLASHFAILURE);
			}
			if (defragFwrite(12,lastsbase,(uchar *)(tdp->spare),
				lastssize) == -1) {
				return(TFSERR_FLASHFAILURE);
			}
		}
		/* Build the header table:
		 */
		fcnt = 0;
		tfp = (TFILE *)tdp->start;
		newaddress = (char *)tdp->start;

		if (verbose > 2) {
			printf("\nDEFRAG HEADER DATA (dht=0x%lx, ftot=%d):\n",
				(ulong)dht,ftot);
		}
	
		while(validtfshdr(tfp)) {
			if (TFS_FILEEXISTS(tfp)) {
				uchar	*base, *eof, *neof, *nbase;
				int		size, slot;
				struct	tfsdat *slotptr;
	
				strcpy(defrag.fname,TFS_NAME(tfp));
				defrag.ohdr = tfp;
				defrag.ohdrcrc = tfp->hdrcrc;
				defrag.filsize = TFS_SIZE(tfp);
				if (addrtosector((char *)tfp,0,0,&base) < 0)
					return(TFSERR_MEMFAIL);

				eof = (uchar *)(tfp+1)+TFS_SIZE(tfp)-1;
				if (addrtosector((char *)eof,0,0,&base) < 0)
					return(TFSERR_MEMFAIL);
				defrag.oeso = eof - base + 1;

				neof = newaddress+TFSHDRSIZ+TFS_SIZE(tfp)-1;
				if (addrtosector((char *)neof,(int *)&defrag.nesn,0,&nbase) < 0)
					return(TFSERR_MEMFAIL);
				defrag.neso = neof - nbase + 1;

				defrag.crc = 0;
				defrag.idx = fcnt;
				defrag.nda = newaddress;
	
				/* If the file is currently opened, adjust the base address. */
				slotptr = tfsSlots;
				for (slot=0;slot<TFS_MAXOPEN;slot++,slotptr++) {
					if (slotptr->offset != -1) {
						if (slotptr->base == (uchar *)(TFS_BASE(tfp))) {
							slotptr->base = (uchar *)(newaddress+TFSHDRSIZ);
						}
					}
				}
				size = TFS_SIZE(tfp) + TFSHDRSIZ;
				if (size & 0xf) {
					size += TFS_FSIZEMOD;
					size &= ~(TFS_FSIZEMOD-1);
				}
				newaddress += size;
				defrag.nextfile = (TFILE *)newaddress;
				defrag.crc = crc32((uchar *)&defrag,DEFRAGHDRSIZ);
				if (verbose > 2) {
					printf(" File %s:\n",TFS_NAME(tfp));
					printf("     nda=  0x%08lx, ohdr= 0x%08lx, nxt=  0x%08lx\n",
						(ulong)(defrag.nda),(ulong)(defrag.ohdr),
						(ulong)(defrag.nextfile));
					printf("     oeso= 0x%08lx, nesn= 0x%08lx, neso= 0x%08lx\n",
						(ulong)(defrag.oeso),(ulong)(defrag.nesn),
						(ulong)(defrag.neso));
				}
				if (defragFwrite(13,(uchar *)(&dht[fcnt]),
					(uchar *)(&defrag),DEFRAGHDRSIZ) == -1) {
					return(TFSERR_FLASHFAILURE);
				}
				fcnt++;
				defragTick(0);
			}
			tfp = nextfp(tfp,tdp);
		}

		if (defragBuildCrcTable(tdp,dht,verbose) < 0)
			return(TFSERR_FLASHFAILURE);

		/* Now, the last part of the state table build is to store a
		 * 32-bit crc of the data we just wrote...
		 */
		crc = crc32((uchar *)dht,(uchar *)tdp->end - (uchar *)dht);
		if (defragFwrite(14,(uchar *)((ulong *)dht-1),(uchar *)&crc,4) == -1) {
			return(TFSERR_FLASHFAILURE);
		}

		defrag_state = SCANNING_ACTIVE_SECTOR;
	}

	/* Exit here to have a complete defrag header installed. */
	defragExitTestPoint(1000);

	if (defrag_state == SCANNING_ACTIVE_SECTOR) {

		if (verbose) {
			printf("TFS: updating sectors %d-%d...\n",
				activesnum,lastsnum);
		}

		/* Now we begin the actual defragmentation.  We have built enough
		 * state information (defrag header and state table) into the last
		 * TFS sector, so now we can start the cleanup.
		 */
		for(sidx = activesnum - firstsnum; sidx < tdp->sectorcount; sidx++) {
			if (defragFillActiveSector(tdp,ftot,sidx,verbose) < 0)
				return(TFSERR_FLASHFAILURE);
		}

		defrag_state = SECTOR_DEFRAG_ALMOST_DONE;
	}

	/* Exit here to test "almost-done" state detection. */
	defragExitTestPoint(1001);

	if (defrag_state == SECTOR_DEFRAG_ALMOST_DONE) {

		/* We've completed the relocation of all files into a defragmented
		 * area of TFS flash space.  Now we have to erase all sectors after
		 * the sector used by the last file in TFS (including the spare)...
		 * If the last file in TFS uses the last sector, then the defrag
		 * header table will be erased and there is nothing left to do
		 * except erase the spare.
		 */
		if (verbose) {
			printf("TFS: clearing available space...\n");
		}
		if (dht[ftot-1].crc != ERASED32) {
			end = (dht[ftot-1].nda + dht[ftot-1].filsize + TFSHDRSIZ) - 1;
			if (addrtosector(end,&snum,0,0) < 0)
				return(TFSERR_FLASHFAILURE);
			snum++;
			while(snum <= lastsnum) {
				if (defragSerase(7,snum) < 0)
					return(TFSERR_FLASHFAILURE);
				snum++;
				defragTick(0);
			}
		}
		if (defragEraseSpare(tdp) < 0)
			return(TFSERR_FLASHFAILURE);

		/* All defragmentation is done, so verify sanity of files... */
		chkstat = tfscheck(tdp,verbose);
	}
	else {
		chkstat = TFS_OKAY;
	}

	if ((verbose) || (!MFLAGS_NODEFRAGPRN()))
		printf("Defragmentation complete\n");

	return(chkstat);
}

/* tfsfixup():
 *	Called at system startup to finish up a TFS defragmentation if one
 *	was in progress.
 */
int
tfsfixup(int verbose, int dontquery)
{
	TDEV	*tdp;

	/* Clear test data... */
	DefragTestType = 0;
	DefragTestPoint = 0;
	DefragTestSector = 0;

#if !DEFRAG_TEST_ENABLED
	tfsTrace = 99;
#endif

	/* For each TFS device, run defrag with "fixup" flag set to let
	 * the defragger know that it should only defrag if a defrag was
	 * in progress. 
	 */
	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		/* Call tfsclean() with fixup flag set... */
#if TFS_VERBOSE_STARTUP
		if (StateOfMonitor == INITIALIZE)
			printf("^oo^ TFS Scanning %s...\n",tdp->prefix);
#endif
		_tfsclean(tdp,1,99);
	}

#if !DEFRAG_TEST_ENABLED
	tfsTrace = 0;
#endif
	return(0);
}

#if DEFRAG_TEST_ENABLED
int
dumpDhdr(DEFRAGHDR *dhp)
{
	printf("ohdr: 0x%08lx\n",(ulong)dhp->ohdr);
	printf("nextfile: 0x%08lx\n",(ulong)dhp->nextfile);
	printf("filsize: 0x%08lx\n",(ulong)dhp->filsize);
	printf("crc: 0x%08lx\n",(ulong)dhp->crc);
	printf("idx: 0x%08lx\n",(ulong)dhp->idx);
	printf("nesn: 0x%08lx\n",(ulong)dhp->nesn);
	printf("neso: 0x%08lx\n",(ulong)dhp->neso);
	printf("nda: 0x%08lx\n",(ulong)dhp->nda);
	printf("fname: %s\n",dhp->fname);
	return(TFS_OKAY);
}

int
dumpDhdrTbl(DEFRAGHDR *dhp, int ftot)
{
	TDEV	*tdp;
	uchar	*sbase;
	ulong	*crc, calccrc;
	int		i, ssize, snum;
	struct	sectorcrc *crctbl;

	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {

		if (!dhp) {
			crctbl = defragCrcTable(tdp);
			printf("Device %s...\n",tdp->prefix);
			dhp = (struct defraghdr *)crctbl - 1;
			ftot = dhp->idx + 1;
			printf("(%d files):\n",ftot);
			dhp = (struct defraghdr *)crctbl - ftot;
			crc = (ulong *)dhp-1;
			if (*crc != crc32((uchar *)dhp,(uchar *)tdp->end - (uchar *)dhp)) {
				printf("Table CRC failure\n");
				return(TFS_OKAY);
			}
		}
		else
			crctbl = (struct sectorcrc *)(dhp + ftot);

		printf("dhp=0x%lx, ftot=%d\n",(ulong)dhp,ftot);
		
		while(dhp < (struct defraghdr *)crctbl) {
			printf(" %s (dhp=0x%lx, idx=%ld):\n",
				dhp->fname,(ulong)dhp,dhp->idx);
			printf("   nda: 0x%08lx, ohdr: 0x%08lx\n",
				(ulong)dhp->nda,(ulong)dhp->ohdr);
			dhp++;
		}

		sbase = (uchar *)tdp->start;
		printf("crctbl at 0x%lx\n",(ulong)crctbl);
		for(i=0;i<tdp->sectorcount;i++) {
			if (addrtosector(sbase,&snum,&ssize,0) < 0)
				return(0);
			if (i == tdp->sectorcount-1) {
				ssize -= 							/* CRC table */
					(tdp->sectorcount * sizeof(struct sectorcrc));	
				ssize -= (ftot * DEFRAGHDRSIZ);		/* DHT table */
				ssize -= 4;							/* Crc of the tables */
			}
			calccrc = crc32(sbase,ssize);
			if (calccrc == crctbl[i].precrc)
				printf("crctbl[%d] (snum=%d) pre-pass\n",i,snum);
			else if (calccrc == crctbl[i].postcrc)
				printf("crctbl[%d] (snum=%d) post-pass\n",i,snum);
			else {
				printf("crctbl[%d] (snum=%d) test failed\n",i,snum);
				printf("pre: 0x%lx, post: 0x%lx,calc: 0x%lx\n",
					crctbl[i].precrc,crctbl[i].postcrc,calccrc);
			}
			sbase += ssize;
		}
	}
	return(TFS_OKAY);
}
#endif	/* DEFRAG_TEST_ENABLED */
#endif	/* INCLUDE_TF

⌨️ 快捷键说明

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