tfsclean1.c

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

C
2,107
字号
		tmpdhp = dhp;
		copytospare = 0;
		finfo.mode = FILLMODE_SPAREOVERLAP;
		for(;tmptot<ftot;tmptot++,tmpdhp++) {
			finfo.tdp = tdp;
			finfo.dhp = tmpdhp;
			finfo.asnum = activesnum;
	
			fullsize = TFSHDRSIZ + tmpdhp->filsize;
			new_fbase = tmpdhp->nda;
			new_fend = (new_fbase + fullsize);
	
			new_fspan = defragGetSpantype(activesbase,activesend,
				new_fbase,new_fend);
	
			if (new_fspan == SPANTYPE_BPEP) 
				continue;
			else if (new_fspan == SPANTYPE_BLEL)
				break;
	
			/* Now retrieve span information about header and data
			 * portions of the file (new and orig)...
			 */
			new_hbase = new_fbase;
			new_hend = new_hbase + TFSHDRSIZ;
			new_dbase = new_hbase + TFSHDRSIZ;
			new_dend = new_fend;
			orig_fend = ((char *)tmpdhp->ohdr + fullsize);
	
			new_hspan = defragGetSpantype(activesbase,activesend,
				new_hbase,new_hend);
			new_dspan = defragGetSpantype(activesbase,activesend,
				new_dbase,new_dend);
	
			/* If defragFillFlash() returns positive (with mode ==
			 * FILLMODE_SPAREOVERLAP set above), then we know that the
			 * spare sector must be loaded with a copy of this active
			 * sector, so we can break out of this loop at that point...
			 */
			finfo.fhdr = 1;
			fillstat = defragFillFlash(&finfo,new_hspan,&tmpactiveaddr,0);
			if (fillstat < 0)
				return(fillstat);	
			if (fillstat > 0) {
				copytospare = 1;
				break;
			}
			if (new_hspan == SPANTYPE_BCEL)
				break;
	
			finfo.fhdr = 0;
			fillstat = defragFillFlash(&finfo,new_dspan,&tmpactiveaddr,0);
			if (fillstat < 0)
				return(fillstat);	
			if (fillstat > 0) {
				copytospare = 1;
				break;
			}
			if (new_dspan == SPANTYPE_BCEL || new_dspan == SPANTYPE_BPEL)
				break;
		}
	}

	finfo.mode = FILLMODE_FWRITE;

	defragExitTestPoint(10002+activesnum);

	if (copytospare) {
		defragTick(verbose);
#if DEFRAG_TEST_ENABLED
		printf("     copying sector %d to spare\n",activesnum);
#endif
		if (defragFwrite(6,(uchar *)tdp->spare,activesbase,activessize) == -1) {
			printf("Failed to copy active %d to spare\n",activesnum);
			return(TFSERR_FLASHFAILURE);
		}
	}
#if DEFRAG_TEST_ENABLED
	else {
		printf("     copy saved\n");
	}
