⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tfs.c

📁 flash文件系统实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* 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 + -