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 + -
显示快捷键?