#endif

	defragTick(verbose);

	/* We can now begin actual modification of the active sector,
	 * so start off by eraseing it...
	 */
	defragExitTestPoint(10003+activesnum);

	if (defragSerase(4,activesnum) < 0)
		return(TFSERR_FLASHFAILURE);

	defragExitTestPoint(10004+activesnum);

	/* THIRD LOOP:
	 * Now we pass through the loop to do the real flash modifications...
	 */
	for(;tot<ftot;tot++,dhp++) {
		finfo.tdp = tdp;
		finfo.dhp = dhp;
		finfo.asnum = activesnum;

		fullsize = TFSHDRSIZ + dhp->filsize;
		new_fbase = dhp->nda;
		new_fend = (new_fbase + fullsize);

		new_fspan = defragGetSpantype(activesbase,activesend,
			new_fbase,new_fend);

		if (new_fspan == SPANTYPE_BPEP) 
			continue;
		else if (new_fspan == SPANTYPE_BLEL)
			break;

		if (verbose)
			printf("  File: %s\n",dhp->fname);

		/* Now retrieve span information about header and data
		 * portions of the file (new and orig)...
		 */
		new_hbase = new_fbase;
		new_hend = new_hbase + TFSHDRSIZ;
		new_dbase = new_hbase + TFSHDRSIZ;
		new_dend = new_fend;
		orig_fend = ((char *)dhp->ohdr + fullsize);

		new_hspan = defragGetSpantype(activesbase,activesend,
			new_hbase,new_hend);
		new_dspan = defragGetSpantype(activesbase,activesend,
			new_dbase,new_dend);

		/* At this point we have all the information we need to copy
		 * the appropriate amount of the file from orignal space
		 * to new space.
		 * We have to break the write up into two parts, the header
		 * (new_hspan) and the data (new_dspan) so we have to look
		 * at the spantype for each to determine what part of the
		 * header and/or data we are going to copy.
		 *
		 * Also, we must consider the possibility that the source
		 * data may be in the spare sector.  This would be the case
		 * if the active sector is the same sector that the original
		 * data was in.  If the source data is in the spare sector,
		 * then an added complication is the fact that it may not
		 * all be there, we may have to copy some from the spare,
		 * then some from the original space.
		 */
		finfo.fhdr = 1;
		fillstat = defragFillFlash(&finfo,new_hspan,&activeaddr,verbose);
		if (fillstat < 0)
			return(fillstat);	
		if (new_hspan == SPANTYPE_BCEL)
			break;

		finfo.fhdr = 0;
		fillstat = defragFillFlash(&finfo,new_dspan,&activeaddr,verbose);
		if (fillstat < 0)
			return(fillstat);	
		if (new_dspan == SPANTYPE_BCEL || new_dspan == SPANTYPE_BPEL)
			break;
		defragTick(verbose);
	}
	return(0);
}

