tfsclean1.c

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

C
2,107
字号
 * of the file data may be the same sector as the active one (meaning that
 * the source is taken from the spare).  It is within this function that
 * the active sector is actually modified and it assumes that the portion
 * of the active sector to be written to is already erased.
 * 
 * 
 * SPANTYPE_BCEC:
 * In this case, the file starts in a sector prior to the currently active
 * sector and ends in the active sector...
 * -----------|----------|----------|----------|---------|---------|----------
 * |          |          |          |          |         |         |         |
 * |          |          |<-active->|          |         |         |  SPARE  |
 * |          |          |  sector  |          |         |         |  SECTOR |
 * |          |          |          |          |         |         |         |
 * |          |          | newfile  |          |         |         |         |
 * |          |          | |<-->|   |          |         |         |         |
 * -----------|----------|----------|----------|---------|---------|----------
 *
 * 
 * SPANTYPE_BPEC:
 * In this case, the file starts in a sector prior to the currently active
 * sector and ends in the active sector...
 * -----------|----------|----------|----------|---------|---------|----------
 * |          |          |          |          |         |         |         |
 * |          |          |          |<-active->|         |         |  SPARE  |
 * |          |          |          |  sector  |         |         |  SECTOR |
 * |          |          |          |          |         |         |         |
 * |          |      |<----newfile----->|      |         |         |         |
 * |          |          |          |          |         |         |         |
 * -----------|----------|----------|----------|---------|---------|----------
 *
 * 
 * SPANTYPE_BPEL:
 * In this case, the file starts in some sector prior to the currently
 * active sector and ends in some sector after the currently active
 * sector...
 * -----------|----------|----------|----------|---------|---------|----------
 * |          |          |          |          |         |         |         |
 * |          |          |<-active->|          |         |         |  SPARE  |
 * |          |          |  sector  |          |         |         |  SECTOR |
 * |          |          |          |          |         |         |         |
 * |       |<---------- newfile------------------->|     |         |         |
 * |          |          |          |          |         |         |         |
 * -----------|----------|----------|----------|---------|---------|----------
 *
 *
 * SPANTYPE_BCEL:
 * In this case, the file starts in the active sector and ends in
 * a later sector.
 * -----------|----------|----------|----------|---------|---------|----------
 * |          |          |          |          |         |         |         |
 * |          |<-active->|          |          |         |         |  SPARE  |
 * |          |  sector  |          |          |         |         |  SECTOR |
 * |          |          |          |          |         |         |         |
 * |          |      |<----newfile----->|      |         |         |         |
 * |          |      ****|          |          |         |         |         |
 * -----------|----------|----------|----------|---------|---------|----------
 */
static int
defragFillFlash(struct fillinfo *fip,int spantype,char **activeaddr,int verbose)
{
	char 	*hp;
	TFILE	nfhdr;
	struct	defraghdr *dhp;	
	int		ohdroffset, nhdroffset;
	uchar	*ovly, *src, *activesbase;
	int		ovlysz, srcsz, activessize;

	src = 0;
	srcsz = 0;
	nhdroffset = ohdroffset = 0;
	dhp = fip->dhp;

	if (verbose >= 2) {
		printf("   defragFillFlash %s %s\n",fip->fhdr ? "hdr" : "dat",
			defragGetSpantypeStr(spantype));
	}

	if (spantype == SPANTYPE_BCEC) {
		if (fip->fhdr) {
			src = (uchar *)dhp->ohdr;
			srcsz = TFSHDRSIZ;
		}
		else {
			src = (uchar *)dhp->ohdr+TFSHDRSIZ;
			srcsz = dhp->filsize;
		}
	}
	else if (spantype == SPANTYPE_BPEC) {
		if (fip->fhdr) {
			/* Calculate the offset into the header at which point a
			 * sector boundary occurs.  Do this for both the old (before
			 * defrag relocation) and new (after defrag relocation)
			 * location of the header.
			 */
			nhdroffset = TFSHDRSIZ - (dhp->neso - dhp->filsize);
			ohdroffset = TFSHDRSIZ - (dhp->oeso - dhp->filsize);
			srcsz = dhp->oeso - dhp->filsize + (ohdroffset - nhdroffset);
			src = (uchar *)dhp->ohdr + nhdroffset;
		}
		else {
			src = (uchar *)dhp->ohdr + TFSHDRSIZ + (dhp->filsize - dhp->neso);
			srcsz = dhp->neso;
		}
	}
	else if (spantype == SPANTYPE_BCEL) {
		if (sectortoaddr(fip->asnum,&activessize,&activesbase) == -1)
			return(TFSERR_MEMFAIL);

		if (fip->fhdr) {
			src = (uchar *)dhp->ohdr;
		}
		else {
			src = (uchar *)dhp->ohdr+TFSHDRSIZ;
		}
		srcsz = (activesbase + activessize) - (uchar *)*activeaddr;
	}
	else if (spantype == SPANTYPE_BPEL) {
		if (sectortoaddr(fip->asnum,&activessize,0) == -1)
			return(TFSERR_MEMFAIL);

		if (fip->fhdr) {
			src = (uchar *)dhp->ohdr;
		}
		else {
			src = (uchar *)dhp->ohdr+TFSHDRSIZ;
		}

		src += ((*activeaddr - dhp->nda) - TFSHDRSIZ);
		srcsz = activessize; 
	}
	else {
		return(0);
	}

	/* Determine if any portion of the source was part of the sector that
	 * is now the active sector..  If yes (ovlysz > 0), then we must
	 * deal with the fact that some (or all) of the fill source is in the
	 * spare sector...
	 */
	if (inSector(fip->tdp,fip->asnum,src,srcsz,&ovly,&ovlysz) < 0)
		return(TFSERR_MEMFAIL);

	/* If the mode is not FILLMODE_FWRITE, then we don't do any of the
	 * flash operations.  We are in this function only to determine
	 * if we need to copy the active sector to the spare prior to 
	 * starting the modification of the active sector.
	 */
	if (fip->mode == FILLMODE_FWRITE) {
		if (fip->fhdr) {
			hp = (char *)&nfhdr;
			if (ovlysz) {
				memcpy(hp+nhdroffset,ovly,ovlysz);
				if (ovlysz != srcsz) {
					memcpy(hp+nhdroffset+ovlysz,(char *)src+ovlysz,
						srcsz-ovlysz);
				}
			}
			else {
				nfhdr = *dhp->ohdr;
			}
			nfhdr.next = dhp->nextfile;
			if (defragFwrite(2,*activeaddr,hp+nhdroffset,srcsz) == -1)
				return(TFSERR_FLASHFAILURE);
		}
		else {
			if (ovlysz) {
				if (defragFwrite(3,*activeaddr,(char *)ovly,ovlysz) == -1)
					return(TFSERR_FLASHFAILURE);
				if (ovlysz != srcsz) {
					if (defragFwrite(4,*activeaddr+ovlysz,(char *)src+ovlysz,
						srcsz-ovlysz) == -1)
						return(TFSERR_FLASHFAILURE);
				}
			}
			else {
				if (defragFwrite(5,*activeaddr,(char *)src,srcsz) == -1)
					return(TFSERR_FLASHFAILURE);
			}
		}
	}
	else if (fip->mode == FILLMODE_CRCONLY) {
		register uchar	*bp;
		int		sz, temp;

		if (fip->fhdr) {
			hp = (char *)&nfhdr;
			nfhdr = *dhp->ohdr;
			nfhdr.next = dhp->nextfile;
			bp = hp + nhdroffset;
		}
		else {
			bp = (uchar *)src;
		}
		sz = srcsz;
		fip->crcsz += sz;
		while(sz) {
			temp = (fip->crc ^ *bp++) & 0x000000FFL;
			fip->crc = ((fip->crc >> 8) & 0x00FFFFFFL) ^ crc32tab[temp];
			sz--;
		}
	}
	*activeaddr += srcsz;

	if ((spantype == SPANTYPE_BCEC || spantype == SPANTYPE_BPEC) &&
		(!fip->fhdr) && ((ulong)*activeaddr & 0xf)) {
		int		sz, temp, modfixsize;

		modfixsize = (TFS_FSIZEMOD - ((ulong)*activeaddr & (TFS_FSIZEMOD-1)));
		*activeaddr += modfixsize;
		if (fip->mode == FILLMODE_CRCONLY) {
			sz = modfixsize;
			fip->crcsz += sz;
			while(sz) {
				temp = (fip->crc ^ 0xff) & 0x000000FFL;
				fip->crc = ((fip->crc >> 8) & 0x00FFFFFFL) ^ crc32tab[temp];
				sz--;
			}
		}
	}

	/* Return ovlysz so that the caller will know if this function
	 * needed the spare sector.  This is used in the "mode = SPARE_OVERLAP"
	 * pass of defragFillActiveSector().
	 */
	return(ovlysz);
}

/* defragFillActiveSector():
 * This and defragFillFlash() are the workhorses of the tfsclean() function.
 * The bulk of this function is used to determine if we need to do anything
 * to the active sector and if so, do we need to copy the active sector to
 * the spare prior to erasing it.
 * The first loop in this function determines whether we need to do anything
 * at all with this sector (it may not be touched by the defragmentation).
 * The second loop determines if we have to copy the active sector to the
 * spare prior to erasing the active sector.
 * The final loop in this function does the call to defragFillFlash()
 * to do the actual flash writes.
 */
