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

📄 tfs.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 5 页
字号:
/* tfs.c: *  Tiny File System *  TFS supports the ability to store/access files in flash.  The TFS *  functions provide a command at the monitor's user interface (the *  "tfs" command) as well as a library of functions that are available to *  the monitor/application code on this target (TFS api). * *  The code that supports TFS in the MicroMonitor package spans across  *  several files.  This is done so that various pieces of TFS can optionally *  be compiled in or out (using INCLUDE_XXX macros in config.h) of the *  monitor package... * *  tfs.c: *      Core TFS code that cannot be optionally omitted without eliminating *      the TFS facility from the monitor. *   *  tfsapi.c: *      This file contains the code that supports the application's ability *      to use the TFS api.  Since some of the api is used by the monitor *      itself, not all of the api-specific code is there, some of it is *      in tfs.c. * *  tfscleanX.c: *      TFS can be configured with one of several different flash defrag *      mechanisms.  Currently, tfsclean[123].c are available. * *  tfscli.c: *      If you don't need the "tfs" command in your command line interface, *      then the code in this file can be omitted. * *  tfsloader.c: *      TFS can support COFF, ELF or A.OUT binary file formats.  The code *      to load each of these formats from flash to RAM is here. * *  tfslog.c: *      If there is a need to log flash interaction to a file, then this *      file contains code to support that. * * *  NOTES: *  * Dealing with multiple task access: *    Since the monitor is inherently a single threaded program *    potentially being used in a multi-tasking environment, the monitor's *    access functions (API) must be provided with a lock/unlock  *    wrapper that will guarantee sequential access to all of the monitor  *    facilities.  Refer to monlib.c to see this implementation.  This *    provides the protection needed by TFS to keep multiple "mon_" *    functions from being executed by different tasks. *    Note that originally this was supported with tfsctrl(TFS_MUTEX ) and *    it only protected the tfs API functions.  This turned out to be *    insufficient because it did not prevent other tasks from calling *    other non-tfs functions in the monitor while tfs access (and *    potentially, flash update) was in progress.  This meant that a flash *    update could be in progress and some other task could call mon_getenv() *    (for example).  This could screw up the flash update because *    mon_getenv() might be fetched out of the same flash device that *    the TFS operation is being performed on. * *  * Dealing with cache coherency: *    I believe the only concern here is that Icache must be invalidated *    and Dcache must be flushed whenever TFS does a memory copy that may *    ultimately be executable code.  This is handled at the end of the *    tfsmemcpy function by calling flushDcache() and invalidateIcache(). *    It is the application's responsibility to give the monitor the *    appropriate functions (see assigncachefuncs()) if necessary. * *  * Configuring a device to run as TFS memory: *    Assuming you are using power-safe cleanup... *    TFS expects that on any given device used for storage of files, the *    device is broken up into some number of sectors with the last sector *    being the largest and used as the spare sector for defragmentation. *    All other sector sizes must be smaller than the SPARE sector and the *    sector just prior to the spare is used for defragmentation state *    overhead.  This sector should be large enough to allow the overhead  *    space to grow down from the top without filling the sector.  For most *    flash devices, these two sectors (spare and overhead) are usually the *    same size and are large.  For FlashRam, the device should be configured *    so that these two sectors are large.  The spare sector will never be *    allowed to contain any file information (because it is 100% dedicated to *    the defragmentation process) and the sector next to this can have files *    in it, but the overhead space is also in this sector. * *  * Testing TFS: *    There are three files dedicated to testing the file system.  Two of them *    (tfstestscript & tfstestscript1) are scripts that are put into the *    file system and run.  The third file (tfstest.c) is a piece of code  *    that can be built into a small application that runs out of TFS to test *    all of the API functionality. *    - tfstestscript: *      This script is used to simply bang on normal defragmentation.  It *      builds files with sizes and names based on the content of memory *      starting at $APPRAMBASE.  Changing the content of memory starting at *      $APPRAMBASE will change the characteristics of this test so it is *      somewhat random.  It is not 100% generic, but can be used as a *      base for testing TFS on various systems. *    - tfstestscript1: *      This script is used to bang on the power-safe defragmentation of *      TFS.  It simulates power hits that might occur during defragmentation. *      This script assumes that the monitor has been built with the *      DEFRAG_TEST_ENABLED flag set. *    - tfstest.c: *      This code can be built into a small application that will thoroughly *      exercise the TFS API.  This file can also be used as a reference for *      some examples of TFS api usage. * *  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 "tfsdev.h"#include "flash.h"#include "cli.h"#if INCLUDE_TFSchar    *(*tfsGetAtime)(long,char *,int);long    (*tfsGetLtime)(void);int     (*tfsDocommand)(char *,int);TDEV    tfsDeviceTbl[TFSDEVTOT];TFILE   **tfsAlist;struct  tfsdat tfsSlots[TFS_MAXOPEN];long    tfsTrace;int     TfsCleanEnable;static long     tfsFmodCount;static int      tfsAlistSize, tfsOldDelFlagCheckActive;/* tfsflgtbl & tfserrtbl: *  Tables that establish an easy lookup mechanism to convert from *  bitfield to string or character. *  Note that TFS_ULVL0 is commented out.  I leave it in here as a place *  holder (comment), but it actually is not needed becasue ulvl_0 is the *  default if no other ulvl is specified. */struct tfsflg tfsflgtbl[] = {    { TFS_BRUN,         'b',    "run_at_boot",          TFS_BRUN },    { TFS_QRYBRUN,      'B',    "qry_run_at_boot",      TFS_QRYBRUN },    { TFS_EXEC,         'e',    "executable",           TFS_EXEC },    { TFS_SYMLINK,      'l',    "symbolic link",        TFS_SYMLINK },    { TFS_EBIN,         'E',    TFS_EBIN_NAME,          TFS_EBIN },    { TFS_IPMOD,        'i',    "inplace_modifiable",   TFS_IPMOD },    { TFS_UNREAD,       'u',    "ulvl_unreadable",      TFS_UNREAD },/*  { TFS_ULVL0,        '0',    "ulvl_0",               TFS_ULVLMSK }, */    { TFS_ULVL1,        '1',    "ulvl_1",               TFS_ULVLMSK },    { TFS_ULVL2,        '2',    "ulvl_2",               TFS_ULVLMSK },    { TFS_ULVL3,        '3',    "ulvl_3",               TFS_ULVLMSK },    { TFS_CPRS,         'c',    "compressed",           TFS_CPRS },    { 0, 0, 0, 0 }};static struct tfserr tfserrtbl[] = {    { TFS_OKAY,             "no error" },    { TFSERR_NOFILE,        "file not found" },    { TFSERR_NOSLOT,        "max fps opened" },    { TFSERR_EOF,           "end of file" },    { TFSERR_BADARG,        "bad argument" },    { TFSERR_NOTEXEC,       "not executable" },    { TFSERR_BADCRC,        "bad crc" },    { TFSERR_FILEEXISTS,    "file already exists" },    { TFSERR_FLASHFAILURE,  "flash operation failed" },    { TFSERR_WRITEMAX,      "max write count exceeded" },    { TFSERR_RDONLY,        "file is read-only" },    { TFSERR_BADFD,         "invalid descriptor" },    { TFSERR_BADHDR,        "bad binary executable header" },    { TFSERR_CORRUPT,       "corrupt file" },    { TFSERR_MEMFAIL,       "memory failure" },    { TFSERR_NOTIPMOD,      "file is not in-place-modifiable" },    { TFSERR_FLASHFULL,     "out of flash space" },    { TFSERR_USERDENIED,    "user level access denied" },    { TFSERR_NAMETOOBIG,    "name or info field too big" },    { TFSERR_FILEINUSE,     "file in use" },    { TFSERR_SCRIPTINSUB,   "can't put script in subroutine" },    { TFSERR_NOTAVAILABLE,  "tfs facility not available" },    { TFSERR_BADFLAG,       "bad flag" },    { TFSERR_CLEANOFF,      "defragmentation is disabled" },    { TFSERR_FLAKEYSOURCE,  "dynamic source data" },    { 0,0 }};/* dummyAtime() & dummyLtime(): *  These two functions are loaded into the function pointers as defaults *  for the time-retrieval stuff used in TFS. */static char *dummyAtime(long tval,char *buf,int buflen){/*  strcpy(buf,"Fri Sep 13 00:00:00 1986"); */    *buf = 0;    return(buf);}static longdummyLtime(void){    return(TIME_UNDEFINED);}/* getdfsdev(): *  Input is a file pointer; based on that pointer return the appropriate *  device header pointer.  If error, just return 0. *  A "device" in TFS is some block of some type of memory that is assumed *  to be contiguous space that can be configured as a block of sectors (to *  look like flash).  For most systems, there is only one (the flash);  *  other systems may have battery-backed RAM, etc... *  Note that this is not fully implemented. */static TDEV *gettfsdev(TFILE *fp){    TDEV *tdp;    for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {        if ((fp >= (TFILE *)tdp->start) &&            (fp < (TFILE *)tdp->end))            return(tdp);    }    return(0);}TDEV *gettfsdev_fromprefix(char * prefix, int verbose){    TDEV *tdp;    for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {        if (!strcmp(prefix,tdp->prefix))            return(tdp);    }    if (verbose)        printf("Bad device prefix: %s\n",prefix);    return(0);}/* tfsflasherase(), tfsflasheraseall() & tfsflashwrite(): *  Wrappers for corresponding flash operations.  The wrappers are used *  to provide one place for the incrmentation of tfsFmodCount. */inttfsflasheraseall(TDEV *tdp){    int snum, last;    if (tfsTrace > 2)        printf("     tfsflasheraseall(%s)\n",tdp->prefix);    tfsFmodCount++;    /* Erase the sectors within the device that are used for file store... */    if (addrtosector((char *)tdp->start,&snum,0,0) < 0)        return(TFSERR_MEMFAIL);    last = snum + tdp->sectorcount;    while(snum < last) {        if (AppFlashErase(snum++) == -1)            return(TFSERR_MEMFAIL);    }    /* Erase the spare (if there is one)...     * (if this system is configured with tfsclean2.c, then     * there is no need for a spare sector).     */    if (tdp->spare) {        if (addrtosector((char *)tdp->spare,&snum,0,0) < 0)            return(TFSERR_MEMFAIL);        if (AppFlashErase(snum) == -1)            return(TFSERR_MEMFAIL);    }    return(TFS_OKAY);}inttfsflasherase(int snum){    if (tfsTrace > 2)        printf("     tfsflasherase(%d)\n",snum);    tfsFmodCount++;    return(AppFlashErase(snum));}inttfsflashwrite(ulong *dest,ulong *src,long bytecnt){    if (tfsTrace > 2)        printf("     tfsflashwrite(0x%lx,0x%lx,%ld)\n",            (ulong)dest,(ulong)src,bytecnt);    if (bytecnt < 0)        return(-1);        tfsFmodCount++;    return(AppFlashWrite(dest,src,bytecnt));}/* tfserrmsg(): *  Return the error message string that corresponds to the incoming *  tfs error number. */char *tfserrmsg(int errno){    struct  tfserr  *tep;        tep = tfserrtbl;    while(tep->msg) {        if (errno == tep->err)            return(tep->msg);        tep++;    }    return("unknown tfs errno");}/* tfsmakeStale(): *  Modify the state of a file to be stale. *  Do this by clearing the TFS_NOTSTALE flag in the tfs header. *  This function is used by tfsadd() when in the process of *  updating a file that already exists in the flash. *  See comments above tfsadd() for more details on the TFS_NOTSTALE flag. */static inttfsmakeStale(TFILE *tfp){    ulong   flags;    flags = TFS_FLAGS(tfp) & ~TFS_NSTALE;    if (tfsflashwrite((ulong *)&tfp->flags,&flags,(long)sizeof(long)) < 0)        return(TFSERR_FLASHFAILURE);    return(TFS_OKAY);}/* tfsflagsbtoa(): *  Convert binary flags to ascii and return the string. */char *tfsflagsbtoa(long flags,char *fstr){    int i;    struct  tfsflg  *tfp;    if ((!flags) || (!fstr))        return((char *)0);    i = 0;    tfp = tfsflgtbl;    *fstr = 0;    while(tfp->sdesc) {        if ((flags & tfp->mask) == tfp->flag)            fstr[i++] = tfp->sdesc;        tfp++;    }    fstr[i] = 0;    return(fstr);}/* tfsflagsatob(): *  Convert ascii flags to binary and return the long. */static inttfsflagsatob(char *fstr, long *flag){    struct  tfsflg  *tfp;    *flag = 0;    if (!fstr)        return(TFSERR_BADFLAG);    while(*fstr) {        tfp = tfsflgtbl;        while(tfp->sdesc) {            if (*fstr == tfp->sdesc) {                *flag |= tfp->flag;                break;            }            tfp++;        }        if (!tfp->flag)            return(TFSERR_BADFLAG);        fstr++;    }    return(TFS_OKAY);}/* hdrcrc(): * The crc of the file header was originally calculated (in tfsadd()) * with the header crc and next pointer nulled out; so a copy must * be made and these two fields cleared.  Also, note that the * TFS_NSTALE and TFS_ACTIVE flags are forced to be set in the copy. * This is done because it is possible that either of these bits may * have been cleared due to other TFS interaction; hence, they need

⌨️ 快捷键说明

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