static int
defragNewSectorCrc(TDEV *tdp, struct defraghdr *dht, int snum, ulong *newcrc)
{
	int		firstsnum;		/* number of first TFS sector */
	int		activesnum;		/* number of sector currently being written to */
	int		activessize;	/* size of active sector */
	char	*activeaddr;	/* offset being written to in the active sector */
	uchar	*activesbase;	/* base address of active sector */
	char	*activesend;	/* end address of active sector */
	struct	defraghdr *dhp;	/* pointer into defrag header table */
	int		fullsize;		/* size of file and header */
	char	*new_dend;		/* new end of data */
	char	*new_dbase;		/* new base of data */
	char	*new_hend;		/* new end of header */
	char	*new_hbase;		/* new base of header */
	char	*new_fend;		/* new end of file */
	char	*new_fbase;		/* new base of file */
	char	*orig_fend;		/* original end of file */
	int		new_fspan;		/* span type for new file */
	int		new_hspan;		/* span type for new header */
	int		new_dspan;		/* span type for new data */
	int		fillstat;		/* result of defragFillFlash() function call */
	int		ftot;
	char	*tmpactiveaddr;
	struct	fillinfo finfo;
	struct	sectorcrc	*crctbl;
	int		lastsnum, tot, sz, temp;

	/* Retrieve number of first TFS sector: */
	if (addrtosector((char *)tdp->start,&firstsnum,0,0) < 0)
		return(TFSERR_MEMFAIL);

	activesnum = snum + firstsnum;
	crctbl = defragCrcTable(tdp);

	/* Retrieve information about active sector: */
	if (sectortoaddr(activesnum,&activessize,&activesbase) == -1)
		return(TFSERR_MEMFAIL);

	if (addrtosector((char *)tdp->end,&lastsnum,0,0) < 0)
		return(TFSERR_MEMFAIL);

	dhp = (struct defraghdr *)crctbl - 1;
	ftot = dhp->idx + 1;
	dhp = dht;
	activeaddr = activesbase;
	tmpactiveaddr = activesbase;
	activesend = activesbase + activessize - 1;

	finfo.tdp = tdp;
	finfo.crcsz = 0;
	finfo.crc = 0xffffffff;
	finfo.asnum = activesnum;
	finfo.mode = FILLMODE_CRCONLY;

	for(tot=0;tot<ftot;tot++,dhp++) {
		finfo.dhp = dhp;

		fullsize = TFSHDRSIZ + dhp->filsize;
		new_fbase = dhp->nda;
		new_fend = (new_fbase + fullsize);

		new_fspan = defragGetSpantype(activesbase,activesend,
			new_fbase,new_fend);

		if (new_fspan == SPANTYPE_BPEP) 
			continue;
		else if (new_fspan == SPANTYPE_BLEL)
			break;

		/* Now retrieve span information about header and data
		 * portions of the file (new and orig)...
		 */
		new_hbase = new_fbase;
		new_hend = new_hbase + TFSHDRSIZ;
		new_dbase = new_hbase + TFSHDRSIZ;
		new_dend = new_fend;
		orig_fend = ((char *)dhp->ohdr + fullsize);

		new_hspan = defragGetSpantype(activesbase,activesend,
			new_hbase,new_hend);
		new_dspan = defragGetSpantype(activesbase,activesend,
			new_dbase,new_dend);

		finfo.fhdr = 1;
		fillstat = defragFillFlash(&finfo,new_hspan,&activeaddr,0);
		if (fillstat < 0)
			return(fillstat);	
		if (new_hspan == SPANTYPE_BCEL)
			break;

		finfo.fhdr = 0;
		fillstat = defragFillFlash(&finfo,new_dspan,&activeaddr,0);
		if (fillstat < 0)
			return(fillstat);	
		if (new_dspan == SPANTYPE_BCEL || new_dspan == SPANTYPE_BPEL)
			break;
	}
	sz = activessize - finfo.crcsz;

	/* If this is the last sector, then we must not include the space used
	 * for defrag state storage in the crc calculation.
	 * We deduct size of CRC table, DHT table and the crc of the DSI space...
	 */
	if (activesnum == lastsnum) {
		sz -= (tdp->sectorcount * sizeof(struct sectorcrc));	
		sz -= (ftot * DEFRAGHDRSIZ);
		sz -= 4;
	}
	while(sz) {
		temp = (finfo.crc ^ 0xff) & 0x000000FFL;
		finfo.crc = ((finfo.crc >> 8) & 0x00FFFFFFL) ^ crc32tab[temp];
		sz--;
	}
	*newcrc = ~finfo.crc;
	return(0);
}

/* defragBuildCrcTable():
 * Build the table of sector crcs.
 * This consists of a set of CRCs representing each sector
 * before defrag starts and after defrag has completed.  
 * One set for each sector.  This table is then used if the
 * defrag process is interrupted to determine the state of
 * the interrupted defragmentation process.
 */
int
defragBuildCrcTable(TDEV *tdp, struct defraghdr *dht, int verbose)
{
	ulong	crc;
	uchar	*sbase;
	int		i, ssize, dhstsize;
	struct	sectorcrc *crctbl;

	dhstsize = (ulong)(tdp->end+1) - (ulong)dht + 4;
	crctbl = defragCrcTable(tdp);

	/* The pre-defrag crc table...
	 * This one's easy because it is simply a crc for each of the current
	 * sectors.
	 */
	sbase = (uchar *)tdp->start;
	for(i=0;i<tdp->sectorcount;i++) {
		if (addrtosector(sbase,0,&ssize,0) < 0)
			return(-1);

		if (i == tdp->sectorcount-1)
			ssize -= dhstsize;
		
		/* The pre-defrag crc: */
		crc = crc32(sbase,ssize);
		if (defragFwrite(7,(uchar *)&crctbl[i].precrc,
			(uchar *)&crc,4) == -1) {
			return(-1);
		}

		/* The post-defrag crc: */
		if (defragNewSectorCrc(tdp,dht,i,&crc) < 0)
			return(-1);

		if (defragFwrite(8,(uchar *)&crctbl[i].postcrc,
			(uchar *)&crc,4) == -1) {
			return(-1);
		}

		sbase += ssize;

		defragTick(0);
	}
	return(0);
}

