?? tfs.c
字號:
/* 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. */ //comment by xxd 2003/9/10 //tfsDocommand = docommand; /* Start off with a buffer for 16 files. This is probably more than * will be used, so it avoids reallocations in tfsreorder(). */ 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 * and a power hit occurred. Refer to notes in tfsadd() for details. * There are a few cases to be covered here... * 1. there is no stale file; so there is nothing to do. * 2. there is a stale file, but no other file with the same name... * In this case, the stale file must be copied to another file (with the * TFS_NSTALE flag set) and the stale file is deleted. * 3. there is stale file and another file with the same name... * In this case, the stale file is simply deleted because the other file * with the same name is newer. */ static voidtfsstalecheck(int verbose){ int err; ulong flags; TDEV *tdp; TFILE *tfp, *tfpa; char buf[16]; tfpa = (TFILE *)0; for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { tfp = (TFILE *)tdp->start; tfpa = (TFILE *)0; while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) { if (tfpa) { if (!strcmp(TFS_NAME(tfp),TFS_NAME(tfpa))) { _tfsunlink(TFS_NAME(tfpa)); return; } } else if (TFS_STALE(tfp)) { tfpa = tfp; } } tfp = nextfp(tfp,tdp); } if (tfpa) break; } if (tfpa) { char name[TFSNAMESIZE+1]; strcpy(name,TFS_NAME(tfpa)); if (verbose) printf("TFS stale fixup (%s)...\n",name); flags = TFS_FLAGS(tfpa) | TFS_NSTALE; err = tfsadd(TFS_NAME(tfpa),TFS_INFO(tfpa),tfsflagsbtoa(flags,buf), (uchar *)(TFS_BASE(tfpa)),TFS_SIZE(tfpa)); /* If rewrite was successful, then remove the stale one; * else, leave it there and report the error. */ if (err == TFS_OKAY) { _tfsunlink(TFS_NAME(tfpa)); } else { printf("TFS stalecheck(%s) error: %s\n",name,tfserrmsg(err)); } }}/* tfsdevtblinit(): * Transfer the information in tfsdevtbl (in tfsdev.h) to tfsDeviceTbl[]. * In most cases, this will be a simple copy. If the device flag is set * to indicate that the initalization is dynamic, then use the flash * ops to retrieve the information from the specified bank. * * For dynamic configuration, the "start" member of the tfsdev structure * must be set in tfsdev.h and the "devinfo & TFS_DEVINFO_BANKMASK" area * must contain the number of the last flash bank that is to be part of * the TFS device. Typically this value is the same bank number as the * starting bank, but it could span across multiple contiguous banks * if the hardware is set up that way. * * To support the use of top-boot devices, plus the TFS requirement that * the SPARE sector be at-least as large as any other sector in the device, * this code will automatically step down the sector list until it finds * the first large sector below all the small ones usually at the top of * a top-boot device. The call to lastlargesector() takes care of this. * * NOTE: * This dynamic configuration assumes that the end of the TFS space is * just below the beginning of the spare space. * */voidtfsdevtblinit(void){ int i, startsector, endsector, bank; TDEV *tDp, *tdp; for(i=0;i<TFSDEVTOT;i++) { tdp = &tfsdevtbl[i]; tDp = &tfsDeviceTbl[i]; *tDp = *tdp; if (i == TFSDEVTOT-1) break; if (tdp->devinfo & TFS_DEVINFO_DYNAMIC) { bank = tDp->devinfo & TFS_DEVINFO_BANKMASK; /* The spare sector may not be the last sector in the device... * device. Especially if the device is TopBoot type. */ if (lastlargesector(bank,&endsector, (int *)&tDp->sparesize,(uchar **)&tDp->spare) == -1) break; tDp->end = tDp->spare - 1; if (addrtosector((uchar *)tDp->start,&startsector,0,0) == -1) break; tDp->sectorcount = endsector - startsector; } }}/* tfsstartup(): * Called at system startup to get things properly initialized. */voidtfsstartup(){ tfsdevtblinit(); tfsclear((TDEV *)0); tfsfixup(3,0); tfsstalecheck(1);}/* tfsexec: Treat the file as machine code that is COFF or ELF. */static inttfsexec(TFILE *fp,int verbose){ int err, (*entry)(); long address; err = tfsloadebin(fp,verbose,&address,0); if (err != TFS_OKAY) return(err); entry = (int(*)())address; ctxAPP(); /* Change context to APPLICATION. */ entry(); /* Call entrypoint (may not return). */ ctxMON(); /* Change context to APPLICATION. */ return(TFS_OKAY);}/* tfsmemset(): * Superset of memset(). Includes verbose option plus verification after * set. */inttfsmemset(uchar *to,uchar val,int count,int verbose,int verifyonly){ int failed; uchar *end; failed = 0; if (verbose) { printf("%s %7d bytes at 0x%08lx to 0x%02x", verifyonly ? "vrfy" : "set ",count,(ulong)to,val); } if (count == 0) goto done; end = to+count; if (verifyonly) { while(to < end) { if (*to++ != val) { failed = 1; break; } } } else { while(to < end) { *to = val; if (*to++ != val) { failed = 1; break; } } }done: if (verbose) { if (failed) printf(" failed"); else if (verifyonly) printf(" OK"); printf("\n"); } if (failed) return(TFSERR_MEMFAIL); else return(TFS_OKAY);}/* tfsmemcpy(): * Superset of memcpy(). Includes verbose option plus verification after * copy. Takes advantage of address alignment when possible. */inttfsmemcpy(uchar *to,uchar *from,int count,int verbose,int verifyonly){ int err; register uchar *end; if (verbose) printf("%s %7d bytes from 0x%08lx to 0x%08lx", verifyonly ? "vrfy" : "copy", count,(ulong)from,(ulong)to); if (verifyonly) { while(count) { if (*to != *from) break; to++; from++; count--; } if (count) { if (verbose) { printf(" FAILED\n"); printf(" (0x%02x @ 0x%08lx should be 0x%02x)\n", *to,(ulong)to,*from); } return(TFSERR_MEMFAIL); } else if (verbose) printf(" OK\n"); return(TFS_OKAY); } if (count == 0) goto done; if (to != from) { err = 0; if (!((int)to & 3) && !((int)from & 3) && !(count & 3)) { register ulong *lto, *lfrom, *lend; count >>= 2; lto = (ulong *)to; lfrom = (ulong *)from; lend = lto + count; while(lto < lend) { *lto = *lfrom; if (*lto != *lfrom) { err = 1; break; } lto++; lfrom++; } } else if (!((int)to & 1) && !((int)from & 1) && !(count & 1)) { register ushort *sto, *sfrom, *send; count >>= 1; sto = (ushort *)to; sfrom = (ushort *)from; send = sto + count; while(sto < send) { *sto = *sfrom; if (*sto != *sfrom) { err = 1; break; } sto++; sfrom++; } } else { end = to + count; while(to < end) { *to = *from; if (*to != *from) { err = 1; break; } to++; from++; } } if (err) { if (verbose) printf(" failed\n"); return(TFSERR_MEMFAIL); } }done: if (verbose) printf("\n"); return(TFS_OKAY);}/* struct tfsran: Used by tfsrunboot only. No need to put this in tfs.h. */struct tfsran { char name[TFSNAMESIZE+1];};/* tfsrunboot(): * This function is called at monitor startup. It scans the list of * files built by tfsreorder() and executes each file in the list that has * the BRUN flag set. As each file is run its name is added to the * ranlist[] table. * * After each file is run, there is a check made to see if the flash has * been modified. If yes, then tfsreorder() is run again and we start * over at the top of the list of files organized by tfsreorder(). As * we step through the tfsAlist[] array, if the file has a BRUN flag set * but it is already in the ranlist[] table, it is not run again. * * This scheme allows a file in the initial list of BRUN files to modify * the file list without confusing the list of files that are to be run. * Files (even new BRUN files) can be added to the list by some other BRUN * file, and these new files will be run. */inttfsrunboot(){ static struct tfsran *ranlist; char *argv[2]; int rancnt, aidx, ridx, err, fmodcnt; /* The argv[] array is used by tfsrun(); argv[0] is name of file to be * executed, argv[1] must be nulled to indicate no command line args * passed to the BRUN file/script. */ argv[1] = (char *)0; /* Keep a local copy of tfsFmodCount so that we can determine if flash * was modified by one of the BRUN files executed. */ fmodcnt = tfsFmodCount; /* Create list of file pointers (tfsAlist[]) in alphabetical order * based on name... */ if ((err = tfsreorder()) < 0) { printf("tfsrunboot() reorder1: %s\n",tfserrmsg(err)); return(-1); } /* Clear the ranlist pointer. This pointer is the base address of a * list of file names that have been run. */ rancnt = 0; ranlist = (struct tfsran *)0;restartloop: for (aidx=0;tfsAlist[aidx];aidx++) { char fname[TFSNAMESIZE+1]; int alreadyran; TFILE *fp; struct tfsran *rp; fp = tfsAlist[aidx]; strcpy(fname,TFS_NAME(fp)); /* If the file has no BRUN flag set, just continue. If a BRUN flag * is set, then see if the file has already been run. If yes, then * just continue; else run the file. */ alreadyran = 0; if (fp->flags & (TFS_BRUN | TFS_QRYBRUN)) { for(ridx=0;ridx<rancnt;ridx++) { if (!strcmp(ranlist[ridx].name,fname)) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -