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

📄 tfsclean1.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 5 页
字号:
/* tfsclean1.c: *  This is one of several different versions of tfsclean().  This version *  is by far the most complex, but offers power-hit safety and minimal *  flash overhead.  It uses a "spare" sector to backup the *  "one-sector-at-a-time" defragmentation process. * *  General notice: *  This code is part of a boot-monitor package developed as a generic base *  platform for embedded system designs.  As such, it is likely to be *  distributed to various projects beyond the control of the original *  author.  Please notify the author of any enhancements made or bugs found *  so that all may benefit from the changes.  In addition, notification back *  to the author will allow the new user to pick up changes that may have *  been made by other users after this version of the code was distributed. * *  Note1: the majority of this code was edited with 4-space tabs. *  Note2: as more and more contributions are accepted, the term "author" *         is becoming a mis-representation of credit. * *  Original author:    Ed Sutter *  Email:              esutter@lucent.com *  Phone:              908-582-2351 */#include "config.h"#include "cpu.h"#include "stddefs.h"#include "genlib.h"#include "tfs.h"#include "tfsprivate.h"#include "flash.h"#include "monflags.h"#if INCLUDE_TFS#if DEFRAG_TEST_ENABLEDvoiddefragExitTestPoint(int val){    if ((DefragTestType == DEFRAG_TEST_EXIT) && (DefragTestPoint == val)) {        printf("\n+++++++++ EXIT @ TEST POINT(%d)\n",val);        CommandLoop();    }}#else#define defragExitTestPoint(val)#endif/* Variables for testing tfsclean(): * They are set up through arguments to "tfs clean" in tfscli.c. */int DefragTestType;int DefragTestPoint;int DefragTestSector;/* defragTick(): * Used to show progress, just to let the user know that we aren't * dead in the water. */static voiddefragTick(int verbose){    static int tick;    static char clockhand[] = { '|', '/', '-', '\\' };    if (!verbose && (!MFLAGS_NODEFRAGPRN())) {        if (tick > 3)            tick = 0;        printf("%c\b",clockhand[tick++]);    }}/* defragCrcTable(): * Return a pointer to the crc table for the specified TFS device. */struct sectorcrc *defragCrcTable(TDEV *tdp){    return((struct sectorcrc *)(tdp->end+1) - tdp->sectorcount);}/* defragSerase(): * Common function to call from within tfsclean() to erase a sector * and generate an error message if necessary. * * If DEFRAG_TEST_ENABLED is defined and the type/sector/point criteria * is met, then instead of erasing the sector; just change the first non-zero * byte to zero to corrupt it.  This essentially makes it a corrupted erase. */static intdefragSerase(int tag, int snum){    int ret = 0;#if DEFRAG_TEST_ENABLED    int ssize;    uchar *sbase, *send, zero;    printf("     serase_%02d(%02d)\n",tag,snum);    if ((DefragTestType == DEFRAG_TEST_SERASE) &&        (DefragTestSector == snum) && (DefragTestPoint == tag)) {            sectortoaddr(snum,&ssize,&sbase);            send = sbase+ssize;            zero = 0;            while(sbase < send) {                if (*sbase != 0) {                    tfsflashwrite((ulong *)sbase,(ulong *)&zero,1);                    break;                }                sbase++;            }            printf("DEFRAG_TEST_SERASE activated @ %d sector %d\n",tag,snum);            CommandLoop();    }    else#endif    ret = tfsflasherase(snum);    if (ret < 0) {        printf("tfsclean() serase erase failed: %d,%d,%d\n",snum,tag,ret);    }    return(ret);}/* defragFwrite(): * Common function to call from within tfsclean() to write to flash * and generate an error message if necessary. * If DEFRAG_TEST_ENABLED is defined and the test type is set to  * DEFRAG_TEST_FWRITE, then use APPRAMBASE as the source of the data * so that the end result is an errored flash write. */static intdefragFwrite(int tag, uchar *dest,uchar *src,int size){    int ret = 0;#if DEFRAG_TEST_ENABLED    int snum;    addrtosector((char *)dest,&snum,0,0);    printf("     fwrite_%02d(%d,0x%lx,0x%lx,%d)\n",        tag,snum,(ulong)dest,(ulong)src,size);    if ((DefragTestType == DEFRAG_TEST_FWRITE) &&        (DefragTestSector == snum) && (DefragTestPoint == tag)) {            tfsflashwrite((ulong *)dest,(ulong *)getAppRamStart(),size/2);            printf("DEFRAG_TEST_FWRITE activated @ %d sector %d\n",tag,snum);            CommandLoop();    }    else#endif    ret = tfsflashwrite((ulong *)dest,(ulong *)src,size);    if (ret < 0) {        printf("tfsclean() fwrite failed: 0x%lx,0x%lx,%d,%d\n",            (ulong)dest,(ulong)src,size,tag);    }    return(ret);}/* defragGetSpantype(): * With the incoming sector base and end (s_base, s_end), * determine the type of span that the incoming file (f_base, f_end) * has across it.  There are six different ways the spanning can * occur: *   1. begin and end in previous active sector (bpep); *   2. begin in previously active sector, end in this one (bpec); *   3. begin in previously active sector, end in later one (bpel); *   4. begin and end in this active sector (bcec); *   5. begin in this active sector, end in later one (bcel); *   6. begin and end in later active sector (blel); */static intdefragGetSpantype(char *s_base,char *s_end,char *f_base,char *f_end){    int spantype;    if (f_base < s_base) {        if ((f_end > s_base) && (f_end <= s_end))            spantype = SPANTYPE_BPEC;        else if (f_end > s_end)            spantype = SPANTYPE_BPEL;        else            spantype = SPANTYPE_BPEP;    }    else {        if (f_base > s_end)            spantype = SPANTYPE_BLEL;        else if (f_end <= s_end)            spantype = SPANTYPE_BCEC;        else            spantype = SPANTYPE_BCEL;    }    return(spantype);}/* defragGetSpantypeStr(): * Return a string that corresponds to the incoming state value. */static char *defragGetSpantypeStr(int spantype){    char *str;    switch(spantype) {    case SPANTYPE_BPEC:        str = "BPEC";        break;    case SPANTYPE_BLEL:        str = "BLEL";        break;    case SPANTYPE_BPEL:        str = "BPEL";        break;    case SPANTYPE_BPEP:        str = "BPEP";        break;    case SPANTYPE_BCEC:        str = "BCEC";        break;    case SPANTYPE_BCEL:        str = "BCEL";        break;    default:        str = "???";        break;    }    return(str);}/* defragEraseSpare(): * Erase the spare sector associated with the incoming TFS device. * The underlying flash driver SHOULD have a check so that it only * erases the sector if the sector is not already erased, so this * extra check (call to flasherased()) may not be necessary in * most cases. */static intdefragEraseSpare(TDEV *tdp){    int snum, ssize;    uchar *sbase;    if (addrtosector((char *)tdp->spare,&snum,&ssize,&sbase) < 0)        return(TFSERR_FLASHFAILURE);    if (!flasherased(sbase,sbase+ssize)) {        if (defragSerase(1,snum) < 0) {            return(TFSERR_FLASHFAILURE);        }    }    return(TFS_OKAY);}/* defragValidDSI(): * Test to see if we have a valid defrag state information (DSI) * area.  The DSI area, working back from tdp->end, consists of a * table of 32-bit crcs (one per sector), a table of defraghdr * structures (one per active file) and a 32-bit crc of the DSI * itself.  Knowing this format, we can easily step backwards into * the DSI space to see if it all makes sense. * If the table is 100% valid, then we will be able to step * backwards through the DSI to find the 32-bit crc of the DSI area. * If it matches, then we can be sure that the DSI is valid. * Return total number of files in header if the defrag header * table appears to be sane, else 0. */ static intdefragValidDSI(TDEV *tdp, struct sectorcrc **scp){    int     ftot, valid, lastssize;    uchar   *lastsbase;    struct  sectorcrc *crctbl;    ulong   hdrcrc, *crc;    struct  defraghdr   *dhp, dfhcpy;    ftot = valid = 0;    crctbl = defragCrcTable(tdp);    dhp = (struct defraghdr *)crctbl - 1;    dfhcpy = *dhp;    hdrcrc = dfhcpy.crc;    dfhcpy.crc = 0;    if (crc32((uchar *)&dfhcpy,DEFRAGHDRSIZ) == hdrcrc) {        ftot = dhp->idx + 1;        dhp = (struct defraghdr *)crctbl - ftot;        crc = (ulong *)dhp - 1;        if (crc32((uchar *)dhp,(uchar *)tdp->end-(uchar *)dhp) == *crc) {            if (scp)                *scp = crctbl;            return(ftot);        }    }    /* It's possible that the DSI space has been relocated to the spare     * sector, so check for that here...     */    addrtosector((char *)tdp->end,0,&lastssize,&lastsbase);    crctbl = ((struct sectorcrc *)(tdp->spare+lastssize) - tdp->sectorcount);    dhp = (struct defraghdr *)crctbl - 1;    dfhcpy = *dhp;    hdrcrc = dfhcpy.crc;    dfhcpy.crc = 0;    if (crc32((uchar *)&dfhcpy,DEFRAGHDRSIZ) == hdrcrc) {        ftot = dhp->idx + 1;        dhp = (struct defraghdr *)crctbl - ftot;        crc = (ulong *)dhp - 1;        if (crc32((uchar *)dhp,            (uchar *)(tdp->spare+lastssize-1) - (uchar *)dhp) == *crc) {#if DEFRAG_TEST_ENABLED            printf("TFS: DSI in spare\n");#endif            if (scp)                *scp = crctbl;            return(ftot);        }    }    return(0);}/* defragSectorInSpare(): * For each sector, run a CRC32 on the content of the spare * using the size of the sector in question.  If the calculated * crc matches that of the table, then we have located the sector * that has been copied to the spare. * This is a pain in the butt because we can't just run a CRC32 on * the spare sector itself because the size of the spare may not match * the size of the sector that was copied to it.  The source sector * might have been smaller; hence when we calculate the CRC32, we need * to use the size of the potential source sector. */static intdefragSectorInSpare(TDEV *tdp, struct sectorcrc *crctbl){    uchar   *sbase;    struct  defraghdr *dhp;    int     i, ssize, snum, ftot;    sbase = (uchar *)tdp->start;    dhp = (struct defraghdr *)crctbl - 1;    ftot = dhp->idx + 1;    for(i=0;i<tdp->sectorcount;i++) {        addrtosector(sbase,&snum,&ssize,0);        if (i == tdp->sectorcount - 1) {            ssize -=                            /* CRC table */                (tdp->sectorcount * sizeof(struct sectorcrc));            ssize -= (ftot * DEFRAGHDRSIZ);     /* DHT table */            ssize -= 4;                         /* Crc of the tables */        }        if (crc32((uchar *)tdp->spare,ssize) == crctbl[i].precrc)            return(snum);        sbase += ssize;    }    return(-1);}/* defragTouchedSectors(): * Step through the crc table and TFS flash space to find the first * and last sectors that have been touched by defragmentation. * This is used by defragGetState() to recover from an interrupted  * defragmentation, so a few verbose messages are useful to indicate * status to the user. */voiddefragTouchedSectors(TDEV *tdp,int *first, int *last){    uchar   *sbase;    struct  defraghdr *dhp;    struct  sectorcrc   *crctbl;    int     i, ssize, snum, ftot;    *first = -1;    *last = -1;    sbase = (uchar *)tdp->start;    crctbl = defragCrcTable(tdp);    dhp = (struct defraghdr *)crctbl - 1;

⌨️ 快捷键说明

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