static int
defragFillActiveSector(TDEV *tdp, int ftot, int snum, int verbose)
{
	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 *sdhp;/* pointer into defrag hdr table in spare */
	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		noreloctot;		/* number of files spanning the active sector */
							/* that do not have to be relocated */
	int		tmptot;			/* temps used for the "SPARE_OVERLAP" mode */
	char	*tmpactiveaddr;
	struct	defraghdr *tmpdhp;
	struct	fillinfo finfo;
	struct	sectorcrc	*crctbl;
	int		lastsnum, tot;
	int		copytospare;
	int		lastfileisnotrelocated;

	/* 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 (verbose)
		printf(" Active sector: %3d @ 0x%lx\n",activesnum,(ulong)activesbase);

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

	/* Establish a pointer to the defrag header table.
	 * For the case when the active sector is the last sector, the defrag
	 * header table will be in the spare, so we also establish a pointer
	 * to that space...
	 */
	dhp = (struct defraghdr *)crctbl;
	dhp -= ftot;
	sdhp = (struct defraghdr *)(tdp->spare+activessize -
			(tdp->sectorcount * sizeof(struct sectorcrc)));
	sdhp -= ftot;

	activeaddr = activesbase;
	tmpactiveaddr = activesbase;
	activesend = activesbase + activessize - 1;

	/* FIRST LOOP:
	 * See if we need to do anything...
	 * In this state, we are simply checking to see if anything is going
	 * to cause the currently active sector to be written to.
	 * If yes, then we need to copy it to the spare and start the
	 * modification process; else, we just return and do nothing
	 * to this sector.
	 * For each file in the defrag header table that is destined for
	 * the address space occupied by the currently active sector, copy
	 * that file (header and data) to the active sector...
	 * Note that it may only be a partial copy, depending on the size
	 * of the file and the amount of space left in the active sector.
	 */

	noreloctot = 0;
	new_fspan = SPANTYPE_UNDEF;
	lastfileisnotrelocated = 0;
	for(tot=0;tot<ftot;tot++,dhp++,sdhp++) {
		fullsize = TFSHDRSIZ + dhp->filsize;
		new_fbase = dhp->nda;
		new_fend = (new_fbase + fullsize);

		/* We must figure out how the new version of the file will
		 * span across the active sector.
		 * See defragGetSpantype() for details.
		 */
		new_fspan = defragGetSpantype(activesbase,activesend,
			new_fbase,new_fend);

		/* If the file we are looking at entirely spans a sector that is
		 * prior to the currently active sector, then we just continue
		 * through the list.
		 * If the file entirely spans a sector that is after the
		 * currently active sector, then we are done with this active sector.  
		 * If the file falls within the active sector in any way, and its
		 * new location does not match its old location, then we
		 * break out of this loop and begin the modification of this
		 * active sector...
		 */
		if (new_fspan == SPANTYPE_BLEL)
			return(0);
		
		if (new_fspan != SPANTYPE_BPEP) {
			if (dhp->nda == (char *)dhp->ohdr) {
				noreloctot++;
				if (tot == ftot-1) {
					lastfileisnotrelocated = 1;
					if (verbose > 1)
						printf("  last file not relocated\n");
				}
			}
			else
				break;
		}
	}

	/* If tot == ftot, then we got through the entire loop above without
	 * finding a file that needs to be relocated into this active sector.
	 * This means one of two things: either all the files fall into a 
	 * sector prior to this active sector, or the files in this active
	 * sector do not need to be relocated.  In either case, we simply
	 * return without touching this sector.
	 * Note that we also keep track of the possibility that the last file
	 * may not be relocated.  If this ends up to be the case, then we are
	 * simply cleaning up one or more dead files after a full set of active
	 * files, so we should clean up the sector.
	 */
	if ((tot == ftot) && (lastfileisnotrelocated == 0))
		return(0);

	/* If tot != ftot, then we must subtract noreloctot from tot so that
	 * we establish 'tot' as the index into the first file that must be
	 * copied to the active sector...
	 */
	if (noreloctot) {
		tot -= noreloctot;
		dhp -= noreloctot;
		sdhp -= noreloctot;
	}

	/* Exit immediately before cleaning up the spare... */
	defragExitTestPoint(10000+activesnum);

	/* Since we got here, we know that we have to do some work on the
	 * currently active sector.  We may not have to copy it to the spare,
	 * but we will erase the spare anyway because the sector erase is
	 * supposed to be smart enough to avoid the erase if it is already 
	 * erased.  This should be handled by the flash driver because in
	 * ALL cases the erase should be avoided if possible.
	 */
	if (defragEraseSpare(tdp) < 0)
		return(TFSERR_FLASHFAILURE);

	/* Exit immediately after cleaning up the spare... */
	defragExitTestPoint(10001+activesnum);

	/* If the active sector is the last sector (which would contain the
	 * defrag header table), then we reference the copy of the table that
	 * is in the spare...
	 * Also, if this is the last sector, then we HAVE to copy it to 
	 * spare, so we can skip the 2nd loop that attempts to determine
	 * if we need to do it.
	 */
	if (activesnum == lastsnum) {
		dhp = sdhp;
		copytospare = 1;
	}
	else {
		/* SECOND LOOP:
		 * See if we need to copy the active sector to the spare...
		 * We do this by continuing the loop we started above.  Notice that
		 * we do an almost identical loop again below this.
		 * On this pass through the loop we are only checking to see if it is
		 * necessary to copy this active sector to the spare.
		 */
		tmptot = tot;

⌨️ 快捷键说明

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