/* _tfsclean():
 * This is the front-end of the defragmentation process, following are the
 * basic steps of defragmentation...
 *
 * Build the Defrag State Information (DSI) area:
 * 1. Create a table of 32-bit CRCs, two for each sector.  One is the CRC
 *	  of the sector prior to beginning defragmentation and the other is
 *	  what will be the CRC of the sector after defragmentation has completed.
 *	  These CRCs are used to help recover from an interrupted defragmentation.
 * 2. Create a table of struct defraghdr structures, one for each file in
 *	  TFS that is currently active (not dead).
 * 3. Create a CRC of the tables created in steps 1 & 2.
 *
 * The data created in steps 1-3 is stored at the end of the last sector
 * used by TFS for file storage.  After this is created, the actual flash
 * defragmentation process starts.
 *
 * File relocation:
 * 4. Step through each sector in TFS flash space, process each file whose
 *	  relocated space overlaps with that sector.  As each sector is being
 *	  re-built, the original version of that sector is stored in the spare.
 *
 * End of flash cleanup:
 * 5. Run through the remaining, now unsused, space in TFS flash and make
 *	  sure it is erased.
 *
 * File check:
 * 6. Run a check of all of the relocated files to make sure everything is
 *	  still sane.
 * 
 * Defragmentation success depends on some coordination with tfsadd()...
 * Whenever a file is added to TFS, tfsadd() must verify that the space
 * needed for defrag overhead (defrag state & header tables) will be
 * available.  Also, tfsadd() must make sure that the defrag overhead will
 * always fit into one sector (the sector just prior to the spare).
 */

int
_tfsclean(TDEV *tdp, int restart, int verbose)
{
	int		dhstsize;		/* Size of state table overhead */
	int		firstsnum;		/* Number of first sector in TFS device. */
	int		lastsnum;		/* Number of last sector in TFS device. */
	int		lastssize;		/* Size of last sector in TFS device. */
	uchar	*lastsbase;		/* Base address of last sector in TFS device. */
	int		sectorcheck;	/* Used to verify proper TFS configuration. */
	struct	defraghdr *dht;	/* Pointer to defrag header table. */
	int		chkstat;		/* Result of tfscheck() after defrag is done. */
	int		ftot;			/* Total number of active files in TFS. */
	int		dtot;			/* Total number of deleted files in TFS. */
	int		fcnt;			/* Running file total, used in hdrtbl build. */
	TFILE	*tfp;			/* Misc file pointer */
	char	*newaddress;	/* Used to calculate "new" location of file. */
	struct	defraghdr	defrag;	/* Used to build defrag header table. */
	int		activesnum;		/* Sector being worked on restarted defrag. */
	struct	sectorcrc	*crctbl;	/* Pointer to table of per-sector crcs. */
	int		defrag_state;
	int		sidx, snum;
	char	*end;
	
	if (TfsCleanEnable < 0)
		return(TFSERR_CLEANOFF);

	/* If incoming TFS device pointer is NULL, return error
	 */
	if (!tdp)
		return(TFSERR_BADARG);

	/* If the 'restart' flag is set, then we only want to do a defrag if
	 * we determine that one is already in progress; so we have to look at
	 * the current state of the defrag state table to figure out if a defrag
	 * was active.  If not, just return.
	 */
	 restart = 0;  //stone add for debug
	if (restart) {
		defrag_state = defragGetState(tdp,&activesnum);
		switch(defrag_state) {
			case SECTOR_DEFRAG_INACTIVE:
			case SECTOR_DEFRAG_ABORT_RESTART:
				return(TFS_OKAY);
			case SCANNING_ACTIVE_SECTOR_1:
			case SCANNING_ACTIVE_SECTOR_2:
			case SCANNING_ACTIVE_SECTOR_3:
			case SCANNING_ACTIVE_SECTOR_4:

⌨️ 快捷键说明

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