diff options
Diffstat (limited to 'main/common/tfs.c')
-rw-r--r-- | main/common/tfs.c | 5217 |
1 files changed, 2689 insertions, 2528 deletions
diff --git a/main/common/tfs.c b/main/common/tfs.c index 5223ba2..1e422d1 100644 --- a/main/common/tfs.c +++ b/main/common/tfs.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -20,109 +20,109 @@ * * 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). + * 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... * - * 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. * - * 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. + * 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. + * 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. + * 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. + * 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. + * 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. + * 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. + * * 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. + * * 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. + * * 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. * * Original author: Ed Sutter (ed.sutter@alcatel-lucent.com) * @@ -139,22 +139,22 @@ #if INCLUDE_TFS -int tfsrun_abortableautoboot(char **arglist,int verbose); -char *(*tfsGetAtime)(long,char *,int); -long (*tfsGetLtime)(void); -int (*tfsDocommand)(char *,int); -TDEV tfsDeviceTbl[TFSDEVTOT+1]; /* See notes above tfsramdevice() */ -TFILE **tfsAlist; -struct tfsdat tfsSlots[TFS_MAXOPEN]; -long tfsTrace; -int TfsCleanEnable; -long tfsFmodCount; -char tfsInitialized; +int tfsrun_abortableautoboot(char **arglist,int verbose); +char *(*tfsGetAtime)(long,char *,int); +long (*tfsGetLtime)(void); +int (*tfsDocommand)(char *,int); +TDEV tfsDeviceTbl[TFSDEVTOT+1]; /* See notes above tfsramdevice() */ +TFILE **tfsAlist; +struct tfsdat tfsSlots[TFS_MAXOPEN]; +long tfsTrace; +int TfsCleanEnable; +long tfsFmodCount; +char tfsInitialized; -static void pre_tfsautoboot_hook(void); +static void pre_tfsautoboot_hook(void); -static int tfsAlistSize, tfsOldDelFlagCheckActive; -static int tfsMonrcActive; +static int tfsAlistSize, tfsOldDelFlagCheckActive; +static int tfsMonrcActive; /* alt_tfsdevtbl[]: * This pre-initialized table of "flash-empty" tfsdev structures allows @@ -183,125 +183,130 @@ struct tfsdev *alt_tfsdevtbl = (struct tfsdev *)TFS_ALTDEVTBL_BASE; * online documentation under the topic "Designated Initializers". */ struct tfsdev alt_tfsdevtbl[TFSDEVTOT] = { - [0 ... (TFSDEVTOT-1)] = - { (char *)0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } + [0 ...(TFSDEVTOT-1)] = + { + (char *)0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff + } }; #endif -#define TFS_ALTDEVTBL_SIZE (TFSDEVTOT * sizeof(struct tfsdev)) +#define TFS_ALTDEVTBL_SIZE (TFSDEVTOT * sizeof(struct tfsdev)) /* 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. + * 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 }, - { 0, 0, 0, 0 } + { 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 }, + { 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_NOTAVAILABLE, "tfs facility not available" }, - { TFSERR_BADFLAG, "bad flag" }, - { TFSERR_CLEANOFF, "defragmentation is disabled" }, - { TFSERR_FLAKEYSOURCE, "dynamic source data" }, - { TFSERR_BADEXTENSION, "invalid file extension" }, - { TFSERR_LINKERROR, "file link error" }, - { TFSERR_BADPREFIX, "invalid device prefix" }, - { TFSERR_ALTINUSE, "alternate devcfg in use" }, - { TFSERR_NORUNMONRC, "can't run from monrc" }, - { TFSERR_DSIMAX, "out of DSI space" }, - { TFSERR_TOOSMALL, "partition size too small" }, - { 0,0 } + { 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_NOTAVAILABLE, "tfs facility not available" }, + { TFSERR_BADFLAG, "bad flag" }, + { TFSERR_CLEANOFF, "defragmentation is disabled" }, + { TFSERR_FLAKEYSOURCE, "dynamic source data" }, + { TFSERR_BADEXTENSION, "invalid file extension" }, + { TFSERR_LINKERROR, "file link error" }, + { TFSERR_BADPREFIX, "invalid device prefix" }, + { TFSERR_ALTINUSE, "alternate devcfg in use" }, + { TFSERR_NORUNMONRC, "can't run from monrc" }, + { TFSERR_DSIMAX, "out of DSI space" }, + { TFSERR_TOOSMALL, "partition size too small" }, + { 0,0 } }; /* dummyAtime() & dummyLtime(): - * These two functions are loaded into the function pointers as defaults - * for the time-retrieval stuff used in TFS. + * 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); + /* strcpy(buf,"Fri Sep 13 00:00:00 1986"); */ + *buf = 0; + return(buf); } static long dummyLtime(void) { - return(TIME_UNDEFINED); + 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. + * 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; + TDEV *tdp; - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if ((fp >= (TFILE *)tdp->start) && - (fp < (TFILE *)tdp->end)) - return(tdp); - } - return(0); + 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) +gettfsdev_fromprefix(char *prefix, int verbose) { - TDEV *tdp; + 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); + 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); } /* tfsspace(): @@ -311,23 +316,25 @@ gettfsdev_fromprefix(char * prefix, int verbose) int tfsspace(char *addr) { - TDEV *tdp; + TDEV *tdp; - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if ((addr >= (char *)tdp->start) && - (addr <= (char *)tdp->end)) - return(1); - if ((addr >= (char *)tdp->spare) && - (addr < (char *)(tdp->spare+tdp->sparesize))) - return(1); - } - return(0); + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + if((addr >= (char *)tdp->start) && + (addr <= (char *)tdp->end)) { + return(1); + } + if((addr >= (char *)tdp->spare) && + (addr < (char *)(tdp->spare+tdp->sparesize))) { + return(1); + } + } + return(0); } #ifndef TFS_NON_STANDARD_FLASH_INTERFACE /* tfsflasherase(), tfsflasheraseall() & tfsflashwrite(): - * Wrappers for corresponding flash operations. The wrappers are used - * to provide one place for the incrmentation of tfsFmodCount. + * Wrappers for corresponding flash operations. The wrappers are used + * to provide one place for the incrmentation of tfsFmodCount. * * In almost all cases, this code is included here; however, there * are some cases where the flash access functions that TFS uses must @@ -338,51 +345,57 @@ int tfsflasheraseall(TDEV *tdp) { #if INCLUDE_FLASH - 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((uchar *)tdp->start,&snum,0,0) < 0) - return(TFSERR_MEMFAIL); - last = snum + tdp->sectorcount; - - while(snum < last) { - if (AppFlashErase(snum++) <= 0) - 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((uchar *)tdp->spare,&snum,0,0) < 0) - return(TFSERR_MEMFAIL); - if (AppFlashErase(snum) <= 0) - return(TFSERR_MEMFAIL); - } + 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((uchar *)tdp->start,&snum,0,0) < 0) { + return(TFSERR_MEMFAIL); + } + last = snum + tdp->sectorcount; + + while(snum < last) { + if(AppFlashErase(snum++) <= 0) { + 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((uchar *)tdp->spare,&snum,0,0) < 0) { + return(TFSERR_MEMFAIL); + } + if(AppFlashErase(snum) <= 0) { + return(TFSERR_MEMFAIL); + } + } #else - memset((void *)tdp->start,(int)0xff,(int)(tdp->end-tdp->start)); + memset((void *)tdp->start,(int)0xff,(int)(tdp->end-tdp->start)); #endif - return(TFS_OKAY); + return(TFS_OKAY); } int tfsflasherase(int snum) { #if INCLUDE_FLASH - if (tfsTrace > 2) - printf(" tfsflasherase(%d)\n",snum); + if(tfsTrace > 2) { + printf(" tfsflasherase(%d)\n",snum); + } - tfsFmodCount++; - return(AppFlashErase(snum)); + tfsFmodCount++; + return(AppFlashErase(snum)); #else - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); #endif } @@ -390,112 +403,119 @@ int tfsflashwrite(uchar *dest,uchar *src,long bytecnt) { #if INCLUDE_FLASH - if (tfsTrace > 2) - printf(" tfsflashwrite(0x%lx,0x%lx,%ld)\n", - (ulong)dest,(ulong)src,bytecnt); - - if (bytecnt < 0) - return(TFSERR_BADARG); - - tfsFmodCount++; - - if (AppFlashWrite(dest,src,bytecnt) == 0) - return(TFS_OKAY); - else - return(TFSERR_FLASHFAILURE); + if(tfsTrace > 2) + printf(" tfsflashwrite(0x%lx,0x%lx,%ld)\n", + (ulong)dest,(ulong)src,bytecnt); + + if(bytecnt < 0) { + return(TFSERR_BADARG); + } + + tfsFmodCount++; + + if(AppFlashWrite(dest,src,bytecnt) == 0) { + return(TFS_OKAY); + } else { + return(TFSERR_FLASHFAILURE); + } #else - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); #endif } -#endif /* TFS_NON_STANDARD_FLASH_INTERFACE */ +#endif /* TFS_NON_STANDARD_FLASH_INTERFACE */ /* tfserrmsg(): - * Return the error message string that corresponds to the incoming - * tfs error number. + * 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"); + 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. + * 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 int tfsmakeStale(TFILE *tfp) { - ulong flags; + ulong flags; - flags = TFS_FLAGS(tfp) & ~TFS_NSTALE; - return(tfsflashwrite((uchar *)&tfp->flags,(uchar *)&flags, - (long)sizeof(long))); + flags = TFS_FLAGS(tfp) & ~TFS_NSTALE; + return(tfsflashwrite((uchar *)&tfp->flags,(uchar *)&flags, + (long)sizeof(long))); } /* tfsflagsbtoa(): - * Convert binary flags to ascii and return the string. + * Convert binary flags to ascii and return the string. */ char * tfsflagsbtoa(long flags,char *fstr) { - int i; - struct tfsflg *tfp; + int i; + struct tfsflg *tfp; - if ((!flags) || (!fstr)) - return((char *)0); + 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); + 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. + * Convert ascii flags to binary and return the long. */ int tfsflagsatob(char *fstr, long *flag) { - struct tfsflg *tfp; + struct tfsflg *tfp; - *flag = 0; + *flag = 0; - if (!fstr) - return(TFSERR_BADFLAG); + 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); + 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(): @@ -516,501 +536,525 @@ tfsflagsatob(char *fstr, long *flag) ulong tfshdrcrc(TFILE *hdr) { - TFILE hdrcpy; + TFILE hdrcpy; - memcpy((char *)&hdrcpy,(char *)hdr,sizeof(TFILE)); - hdrcpy.next = 0; - hdrcpy.hdrcrc = 0; - hdrcpy.flags |= (TFS_NSTALE | TFS_ACTIVE); - return(crc32((uchar *)&hdrcpy,TFSHDRSIZ)); + memcpy((char *)&hdrcpy,(char *)hdr,sizeof(TFILE)); + hdrcpy.next = 0; + hdrcpy.hdrcrc = 0; + hdrcpy.flags |= (TFS_NSTALE | TFS_ACTIVE); + return(crc32((uchar *)&hdrcpy,TFSHDRSIZ)); } /* validtfshdr(): - * Return 1 if the header pointed to by the incoming header pointer is valid. - * Else return 0. The header crc is calculated based on the hdrcrc - * and next members of the structure being zero. - * Note that if the file is deleted, then just ignore the crc and return 1. + * Return 1 if the header pointed to by the incoming header pointer is valid. + * Else return 0. The header crc is calculated based on the hdrcrc + * and next members of the structure being zero. + * Note that if the file is deleted, then just ignore the crc and return 1. */ int validtfshdr(TFILE *hdr) { - /* A few quick checks... */ - if (!hdr || hdr->hdrsize == ERASED16) - return(0); + /* A few quick checks... */ + if(!hdr || hdr->hdrsize == ERASED16) { + return(0); + } - if (tfshdrcrc(hdr) == hdr->hdrcrc) { - return(1); - } - else { - /* Support transition to new deletion flag method... - */ - if ((hdr->flags == 0) && tfsOldDelFlagCheckActive) - return(1); + if(tfshdrcrc(hdr) == hdr->hdrcrc) { + return(1); + } else { + /* Support transition to new deletion flag method... + */ + if((hdr->flags == 0) && tfsOldDelFlagCheckActive) { + return(1); + } - printf("Bad TFS hdr crc @ 0x%lx\n",(ulong)hdr); - return(0); - } + printf("Bad TFS hdr crc @ 0x%lx\n",(ulong)hdr); + return(0); + } } /* nextfp(): - * Used as a common means of retrieving the next file header pointer. It - * does some sanity checks based on the fact that all pointers must fall - * within the TFSSTART<->TFSEND memory range and since each file is placed - * just after the previous one in linear memory space, fp->next should - * always be greater than fp. + * Used as a common means of retrieving the next file header pointer. It + * does some sanity checks based on the fact that all pointers must fall + * within the TFSSTART<->TFSEND memory range and since each file is placed + * just after the previous one in linear memory space, fp->next should + * always be greater than fp. */ TFILE * nextfp(TFILE *fp, TDEV *tdp) { - if (!tdp) - tdp = gettfsdev(fp); + if(!tdp) { + tdp = gettfsdev(fp); + } - /* Make some basic in-range checks... - */ - if ((!tdp) || (fp < (TFILE *)tdp->start) || (fp > (TFILE *)tdp->end) || - (fp->next < (TFILE *)tdp->start) || (fp->next > (TFILE *)tdp->end) || - (fp->next <= fp)) { - printf("Bad TFS hdr ptr @ 0x%lx\n",(ulong)fp); - return(0); - } - return(fp->next); + /* Make some basic in-range checks... + */ + if((!tdp) || (fp < (TFILE *)tdp->start) || (fp > (TFILE *)tdp->end) || + (fp->next < (TFILE *)tdp->start) || (fp->next > (TFILE *)tdp->end) || + (fp->next <= fp)) { + printf("Bad TFS hdr ptr @ 0x%lx\n",(ulong)fp); + return(0); + } + return(fp->next); } /* tfsflasherased(): - * Jump to the point in flash after the last file in TFS, then verify - * that all remaining flash that is dedicated to TFS is erased (0xff). - * If erased, return 1; else return 0. + * Jump to the point in flash after the last file in TFS, then verify + * that all remaining flash that is dedicated to TFS is erased (0xff). + * If erased, return 1; else return 0. */ int tfsflasherased(TDEV *tdp, int verbose) { - ulong *lp; - TFILE *tfp; - - tfp = (TFILE *)tdp->start; - while(validtfshdr(tfp)) - tfp = nextfp(tfp,tdp); - - lp = (ulong *)tfp; - while (lp < (ulong *)tdp->end) { - if (*lp != ERASED32) { - if (verbose) - printf("End of TFS on %s not erased at 0x%lx\n", - tdp->prefix,(ulong)lp); - return(0); - } + ulong *lp; + TFILE *tfp; + + tfp = (TFILE *)tdp->start; + while(validtfshdr(tfp)) { + tfp = nextfp(tfp,tdp); + } + + lp = (ulong *)tfp; + while(lp < (ulong *)tdp->end) { + if(*lp != ERASED32) { + if(verbose) + printf("End of TFS on %s not erased at 0x%lx\n", + tdp->prefix,(ulong)lp); + return(0); + } #ifdef WATCHDOG_ENABLED - if (((ulong)lp & 0x3f) == 0) - WATCHDOG_MACRO; + if(((ulong)lp & 0x3f) == 0) { + WATCHDOG_MACRO; + } #endif - lp++; - } - return(1); + lp++; + } + return(1); } static int tfsftot(TDEV *tdpin) { - int ftot; - TFILE *tfp; - TDEV *tdp; - - ftot = 0; - for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if (!tdpin || (tdpin == tdp)) { - tfp = (TFILE *)tdp->start; - while(validtfshdr(tfp)) { - if (TFS_FILEEXISTS(tfp)) - ftot++; - tfp = nextfp(tfp,tdp); - } - } - } - return(ftot); + int ftot; + TFILE *tfp; + TDEV *tdp; + + ftot = 0; + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + if(!tdpin || (tdpin == tdp)) { + tfp = (TFILE *)tdp->start; + while(validtfshdr(tfp)) { + if(TFS_FILEEXISTS(tfp)) { + ftot++; + } + tfp = nextfp(tfp,tdp); + } + } + } + return(ftot); } /* tfsmemuse(): - * Step through one (or all) TFS devices and tally up various memory usage - * totals. See definition of tfsmem structure for more details. - * If incoming tdpin pointer is NULL, then tally up for all TFS devices; - * otherwise, tally up for only the one device pointed to by tdpin. + * Step through one (or all) TFS devices and tally up various memory usage + * totals. See definition of tfsmem structure for more details. + * If incoming tdpin pointer is NULL, then tally up for all TFS devices; + * otherwise, tally up for only the one device pointed to by tdpin. */ int tfsmemuse(TDEV *tdpin, TINFO *tinfo, int verbose) { - TFILE *tfp; - TDEV *tdp, *dsimax; - int devtot, devidx, ftot, fmax; - char *cfgerr, varname[TFSNAMESIZE+16]; - - /* Start by clearing incoming structure... - */ - tinfo->pso = 0; - tinfo->sos = 0; - tinfo->memtot = 0; - tinfo->liveftot = 0; - tinfo->deadftot = 0; - tinfo->livedata = 0; - tinfo->deaddata = 0; - tinfo->liveovrhd = 0; - tinfo->deadovrhd = 0; - tinfo->sectortot = 0; - - if (verbose) { - printf("TFS Memory Usage...\n "); - printf(" name start end spare spsize scnt type\n"); - } - - devtot = fmax = 0; - for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) - devtot++; - - devidx = 0; - dsimax = 0; - for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if (!tdpin || (tdpin == tdp)) { - tfp = (TFILE *)tdp->start; - - cfgerr = (char *)0; - - /* Do some sanity checks on the configuration... - */ - if ((tdp->spare >= tdp->start) && (tdp->spare <= tdp->end)) { - cfgerr = "spare within storage space"; - } - if (cfgerr) { - printf("Bad %s TFS config: %s.\n",tdp->prefix,cfgerr); - } - - /* Store TFS device info to shell variables. - */ - sprintf(varname,"TFS_PREFIX_%d", devidx); - shell_sprintf(varname,"%s",tdp->prefix); - - sprintf(varname,"TFS_START_%d", devidx); - shell_sprintf(varname,"0x%lx",tdp->start); - - sprintf(varname,"TFS_END_%d", devidx); - shell_sprintf(varname,"0x%lx",tdp->end); - - sprintf(varname,"TFS_SPARE_%d", devidx); - shell_sprintf(varname,"0x%lx",tdp->spare); - - sprintf(varname,"TFS_SPARESZ_%d", devidx); - shell_sprintf(varname,"0x%lx",tdp->sparesize); - - sprintf(varname,"TFS_SCNT_%d", devidx); - shell_sprintf(varname,"%d",tdp->sectorcount); - - sprintf(varname,"TFS_DEVINFO_%d", devidx); - shell_sprintf(varname,"0x%lx",tdp->devinfo); - - if (verbose) { - printf("%10s: 0x%08lx|0x%08lx|", - tdp->prefix,(ulong)(tdp->start),(ulong)(tdp->end)); - - if (TFS_DEVTYPE_ISRAM(tdp)) - printf(" - NA - | - NA - | NA "); - else - printf("0x%08lx|0x%06lx|%4ld",(ulong)(tdp->spare), - tdp->sparesize,tdp->sectorcount); - - printf("|0x%lx\n",(ulong)(tdp->devinfo)); - } - tinfo->memtot += ((tdp->end - tdp->start) + 1) + tdp->sparesize; - tinfo->pso += (tdp->sectorcount * 4) + 16; - tinfo->sos += tdp->sparesize; - tinfo->sectortot += tdp->sectorcount; - ftot = 0; - while(validtfshdr(tfp)) { - if (TFS_FILEEXISTS(tfp)) { - ftot++; - tinfo->liveftot++; - tinfo->livedata += TFS_SIZE(tfp); - tinfo->liveovrhd += (TFSHDRSIZ + DEFRAGHDRSIZ); - } - else { - tinfo->deadftot++; - tinfo->deaddata += TFS_SIZE(tfp); - tinfo->deadovrhd += TFSHDRSIZ; - } - tfp = nextfp(tfp,tdp); - } + TFILE *tfp; + TDEV *tdp, *dsimax; + int devtot, devidx, ftot, fmax; + char *cfgerr, varname[TFSNAMESIZE+16]; + + /* Start by clearing incoming structure... + */ + tinfo->pso = 0; + tinfo->sos = 0; + tinfo->memtot = 0; + tinfo->liveftot = 0; + tinfo->deadftot = 0; + tinfo->livedata = 0; + tinfo->deaddata = 0; + tinfo->liveovrhd = 0; + tinfo->deadovrhd = 0; + tinfo->sectortot = 0; + + if(verbose) { + printf("TFS Memory Usage...\n "); + printf(" name start end spare spsize scnt type\n"); + } + + devtot = fmax = 0; + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + devtot++; + } + + devidx = 0; + dsimax = 0; + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + if(!tdpin || (tdpin == tdp)) { + tfp = (TFILE *)tdp->start; + + cfgerr = (char *)0; + + /* Do some sanity checks on the configuration... + */ + if((tdp->spare >= tdp->start) && (tdp->spare <= tdp->end)) { + cfgerr = "spare within storage space"; + } + if(cfgerr) { + printf("Bad %s TFS config: %s.\n",tdp->prefix,cfgerr); + } + + /* Store TFS device info to shell variables. + */ + sprintf(varname,"TFS_PREFIX_%d", devidx); + shell_sprintf(varname,"%s",tdp->prefix); + + sprintf(varname,"TFS_START_%d", devidx); + shell_sprintf(varname,"0x%lx",tdp->start); + + sprintf(varname,"TFS_END_%d", devidx); + shell_sprintf(varname,"0x%lx",tdp->end); + + sprintf(varname,"TFS_SPARE_%d", devidx); + shell_sprintf(varname,"0x%lx",tdp->spare); + + sprintf(varname,"TFS_SPARESZ_%d", devidx); + shell_sprintf(varname,"0x%lx",tdp->sparesize); + + sprintf(varname,"TFS_SCNT_%d", devidx); + shell_sprintf(varname,"%d",tdp->sectorcount); + + sprintf(varname,"TFS_DEVINFO_%d", devidx); + shell_sprintf(varname,"0x%lx",tdp->devinfo); + + if(verbose) { + printf("%10s: 0x%08lx|0x%08lx|", + tdp->prefix,(ulong)(tdp->start),(ulong)(tdp->end)); + + if(TFS_DEVTYPE_ISRAM(tdp)) { + printf(" - NA - | - NA - | NA "); + } else + printf("0x%08lx|0x%06lx|%4ld",(ulong)(tdp->spare), + tdp->sparesize,tdp->sectorcount); + + printf("|0x%lx\n",(ulong)(tdp->devinfo)); + } + tinfo->memtot += ((tdp->end - tdp->start) + 1) + tdp->sparesize; + tinfo->pso += (tdp->sectorcount * 4) + 16; + tinfo->sos += tdp->sparesize; + tinfo->sectortot += tdp->sectorcount; + ftot = 0; + while(validtfshdr(tfp)) { + if(TFS_FILEEXISTS(tfp)) { + ftot++; + tinfo->liveftot++; + tinfo->livedata += TFS_SIZE(tfp); + tinfo->liveovrhd += (TFSHDRSIZ + DEFRAGHDRSIZ); + } else { + tinfo->deadftot++; + tinfo->deaddata += TFS_SIZE(tfp); + tinfo->deadovrhd += TFSHDRSIZ; + } + tfp = nextfp(tfp,tdp); + } #if INCLUDE_FLASH - /* Keep track of how many files are stored, relative to the - * size of the sector used to store DSI info at defrag time... - */ - if (!TFS_DEVTYPE_ISRAM(tdp)) { - int sector_ovrhd, ssize; - - if (addrtosector((uchar *)(tdp->end),0,&ssize,0) < 0) - return(TFSERR_MEMFAIL); - sector_ovrhd = tdp->sectorcount * sizeof(struct sectorcrc); - - if ((((ftot + 1) * DEFRAGHDRSIZ) + sector_ovrhd) > ssize) - dsimax = tdp; - - fmax += (ssize - sector_ovrhd)/DEFRAGHDRSIZ; - } + /* Keep track of how many files are stored, relative to the + * size of the sector used to store DSI info at defrag time... + */ + if(!TFS_DEVTYPE_ISRAM(tdp)) { + int sector_ovrhd, ssize; + + if(addrtosector((uchar *)(tdp->end),0,&ssize,0) < 0) { + return(TFSERR_MEMFAIL); + } + sector_ovrhd = tdp->sectorcount * sizeof(struct sectorcrc); + + if((((ftot + 1) * DEFRAGHDRSIZ) + sector_ovrhd) > ssize) { + dsimax = tdp; + } + + fmax += (ssize - sector_ovrhd)/DEFRAGHDRSIZ; + } #endif - } - devidx++; - } - shell_sprintf("TFS_DEVTOT","%d",devtot); - - tinfo->memused = tinfo->livedata + tinfo->liveovrhd + - tinfo->deaddata + tinfo->deadovrhd + tinfo->pso + tinfo->sos + - tinfo->sectortot * sizeof(struct sectorcrc); - tinfo->memfree = tinfo->memtot - tinfo->memused; - - /* Remaining space may not even be big enough to contain the - * file overhead, if this is the case, show a remaining space - * of zero rather than a negative number... - */ - tinfo->memfordata = - tinfo->memfree - (devtot * (TFSHDRSIZ + DEFRAGHDRSIZ)); - if (tinfo->memfordata < 0) - tinfo->memfordata = 0; - - - if (verbose) { - printf("\n Total memory: %d bytes (used=%d, avail=%d (%d for data)).\n", - tinfo->memtot,tinfo->memused,tinfo->memfree, tinfo->memfordata); - printf(" Per-device overhead: %d bytes ",tinfo->pso+tinfo->sos); - printf("(defrag-state=%d spare-sector=%d).\n",tinfo->pso,tinfo->sos); - printf(" File data space: %d bytes (live=%d, dead=%d).\n", - tinfo->livedata+tinfo->deaddata, - tinfo->livedata,tinfo->deaddata); - printf(" File overhead space: %d bytes (live=%d, dead=%d).\n", - tinfo->liveovrhd+tinfo->deadovrhd, - tinfo->liveovrhd,tinfo->deadovrhd); - printf(" Sector overhead space: %d bytes.\n", - tinfo->sectortot*sizeof(struct sectorcrc)); - printf(" File count: %d (live=%d, dead=%d).\n", - tinfo->liveftot+tinfo->deadftot,tinfo->liveftot,tinfo->deadftot); - printf(" Defrag will release %d bytes\n", - tinfo->deadovrhd+tinfo->deaddata); - printf(" Max # files storable in flash: %d\n",fmax); - if (dsimax) - printf(" Device '%s' has max Defrag-State-Info\n",dsimax->prefix); - printf("\n"); - } - return(tinfo->liveftot + tinfo->deadftot); + } + devidx++; + } + shell_sprintf("TFS_DEVTOT","%d",devtot); + + tinfo->memused = tinfo->livedata + tinfo->liveovrhd + + tinfo->deaddata + tinfo->deadovrhd + tinfo->pso + tinfo->sos + + tinfo->sectortot * sizeof(struct sectorcrc); + tinfo->memfree = tinfo->memtot - tinfo->memused; + + /* Remaining space may not even be big enough to contain the + * file overhead, if this is the case, show a remaining space + * of zero rather than a negative number... + */ + tinfo->memfordata = + tinfo->memfree - (devtot * (TFSHDRSIZ + DEFRAGHDRSIZ)); + if(tinfo->memfordata < 0) { + tinfo->memfordata = 0; + } + + + if(verbose) { + printf("\n Total memory: %d bytes (used=%d, avail=%d (%d for data)).\n", + tinfo->memtot,tinfo->memused,tinfo->memfree, tinfo->memfordata); + printf(" Per-device overhead: %d bytes ",tinfo->pso+tinfo->sos); + printf("(defrag-state=%d spare-sector=%d).\n",tinfo->pso,tinfo->sos); + printf(" File data space: %d bytes (live=%d, dead=%d).\n", + tinfo->livedata+tinfo->deaddata, + tinfo->livedata,tinfo->deaddata); + printf(" File overhead space: %d bytes (live=%d, dead=%d).\n", + tinfo->liveovrhd+tinfo->deadovrhd, + tinfo->liveovrhd,tinfo->deadovrhd); + printf(" Sector overhead space: %d bytes.\n", + tinfo->sectortot*sizeof(struct sectorcrc)); + printf(" File count: %d (live=%d, dead=%d).\n", + tinfo->liveftot+tinfo->deadftot,tinfo->liveftot,tinfo->deadftot); + printf(" Defrag will release %d bytes\n", + tinfo->deadovrhd+tinfo->deaddata); + printf(" Max # files storable in flash: %d\n",fmax); + if(dsimax) { + printf(" Device '%s' has max Defrag-State-Info\n",dsimax->prefix); + } + printf("\n"); + } + return(tinfo->liveftot + tinfo->deadftot); } /* tfscheck(): - * Step through each file in a particular device making a few checks... - * - First look at the header. If hdrsize is erased, it "should" indicate - * the end of the linear list of files. To be anal about it, verify that - * the entire header is erased. If it is, we truly are at the end of the - * list; otherwise, header error. - * - Second, do a crc32 on the header. - * - Third, if the file is not deleted, then do a crc32 on the data portion - * of the file (if the file is deleted, then it really doesn't matter if - * there is a crc32 error on that data). - * - Finally, if the header is not corrupted, index to the next pointer and - * continue. If the header is corrupt, see if enough information - * in the header is valid to allow us to step to the next file. Do this - * by calculating where the next pointer should be (using current pointer, - * file+header size and mod16 adjustment) and then see if that matches the - * value stored in the actual "next" pointer. If yes, go to next file; - * else break out of the loop. - * - * The purpose is to do more sophisticated file system checks than are - * done in normal TFS operations. + * Step through each file in a particular device making a few checks... + * - First look at the header. If hdrsize is erased, it "should" indicate + * the end of the linear list of files. To be anal about it, verify that + * the entire header is erased. If it is, we truly are at the end of the + * list; otherwise, header error. + * - Second, do a crc32 on the header. + * - Third, if the file is not deleted, then do a crc32 on the data portion + * of the file (if the file is deleted, then it really doesn't matter if + * there is a crc32 error on that data). + * - Finally, if the header is not corrupted, index to the next pointer and + * continue. If the header is corrupt, see if enough information + * in the header is valid to allow us to step to the next file. Do this + * by calculating where the next pointer should be (using current pointer, + * file+header size and mod16 adjustment) and then see if that matches the + * value stored in the actual "next" pointer. If yes, go to next file; + * else break out of the loop. + * + * The purpose is to do more sophisticated file system checks than are + * done in normal TFS operations. */ -#define TFS_CORRUPT 1 -#define HDR_CORRUPT 2 -#define DATA_CORRUPT 4 +#define TFS_CORRUPT 1 +#define HDR_CORRUPT 2 +#define DATA_CORRUPT 4 int tfscheck(TDEV *tdp, int verbose) { - TFILE *fp, *fp1; - int tfscorrupt, filtot, err; - - /* If the incoming device pointer is null, then loop through all - * devices in TFS, recursively calling tfscheck() with each pointer... - */ - if (!tdp) { - for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - err = tfscheck(tdp,verbose); - if (err != TFS_OKAY) - return(err); - } - return(TFS_OKAY); - } - - if (verbose) - printf("TFS device %s check:\n",tdp->prefix); - - filtot = tfscorrupt = 0; - - fp = (TFILE *)tdp->start; - while(1) { - tfscorrupt &= ~(HDR_CORRUPT | DATA_CORRUPT); - - /* If hdrsize is ERASED16, then verify that the whole header is - * also ERASED16, if yes, we're at the end of the linear list of - * files; otherwise, we have a corrupt header. - */ - if (fp->hdrsize == ERASED16) { - int i; - ushort *sp; - - /* If this is right at the edge of the end of the TFS device, - * then break with no further checks to this header. - */ - if ((fp+1) > (TFILE *)tdp->end) - break; - - /* Make sure the entire header is erased... - */ - sp = (ushort *)fp; - for(i=0;i<TFSHDRSIZ;i+=2,sp++) { - if (*sp != ERASED16) { - if (verbose) - printf(" Corrupt hdr @ 0x%lx",(ulong)fp); - tfscorrupt = HDR_CORRUPT | TFS_CORRUPT; - break; - } - } - if (!(tfscorrupt & HDR_CORRUPT)) - break; - else - goto nextfile; - } - - /* Run a crc check on the header even if file is deleted... - */ - if (tfshdrcrc(fp) != fp->hdrcrc) { - if (verbose) - printf(" CRC error in hdr @ 0x%lx\n",(ulong)fp); - tfscorrupt = HDR_CORRUPT | TFS_CORRUPT; - goto nextfile; - } - - /* If file exists, and it's not IPMOD, run a crc check on data... - */ - if (TFS_FILEEXISTS(fp) && !(fp->flags & TFS_IPMOD)) { - filtot++; - if (verbose) - printf(" %s...",fp->name); - - if ((!(fp->flags & TFS_IPMOD)) && - (crc32((uchar *)(TFS_BASE(fp)),fp->filsize) != fp->filcrc)) { - if (verbose) - printf(" CRC error in data"); - tfscorrupt = DATA_CORRUPT | TFS_CORRUPT; - } - else { - if (verbose) - printf(" ok"); - } - } - - /* Prior to incrementing to the next file pointer, if the header - * is corrupted, attempt to salvage the next pointer... - * If the value of the next pointer matches what is calculated - * from the file size and header size, then assume it is ok - * and allow the tfscheck() loop to continue; otherwise break. - */ + TFILE *fp, *fp1; + int tfscorrupt, filtot, err; + + /* If the incoming device pointer is null, then loop through all + * devices in TFS, recursively calling tfscheck() with each pointer... + */ + if(!tdp) { + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + err = tfscheck(tdp,verbose); + if(err != TFS_OKAY) { + return(err); + } + } + return(TFS_OKAY); + } + + if(verbose) { + printf("TFS device %s check:\n",tdp->prefix); + } + + filtot = tfscorrupt = 0; + + fp = (TFILE *)tdp->start; + while(1) { + tfscorrupt &= ~(HDR_CORRUPT | DATA_CORRUPT); + + /* If hdrsize is ERASED16, then verify that the whole header is + * also ERASED16, if yes, we're at the end of the linear list of + * files; otherwise, we have a corrupt header. + */ + if(fp->hdrsize == ERASED16) { + int i; + ushort *sp; + + /* If this is right at the edge of the end of the TFS device, + * then break with no further checks to this header. + */ + if((fp+1) > (TFILE *)tdp->end) { + break; + } + + /* Make sure the entire header is erased... + */ + sp = (ushort *)fp; + for(i=0; i<TFSHDRSIZ; i+=2,sp++) { + if(*sp != ERASED16) { + if(verbose) { + printf(" Corrupt hdr @ 0x%lx",(ulong)fp); + } + tfscorrupt = HDR_CORRUPT | TFS_CORRUPT; + break; + } + } + if(!(tfscorrupt & HDR_CORRUPT)) { + break; + } else { + goto nextfile; + } + } + + /* Run a crc check on the header even if file is deleted... + */ + if(tfshdrcrc(fp) != fp->hdrcrc) { + if(verbose) { + printf(" CRC error in hdr @ 0x%lx\n",(ulong)fp); + } + tfscorrupt = HDR_CORRUPT | TFS_CORRUPT; + goto nextfile; + } + + /* If file exists, and it's not IPMOD, run a crc check on data... + */ + if(TFS_FILEEXISTS(fp) && !(fp->flags & TFS_IPMOD)) { + filtot++; + if(verbose) { + printf(" %s...",fp->name); + } + + if((!(fp->flags & TFS_IPMOD)) && + (crc32((uchar *)(TFS_BASE(fp)),fp->filsize) != fp->filcrc)) { + if(verbose) { + printf(" CRC error in data"); + } + tfscorrupt = DATA_CORRUPT | TFS_CORRUPT; + } else { + if(verbose) { + printf(" ok"); + } + } + } + + /* Prior to incrementing to the next file pointer, if the header + * is corrupted, attempt to salvage the next pointer... + * If the value of the next pointer matches what is calculated + * from the file size and header size, then assume it is ok + * and allow the tfscheck() loop to continue; otherwise break. + */ nextfile: - if (tfscorrupt & HDR_CORRUPT) { - if (fp->next) { - ulong modnext; - - modnext = (ulong)((int)(fp+1) + fp->filsize); - if (modnext & 0xf) { - modnext += 16; - modnext &= ~0xf; - } - if (verbose) - printf(" (next ptr "); - if (fp->next != (TFILE *)modnext) { - if (verbose) - printf("damaged)\n"); - break; - } - else { - if (verbose) - printf("salvaged)"); - } - } - } - fp1 = nextfp(fp,tdp); - if (!fp1) { - tfscorrupt = HDR_CORRUPT | TFS_CORRUPT; - break; - } - if ((verbose) && (TFS_FILEEXISTS(fp) || tfscorrupt)) - putchar('\n'); - fp = fp1; - } - tfsflasherased(tdp,verbose); - if (tfscorrupt) - return(TFSERR_CORRUPT); - if (verbose) - printf(" PASSED\n"); - return (TFS_OKAY); + if(tfscorrupt & HDR_CORRUPT) { + if(fp->next) { + ulong modnext; + + modnext = (ulong)((int)(fp+1) + fp->filsize); + if(modnext & 0xf) { + modnext += 16; + modnext &= ~0xf; + } + if(verbose) { + printf(" (next ptr "); + } + if(fp->next != (TFILE *)modnext) { + if(verbose) { + printf("damaged)\n"); + } + break; + } else { + if(verbose) { + printf("salvaged)"); + } + } + } + } + fp1 = nextfp(fp,tdp); + if(!fp1) { + tfscorrupt = HDR_CORRUPT | TFS_CORRUPT; + break; + } + if((verbose) && (TFS_FILEEXISTS(fp) || tfscorrupt)) { + putchar('\n'); + } + fp = fp1; + } + tfsflasherased(tdp,verbose); + if(tfscorrupt) { + return(TFSERR_CORRUPT); + } + if(verbose) { + printf(" PASSED\n"); + } + return (TFS_OKAY); } void tfsclear(TDEV *tdp) { - int i; - - /* Clear the fileslot[] table indicating that no files are opened. - * Only clear the slots applicable to the incoming TDEV pointer. - */ - for (i = 0; i < TFS_MAXOPEN; i++) { - ulong offset; - - offset = tfsSlots[i].offset; - if (offset != (ulong)-1) { - if ((tdp == (TDEV *)0) || - ((offset >= tdp->start) && (offset <= tdp->end))) - tfsSlots[i].offset = -1; - } - } - - /* 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. - */ - tfsDocommand = docommand; - - /* Start off with a buffer for 16 files. This is probably more than - * will be used, so it avoids reallocations in tfsreorder(). - * - * Note that this function may be called as a result of the monitor - * doing an application exit. In that case, the heap is not - * re-initialized; hence, tfsAlist may already be allocated. - * If it is, then just leave it alone... - */ - if (tfsAlist == 0) { - tfsAlistSize = 16; - tfsAlist = (TFILE **)malloc((tfsAlistSize+1) * sizeof(TFILE **)); - if (!tfsAlist) { - printf("tfsclear(): tfsAlist allocation failed\n"); - tfsAlistSize = 0; - } - } + int i; + + /* Clear the fileslot[] table indicating that no files are opened. + * Only clear the slots applicable to the incoming TDEV pointer. + */ + for(i = 0; i < TFS_MAXOPEN; i++) { + ulong offset; + + offset = tfsSlots[i].offset; + if(offset != (ulong)-1) { + if((tdp == (TDEV *)0) || + ((offset >= tdp->start) && (offset <= tdp->end))) { + tfsSlots[i].offset = -1; + } + } + } + + /* 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. + */ + tfsDocommand = docommand; + + /* Start off with a buffer for 16 files. This is probably more than + * will be used, so it avoids reallocations in tfsreorder(). + * + * Note that this function may be called as a result of the monitor + * doing an application exit. In that case, the heap is not + * re-initialized; hence, tfsAlist may already be allocated. + * If it is, then just leave it alone... + */ + if(tfsAlist == 0) { + tfsAlistSize = 16; + tfsAlist = (TFILE **)malloc((tfsAlistSize+1) * sizeof(TFILE **)); + if(!tfsAlist) { + printf("tfsclear(): tfsAlist allocation failed\n"); + tfsAlistSize = 0; + } + } } /* tfsqstalecheck(): @@ -1030,203 +1074,207 @@ tfsclear(TDEV *tdp) static TFILE * tfsqstalecheck(void) { - TDEV *tdp; - TFILE *tfp, *tfpa; - - 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((TFILE *)0); - } - } - else if (TFS_STALE(tfp)) { - tfpa = tfp; - } - } - tfp = nextfp(tfp,tdp); - } - if (tfpa) - break; - } - return(tfpa); + TDEV *tdp; + TFILE *tfp, *tfpa; + + 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((TFILE *)0); + } + } else if(TFS_STALE(tfp)) { + tfpa = tfp; + } + } + tfp = nextfp(tfp,tdp); + } + if(tfpa) { + break; + } + } + return(tfpa); } /* 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. - */ + * 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 void tfsstalecheck(void) { - int err; - ulong flags; - TFILE *tfpa; - char buf[16]; - - tfpa = tfsqstalecheck(); - if (tfpa) { - char name[TFSNAMESIZE+1]; - - strcpy(name,TFS_NAME(tfpa)); - printf("TFS stale fixup (%s)...\n",name); - if (pollConsole("ok?")) { - printf("aborted\n"); - return; - } - 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)); - } - } + int err; + ulong flags; + TFILE *tfpa; + char buf[16]; + + tfpa = tfsqstalecheck(); + if(tfpa) { + char name[TFSNAMESIZE+1]; + + strcpy(name,TFS_NAME(tfpa)); + printf("TFS stale fixup (%s)...\n",name); + if(pollConsole("ok?")) { + printf("aborted\n"); + return; + } + 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. + * 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. + * 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. + * 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. + * NOTE: + * This dynamic configuration assumes that the end of the TFS space is + * just below the beginning of the spare space. * */ void tfsdevtblinit(void) { - int i; + int i; #if INCLUDE_FLASH - int startsector, endsector, bank; + int startsector, endsector, bank; #endif - TDEV *tDp, *tdp; - - for(i=0;i<TFSDEVTOT;i++) { - if ((alt_tfsdevtbl != (struct tfsdev *)0xffffffff) && - (alt_tfsdevtbl[i].prefix != (char *)0xffffffff)) { - tdp = &alt_tfsdevtbl[i]; - - /* do some sanity checking on the alternate table: - */ - if ((tdp->start >= tdp->end) || - (tdp->sparesize > (1024*1024)) || - (tdp->sectorcount > (1024*16))) { - printf("TFS altdevtbl[%d] appears corrupt\n",i); - tdp = &tfsdevtbl[i]; - } - } - else - tdp = &tfsdevtbl[i]; - - tDp = &tfsDeviceTbl[i]; - memcpy((char *)tDp,(char *)tdp,sizeof(struct tfsdev)); - if (i == TFSDEVTOT-1) - break; + TDEV *tDp, *tdp; + + for(i=0; i<TFSDEVTOT; i++) { + if((alt_tfsdevtbl != (struct tfsdev *)0xffffffff) && + (alt_tfsdevtbl[i].prefix != (char *)0xffffffff)) { + tdp = &alt_tfsdevtbl[i]; + + /* do some sanity checking on the alternate table: + */ + if((tdp->start >= tdp->end) || + (tdp->sparesize > (1024*1024)) || + (tdp->sectorcount > (1024*16))) { + printf("TFS altdevtbl[%d] appears corrupt\n",i); + tdp = &tfsdevtbl[i]; + } + } else { + tdp = &tfsdevtbl[i]; + } + + tDp = &tfsDeviceTbl[i]; + memcpy((char *)tDp,(char *)tdp,sizeof(struct tfsdev)); + if(i == TFSDEVTOT-1) { + break; + } #if INCLUDE_FLASH - 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, (uchar *)tDp->start, - tDp->sectorcount+1, &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; - - /* - printf( "tfsdevtblinit - dynamic TFS allocation\n" - " prefix........ %s\n" - " start......... 0x%08X\n" - " end........... 0x%08X\n" - " spare......... 0x%08X\n" - " sparesize..... 0x%08X\n" - " sectorcount... %d\n", - tDp->prefix, tDp->start, tDp->end, tDp->spare, - tDp->sparesize, tDp->sectorcount); - */ - } + 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, (uchar *)tDp->start, + tDp->sectorcount+1, &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; + + /* + printf( "tfsdevtblinit - dynamic TFS allocation\n" + " prefix........ %s\n" + " start......... 0x%08X\n" + " end........... 0x%08X\n" + " spare......... 0x%08X\n" + " sparesize..... 0x%08X\n" + " sectorcount... %d\n", + tDp->prefix, tDp->start, tDp->end, tDp->spare, + tDp->sparesize, tDp->sectorcount); + */ + } #endif - } + } } /* tfsstartup(): - * Called at system startup to get things properly initialized. + * Called at system startup to get things properly initialized. */ void tfsstartup() { - TDEV *tdp; + TDEV *tdp; - if (!tfsInitialized) - tfsdevtblinit(); + if(!tfsInitialized) { + tfsdevtblinit(); + } - tfsclear((TDEV *)0); + tfsclear((TDEV *)0); - /* No need to walk through the entire TFS init if it has already - * been done... - */ - if (tfsInitialized) - return; + /* No need to walk through the entire TFS init if it has already + * been done... + */ + if(tfsInitialized) { + return; + } - /* Step through the table looking for TFS devices that may need to - * be automatically initialized at startup. There are two cases: - * - if the devtype is TFS_DEVTYPE_RAM. - * - if the devtype is TFS_DEVTYPE_NVRAM with AUTOINIT set. - */ - for(tdp = tfsDeviceTbl;tdp->prefix != 0;tdp++) { - if (((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_RAM) || - (((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_NVRAM) && - (tdp->devinfo & TFS_DEVINFO_AUTOINIT))) { - _tfsinit(tdp); - } - } + /* Step through the table looking for TFS devices that may need to + * be automatically initialized at startup. There are two cases: + * - if the devtype is TFS_DEVTYPE_RAM. + * - if the devtype is TFS_DEVTYPE_NVRAM with AUTOINIT set. + */ + for(tdp = tfsDeviceTbl; tdp->prefix != 0; tdp++) { + if(((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_RAM) || + (((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_NVRAM) && + (tdp->devinfo & TFS_DEVINFO_AUTOINIT))) { + _tfsinit(tdp); + } + } - tfsfixup(3,0); - tfsstalecheck(); - tfsInitialized = 1; + tfsfixup(3,0); + tfsstalecheck(); + tfsInitialized = 1; } /* tfsexec: Treat the file as machine code that is COFF or ELF. */ @@ -1234,253 +1282,260 @@ tfsstartup() static int tfsexec(TFILE *fp,int verbose) { - int err, (*entry)(void); - long address; + int err, (*entry)(void); + long address; - err = tfsloadebin(fp,verbose,&address,0,0); - if (err != TFS_OKAY) - return(err); + err = tfsloadebin(fp,verbose,&address,0,0); + if(err != TFS_OKAY) { + return(err); + } - entry = (int(*)(void))address; - entry(); /* Call entrypoint (may not return). */ - return(TFS_OKAY); + entry = (int(*)(void))address; + entry(); /* Call entrypoint (may not return). */ + return(TFS_OKAY); } /* struct tfsran: - Used by tfsrunboot only. No need to put this in tfs.h. + Used by tfsrunboot only. No need to put this in tfs.h. */ struct tfsran { - char name[TFSNAMESIZE+1]; + 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. + * 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. */ int tfsrunboot(void) { - static struct tfsran *ranlist; - char *argv[2]; - int rancnt, aidx, ridx, err, fmodcnt; + static struct tfsran *ranlist; + char *argv[2]; + int rancnt, aidx, ridx, err, fmodcnt; #if TFS_RUN_DISABLE - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); #endif - if (!tfsInitialized) { - printf("TFS not initialized, tfsrunboot aborting.\n"); - return(0); - } - - /* 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; + if(!tfsInitialized) { + printf("TFS not initialized, tfsrunboot aborting.\n"); + return(0); + } + + /* 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)) { - alreadyran = 1; - break; - } - } - } - else - continue; /* No BRUN flag set. */ - - if (alreadyran) { /* BRUN flag set, but file has already */ - continue; /* been run. */ - } - - err = TFS_OKAY; - argv[0] = fname; - - /* At this point we know the file is a BRUN type, so just see if - * the query should precede the run... - */ - if (fp->flags & TFS_QRYBRUN) { - int pollval; - char query[TFSNAMESIZE+8]; - - sprintf(query,"%s?",fname); - pollval = pollConsole(query); + 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)) { + alreadyran = 1; + break; + } + } + } else { + continue; /* No BRUN flag set. */ + } + + if(alreadyran) { /* BRUN flag set, but file has already */ + continue; /* been run. */ + } + + err = TFS_OKAY; + argv[0] = fname; + + /* At this point we know the file is a BRUN type, so just see if + * the query should precede the run... + */ + if(fp->flags & TFS_QRYBRUN) { + int pollval; + char query[TFSNAMESIZE+8]; + + sprintf(query,"%s?",fname); + pollval = pollConsole(query); #ifdef TFS_AUTOBOOT_CANCEL_CHAR - if (pollval == (int)TFS_AUTOBOOT_CANCEL_CHAR) - continue; + if(pollval == (int)TFS_AUTOBOOT_CANCEL_CHAR) { + continue; + } #else - if (pollval) - continue; + if(pollval) { + continue; + } #endif - } - /* Increase the size of the ranlist[] table and add the file that - * is about to be run to that list... - */ - rancnt++; - rp = (struct tfsran*)realloc((char *)ranlist, - rancnt*sizeof(struct tfsran)); - - if (!rp) { - if (ranlist) - free((char *)ranlist); - printf("tfsrunboot() runlist realloc failure\n"); - return(-1); - } - - ranlist = rp; - strcpy(ranlist[rancnt-1].name,fname); - - /* Run the executable... - */ - if (fp->flags & TFS_BRUN) { - err = tfsrun_abortableautoboot(argv,0); - } - else { - pre_tfsautoboot_hook(); - err = tfsrun(argv,0); - } - - if (err != TFS_OKAY) - printf("%s: %s\n",fname,tfserrmsg(err)); - - /* If flash has been modified, then we must re-run tfsreorder() and - * start over... - */ - if (fmodcnt != tfsFmodCount) { - if ((err = tfsreorder()) < 0) { - printf("tfsrunboot() reorder2: %s\n",tfserrmsg(err)); - return(err); - } - fmodcnt = tfsFmodCount; - goto restartloop; - } - } - if (ranlist) - free((char *)ranlist); - return(rancnt); + } + /* Increase the size of the ranlist[] table and add the file that + * is about to be run to that list... + */ + rancnt++; + rp = (struct tfsran *)realloc((char *)ranlist, + rancnt*sizeof(struct tfsran)); + + if(!rp) { + if(ranlist) { + free((char *)ranlist); + } + printf("tfsrunboot() runlist realloc failure\n"); + return(-1); + } + + ranlist = rp; + strcpy(ranlist[rancnt-1].name,fname); + + /* Run the executable... + */ + if(fp->flags & TFS_BRUN) { + err = tfsrun_abortableautoboot(argv,0); + } else { + pre_tfsautoboot_hook(); + err = tfsrun(argv,0); + } + + if(err != TFS_OKAY) { + printf("%s: %s\n",fname,tfserrmsg(err)); + } + + /* If flash has been modified, then we must re-run tfsreorder() and + * start over... + */ + if(fmodcnt != tfsFmodCount) { + if((err = tfsreorder()) < 0) { + printf("tfsrunboot() reorder2: %s\n",tfserrmsg(err)); + return(err); + } + fmodcnt = tfsFmodCount; + goto restartloop; + } + } + if(ranlist) { + free((char *)ranlist); + } + return(rancnt); } /* tfsreorder(): - * Populate the tfsAlist[] array with the list of currently active file - * pointers, but put in alphabetical (lexicographical using strcmp()) order - * based on the filename. - * Note that after each file addition/deletion, this must be re-run. + * Populate the tfsAlist[] array with the list of currently active file + * pointers, but put in alphabetical (lexicographical using strcmp()) order + * based on the filename. + * Note that after each file addition/deletion, this must be re-run. */ int tfsreorder(void) { - TFILE *fp; - TDEV *tdp; - int i, j, tot; - - /* Determine how many valid files exist, and create tfsAlist array: - */ - tot = 0; - - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - fp = (TFILE *)tdp->start; - while(validtfshdr(fp)) { - if (TFS_FILEEXISTS(fp)) - tot++; - fp = nextfp(fp,tdp); - } - } - - /* If tfsAlist already exists, and is already big enough, then - * don't do any allocation; otherwise, create the array with one extra - * slot for a NULL pointer used elsewhere as an end-of-list indicator. - */ - if (tot > tfsAlistSize) { - tfsAlist = (TFILE **)realloc((char *)tfsAlist, - (tot+1) * sizeof(TFILE **)); - if (!tfsAlist) { - tfsAlistSize = 0; - return(TFSERR_MEMFAIL); - } - tfsAlistSize = tot; - } - - /* Clear the entire table (plus the extra one at the end): - */ - for(i=0;i<=tot;i++) - tfsAlist[i] = (TFILE *)0; - - /* Populate tfsAlist[] with a pointer to each active file - * in flash as they exist in memory... - */ - i = 0; - - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - fp = (TFILE *)tdp->start; - while(validtfshdr(fp)) { - if (TFS_FILEEXISTS(fp)) { - tfsAlist[i++] = fp; - } - fp = nextfp(fp,tdp); - } - } - - /* Now run a bubble sort on that list based on the lexicographical - * ordering returned by strcmp... - */ - for(i=1;i<tot;++i) { - for(j=tot-1;j>=i;--j) { - if (strcmp(TFS_NAME(tfsAlist[j-1]),TFS_NAME(tfsAlist[j])) > 0) { - fp = tfsAlist[j-1]; - tfsAlist[j-1] = tfsAlist[j]; - tfsAlist[j] = fp; - } - } - } - return(tot); + TFILE *fp; + TDEV *tdp; + int i, j, tot; + + /* Determine how many valid files exist, and create tfsAlist array: + */ + tot = 0; + + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + fp = (TFILE *)tdp->start; + while(validtfshdr(fp)) { + if(TFS_FILEEXISTS(fp)) { + tot++; + } + fp = nextfp(fp,tdp); + } + } + + /* If tfsAlist already exists, and is already big enough, then + * don't do any allocation; otherwise, create the array with one extra + * slot for a NULL pointer used elsewhere as an end-of-list indicator. + */ + if(tot > tfsAlistSize) { + tfsAlist = (TFILE **)realloc((char *)tfsAlist, + (tot+1) * sizeof(TFILE **)); + if(!tfsAlist) { + tfsAlistSize = 0; + return(TFSERR_MEMFAIL); + } + tfsAlistSize = tot; + } + + /* Clear the entire table (plus the extra one at the end): + */ + for(i=0; i<=tot; i++) { + tfsAlist[i] = (TFILE *)0; + } + + /* Populate tfsAlist[] with a pointer to each active file + * in flash as they exist in memory... + */ + i = 0; + + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + fp = (TFILE *)tdp->start; + while(validtfshdr(fp)) { + if(TFS_FILEEXISTS(fp)) { + tfsAlist[i++] = fp; + } + fp = nextfp(fp,tdp); + } + } + + /* Now run a bubble sort on that list based on the lexicographical + * ordering returned by strcmp... + */ + for(i=1; i<tot; ++i) { + for(j=tot-1; j>=i; --j) { + if(strcmp(TFS_NAME(tfsAlist[j-1]),TFS_NAME(tfsAlist[j])) > 0) { + fp = tfsAlist[j-1]; + tfsAlist[j-1] = tfsAlist[j]; + tfsAlist[j] = fp; + } + } + } + return(tot); } /* tfsheadroom(): @@ -1491,347 +1546,370 @@ tfsreorder(void) static long tfsheadroom(int fd) { - struct tfsdat *tdat; + struct tfsdat *tdat; - if ((fd < 0) || (fd >= TFS_MAXOPEN)) - return(TFSERR_BADARG); + if((fd < 0) || (fd >= TFS_MAXOPEN)) { + return(TFSERR_BADARG); + } - tdat = &tfsSlots[fd]; - if (tdat->flagmode & TFS_RDONLY) - return(tdat->hdr.filsize - tdat->offset); - else - return(tdat->hwp - tdat->offset); + tdat = &tfsSlots[fd]; + if(tdat->flagmode & TFS_RDONLY) { + return(tdat->hdr.filsize - tdat->offset); + } else { + return(tdat->hwp - tdat->offset); + } } /* tfstell(): - * Return the offset into the file that is specified by the incoming - * descriptor. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Return the offset into the file that is specified by the incoming + * descriptor. + * MONLIB NOTICE: this function is accessible through monlib.c. */ long tfstell(int fd) { - if ((fd < 0) || (fd >= TFS_MAXOPEN)) - return(TFSERR_BADARG); - return(tfsSlots[fd].offset); + if((fd < 0) || (fd >= TFS_MAXOPEN)) { + return(TFSERR_BADARG); + } + return(tfsSlots[fd].offset); } /* tfscompare(): - * Compare the content of the file specified by tfp with the content pointed - * to by the remaining arguments. If identical, return 0; else return -1. + * Compare the content of the file specified by tfp with the content pointed + * to by the remaining arguments. If identical, return 0; else return -1. */ static int tfscompare(TFILE *tfp,char *name, char *info, char *flags, uchar *src, int size) { - long bflags; - - /* Compare size, name, info field, flags and data: - */ - - /* Size... - */ - if (TFS_SIZE(tfp) != size) - return(-1); - - /* Name... - */ - if (strcmp(name,TFS_NAME(tfp))) - return(-1); - - /* Info field... - */ - if (info) { - if (strcmp(info,TFS_INFO(tfp))) - return(-1); - } - else { - if (TFS_INFO(tfp)[0] != 0) - return(-1); - } - - /* Flags... - */ - if (tfsflagsatob(flags, &bflags) == -1) - return(-1); - if (bflags != (TFS_FLAGS(tfp) & 0x7ff)) - return(-1); - - /* Data... - */ - if (memcmp(TFS_BASE(tfp),(char *)src,size)) - return(-1); - - return(0); + long bflags; + + /* Compare size, name, info field, flags and data: + */ + + /* Size... + */ + if(TFS_SIZE(tfp) != size) { + return(-1); + } + + /* Name... + */ + if(strcmp(name,TFS_NAME(tfp))) { + return(-1); + } + + /* Info field... + */ + if(info) { + if(strcmp(info,TFS_INFO(tfp))) { + return(-1); + } + } else { + if(TFS_INFO(tfp)[0] != 0) { + return(-1); + } + } + + /* Flags... + */ + if(tfsflagsatob(flags, &bflags) == -1) { + return(-1); + } + if(bflags != (TFS_FLAGS(tfp) & 0x7ff)) { + return(-1); + } + + /* Data... + */ + if(memcmp(TFS_BASE(tfp),(char *)src,size)) { + return(-1); + } + + return(0); } /* tfsinit(): - * Clear out all the flash that is dedicated to the file system. - * This removes all currently stored files and erases the flash. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Clear out all the flash that is dedicated to the file system. + * This removes all currently stored files and erases the flash. + * MONLIB NOTICE: this function is accessible through monlib.c. */ int _tfsinit(TDEV *tdpin) { - int ret; - TDEV *tdp; + int ret; + TDEV *tdp; - /* Step through the table of TFS devices and erase each sector... - */ - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if (!tdpin || (tdp == tdpin)) { - ret = tfsflasheraseall(tdp); - if (ret != TFS_OKAY) - return(ret); - } - } - return(TFS_OKAY); + /* Step through the table of TFS devices and erase each sector... + */ + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + if(!tdpin || (tdp == tdpin)) { + ret = tfsflasheraseall(tdp); + if(ret != TFS_OKAY) { + return(ret); + } + } + } + return(TFS_OKAY); } int tfsinit(void) { - if (tfsTrace > 0) - printf("tfsinit()\n"); - return(_tfsinit(0)); + if(tfsTrace > 0) { + printf("tfsinit()\n"); + } + return(_tfsinit(0)); } /* tfsFtot(): - * Return the number of files in a device, or all devices if tdpin is null. + * Return the number of files in a device, or all devices if tdpin is null. */ int tfsFtot(TDEV *tdpin) { - int ftot; - TFILE *fp; - TDEV *tdp; + int ftot; + TFILE *fp; + TDEV *tdp; - ftot = 0; - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if (!tdpin || (tdpin == tdp)) { - fp = (TFILE *)tdp->start; - while (fp->hdrsize != ERASED16) { - ftot++; - fp = nextfp(fp,tdp); - } - } - } - return(ftot); + ftot = 0; + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + if(!tdpin || (tdpin == tdp)) { + fp = (TFILE *)tdp->start; + while(fp->hdrsize != ERASED16) { + ftot++; + fp = nextfp(fp,tdp); + } + } + } + return(ftot); } /* tfsFileIsOpened(): - * Return 1 if file is currently opened; else 0. + * Return 1 if file is currently opened; else 0. */ int tfsFileIsOpened(char *name) { - int i; - struct tfsdat *slot; + int i; + struct tfsdat *slot; - slot = tfsSlots; - for (i=0;i<TFS_MAXOPEN;i++,slot++) { - if ((slot->offset >= 0) && !strcmp(slot->hdr.name,name)) - return(1); - } - return(0); + slot = tfsSlots; + for(i=0; i<TFS_MAXOPEN; i++,slot++) { + if((slot->offset >= 0) && !strcmp(slot->hdr.name,name)) { + return(1); + } + } + return(0); } /* tfsunopen(): - * If the incoming file descriptor is valid, mark that file as no-longer - * opened and return TFS_OKAY; else return TFSERR_BADARG. - * descriptor. + * If the incoming file descriptor is valid, mark that file as no-longer + * opened and return TFS_OKAY; else return TFSERR_BADARG. + * descriptor. */ static long tfsunopen(int fd) { - if ((fd < 0) || (fd >= TFS_MAXOPEN)) - return(TFSERR_BADARG); - if (tfsSlots[fd].offset == -1) - return(TFSERR_BADARG); - tfsSlots[fd].offset = -1; - return(TFS_OKAY); + if((fd < 0) || (fd >= TFS_MAXOPEN)) { + return(TFSERR_BADARG); + } + if(tfsSlots[fd].offset == -1) { + return(TFSERR_BADARG); + } + tfsSlots[fd].offset = -1; + return(TFS_OKAY); } /* tfsctrl(): - * Provides an ioctl-like interface to tfs. - * Requests supported: - * TFS_ERRMSG: Return error message (char *) corresponding to - * the incoming error number (arg1). - * TFS_MEMUSE: Return the total amount of memory currently in use by - * TFS. - * TFS_MEMAVAIL: Return the amount of memory currently avaialable for - * use in TFS. - * TFS_MEMDEAD: Return the amount of memory currently in use by - * dead files in TFS. - * TFS_DEFRAG: Mechanism for the application to issue - * a defragmentation request. - * Arg1: if 1, then reset after defrag is complete. - * Arg2: verbosity level. - * TFS_TELL: Return the offset into the file specified by the - * incoming file descriptor (arg1). - * TFS_FATOB: Return the binary equivalent of the TFS flags string - * pointed to by arg1. - * TFS_FBTOA: Return the string equivalent of the TFS flags (long) - * in arg1, destination buffer in arg2. - * TFS_UNOPEN: In TFS, a the data is not actually written to FLASH - * until the tfsclose() function is called. This argument - * to tfsctrl() allows a file to be opened and possibly - * written to, then unopened without actually modifying - * the FLASH. The value of arg1 file descriptor to - * apply the "unopen" to. - * TFS_TIMEFUNCS: This ctrl call is used to tell TFS what function - * to call for time information... - * Arg1 is a pointer to: - * (long)getLtime(void) - * - Get Long Time... - * Returns a long representation of time. - * Arg2 is a pointer to: - * (char *)getAtime(long tval,char *buf). - * - Get Ascii Time... - * If tval is zero, the buf is loaded with a string - * representing the current time; - * If tval is non-zero, then buf is loaded with a - * string conversion of the value of tval. - * Note that since it is up to these functions to - * make the conversion between binary version of time - * and ascii version, we don't define the exact meaning - * of the value returne by getBtime(). - * TFS_DOCOMMAND: Allows the application to redefine the function - * that is called to process each line of a script. - * This is useful if the application has its own - * command interpreter, but wants to use the scripting - * facilities of the monitor. - * Arg1 is a pointer to the docommand function to be - * used instead of the standard; - * Arg2 is a pointer to a location into which the current - * docommand function pointer can be stored. - * If arg1 is 0, load standard docommand; - * if arg2 is 0, don't load old value. - * TFS_INITDEV: Allows the application to initialize one of TFS's - * devices. Arg1 is a pointer to the device name prefix. - * TFS_DEFRAGDEV: Allows the application to defrag one of TFS's - * devices. Arg1 is a pointer to the device name prefix. - * TFS_CHECKDEV: Allows the application to check one of TFS's - * devices. Arg1 is a pointer to the device name prefix. - * TFS_RAMDEV: Allows the application to create (or remove) a - * special temporary TFS device in RAM. + * Provides an ioctl-like interface to tfs. + * Requests supported: + * TFS_ERRMSG: Return error message (char *) corresponding to + * the incoming error number (arg1). + * TFS_MEMUSE: Return the total amount of memory currently in use by + * TFS. + * TFS_MEMAVAIL: Return the amount of memory currently avaialable for + * use in TFS. + * TFS_MEMDEAD: Return the amount of memory currently in use by + * dead files in TFS. + * TFS_DEFRAG: Mechanism for the application to issue + * a defragmentation request. + * Arg1: if 1, then reset after defrag is complete. + * Arg2: verbosity level. + * TFS_TELL: Return the offset into the file specified by the + * incoming file descriptor (arg1). + * TFS_FATOB: Return the binary equivalent of the TFS flags string + * pointed to by arg1. + * TFS_FBTOA: Return the string equivalent of the TFS flags (long) + * in arg1, destination buffer in arg2. + * TFS_UNOPEN: In TFS, a the data is not actually written to FLASH + * until the tfsclose() function is called. This argument + * to tfsctrl() allows a file to be opened and possibly + * written to, then unopened without actually modifying + * the FLASH. The value of arg1 file descriptor to + * apply the "unopen" to. + * TFS_TIMEFUNCS: This ctrl call is used to tell TFS what function + * to call for time information... + * Arg1 is a pointer to: + * (long)getLtime(void) + * - Get Long Time... + * Returns a long representation of time. + * Arg2 is a pointer to: + * (char *)getAtime(long tval,char *buf). + * - Get Ascii Time... + * If tval is zero, the buf is loaded with a string + * representing the current time; + * If tval is non-zero, then buf is loaded with a + * string conversion of the value of tval. + * Note that since it is up to these functions to + * make the conversion between binary version of time + * and ascii version, we don't define the exact meaning + * of the value returne by getBtime(). + * TFS_DOCOMMAND: Allows the application to redefine the function + * that is called to process each line of a script. + * This is useful if the application has its own + * command interpreter, but wants to use the scripting + * facilities of the monitor. + * Arg1 is a pointer to the docommand function to be + * used instead of the standard; + * Arg2 is a pointer to a location into which the current + * docommand function pointer can be stored. + * If arg1 is 0, load standard docommand; + * if arg2 is 0, don't load old value. + * TFS_INITDEV: Allows the application to initialize one of TFS's + * devices. Arg1 is a pointer to the device name prefix. + * TFS_DEFRAGDEV: Allows the application to defrag one of TFS's + * devices. Arg1 is a pointer to the device name prefix. + * TFS_CHECKDEV: Allows the application to check one of TFS's + * devices. Arg1 is a pointer to the device name prefix. + * TFS_RAMDEV: Allows the application to create (or remove) a + * special temporary TFS device in RAM. * * - * MONLIB NOTICE: this function is accessible through monlib.c. + * MONLIB NOTICE: this function is accessible through monlib.c. */ long tfsctrl(int rqst,long arg1,long arg2) { - long retval, flag; - TDEV *tdp; - TINFO tinfo; - TRAMDEV *trdp; - - if (tfsTrace > 0) - printf("tfsctrl(%d,0x%lx,0x%lx)\n",rqst,arg1,arg2); - - switch(rqst) { - case TFS_ERRMSG: - retval = (long)tfserrmsg(arg1); - break; - case TFS_MEMUSE: - tfsmemuse(0,&tinfo,0); - retval = tinfo.memused; - break; - case TFS_MEMAVAIL: - tfsmemuse(0,&tinfo,0); - retval = tinfo.memfordata; - break; - case TFS_MEMDEAD: - tfsmemuse(0,&tinfo,0); - retval = tinfo.deadovrhd+tinfo.deaddata; - break; - case TFS_INITDEV: - tdp = gettfsdev_fromprefix((char *)arg1,0); - if (!tdp) - retval = TFSERR_BADARG; - else - retval = _tfsinit(tdp); - break; - case TFS_CHECKDEV: - tdp = 0; - if (arg1 != 0) - tdp = gettfsdev_fromprefix((char *)arg1,0); - retval = tfscheck(tdp,0); - break; - case TFS_DEFRAGDEV: - tdp = gettfsdev_fromprefix((char *)arg1,0); - if (!tdp) - retval = TFSERR_BADARG; - else - retval = tfsclean(tdp,0); - break; - case TFS_DEFRAG: - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) - tfsclean(tdp,(int)arg1); - retval = 0; - break; - case TFS_FCOUNT: - if (arg1) { - tdp = gettfsdev_fromprefix((char *)arg1,0); - if (!tdp) - retval = TFSERR_BADARG; - else - retval = tfsftot(tdp); - } - else { - retval = tfsftot(0); - } - break; - case TFS_DEFRAGON: - retval = tfsclean_on(); - break; - case TFS_DEFRAGOFF: - retval = tfsclean_off(); - break; - case TFS_UNOPEN: - retval = tfsunopen((int)arg1); - break; - case TFS_FATOB: - retval = tfsflagsatob((char *)arg1,&flag); - if (retval == TFS_OKAY) - retval = flag; - break; - case TFS_FBTOA: - retval = (long)tfsflagsbtoa(arg1,(char *)arg2); - if (retval == 0) - retval = TFSERR_BADARG; - break; - case TFS_HEADROOM: - retval = tfsheadroom(arg1); - break; - case TFS_RAMDEV: - trdp = (TRAMDEV *)arg1; - retval = tfsramdevice(trdp->name,trdp->base,trdp->size); - break; - case TFS_TELL: - retval = tfstell(arg1); - break; - case TFS_TIMEFUNCS: - tfsGetLtime = (long(*)(void))arg1; - tfsGetAtime = (char *(*)(long,char *,int))arg2; - retval = TFS_OKAY; - break; - case TFS_DOCOMMAND: - if (arg2) - *(long *)arg2 = (long)tfsDocommand; - if (arg1) - tfsDocommand = (int(*)(char *,int))arg1; - else - tfsDocommand = docommand; - retval = TFS_OKAY; - break; - default: - retval = TFSERR_BADARG; - break; - } - return(retval); + long retval, flag; + TDEV *tdp; + TINFO tinfo; + TRAMDEV *trdp; + + if(tfsTrace > 0) { + printf("tfsctrl(%d,0x%lx,0x%lx)\n",rqst,arg1,arg2); + } + + switch(rqst) { + case TFS_ERRMSG: + retval = (long)tfserrmsg(arg1); + break; + case TFS_MEMUSE: + tfsmemuse(0,&tinfo,0); + retval = tinfo.memused; + break; + case TFS_MEMAVAIL: + tfsmemuse(0,&tinfo,0); + retval = tinfo.memfordata; + break; + case TFS_MEMDEAD: + tfsmemuse(0,&tinfo,0); + retval = tinfo.deadovrhd+tinfo.deaddata; + break; + case TFS_INITDEV: + tdp = gettfsdev_fromprefix((char *)arg1,0); + if(!tdp) { + retval = TFSERR_BADARG; + } else { + retval = _tfsinit(tdp); + } + break; + case TFS_CHECKDEV: + tdp = 0; + if(arg1 != 0) { + tdp = gettfsdev_fromprefix((char *)arg1,0); + } + retval = tfscheck(tdp,0); + break; + case TFS_DEFRAGDEV: + tdp = gettfsdev_fromprefix((char *)arg1,0); + if(!tdp) { + retval = TFSERR_BADARG; + } else { + retval = tfsclean(tdp,0); + } + break; + case TFS_DEFRAG: + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + tfsclean(tdp,(int)arg1); + } + retval = 0; + break; + case TFS_FCOUNT: + if(arg1) { + tdp = gettfsdev_fromprefix((char *)arg1,0); + if(!tdp) { + retval = TFSERR_BADARG; + } else { + retval = tfsftot(tdp); + } + } else { + retval = tfsftot(0); + } + break; + case TFS_DEFRAGON: + retval = tfsclean_on(); + break; + case TFS_DEFRAGOFF: + retval = tfsclean_off(); + break; + case TFS_UNOPEN: + retval = tfsunopen((int)arg1); + break; + case TFS_FATOB: + retval = tfsflagsatob((char *)arg1,&flag); + if(retval == TFS_OKAY) { + retval = flag; + } + break; + case TFS_FBTOA: + retval = (long)tfsflagsbtoa(arg1,(char *)arg2); + if(retval == 0) { + retval = TFSERR_BADARG; + } + break; + case TFS_HEADROOM: + retval = tfsheadroom(arg1); + break; + case TFS_RAMDEV: + trdp = (TRAMDEV *)arg1; + retval = tfsramdevice(trdp->name,trdp->base,trdp->size); + break; + case TFS_TELL: + retval = tfstell(arg1); + break; + case TFS_TIMEFUNCS: + tfsGetLtime = (long(*)(void))arg1; + tfsGetAtime = (char *(*)(long,char *,int))arg2; + retval = TFS_OKAY; + break; + case TFS_DOCOMMAND: + if(arg2) { + *(long *)arg2 = (long)tfsDocommand; + } + if(arg1) { + tfsDocommand = (int(*)(char *,int))arg1; + } else { + tfsDocommand = docommand; + } + retval = TFS_OKAY; + break; + default: + retval = TFSERR_BADARG; + break; + } + return(retval); } /* tfsNameToDevice(): @@ -1844,16 +1922,18 @@ tfsctrl(int rqst,long arg1,long arg2) TDEV * tfsNameToDevice(char *name) { - TDEV *tdp; + TDEV *tdp; - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - if (!strncmp(name,tdp->prefix,strlen(tdp->prefix))) - break; - } - if (tdp->start == TFSEOT) - tdp = tfsDeviceTbl; + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + if(!strncmp(name,tdp->prefix,strlen(tdp->prefix))) { + break; + } + } + if(tdp->start == TFSEOT) { + tdp = tfsDeviceTbl; + } - return(tdp); + return(tdp); } /* tfsramdevice(): @@ -1867,510 +1947,547 @@ tfsNameToDevice(char *name) int tfsramdevice(char *name,long base,long size) { - TFILE *fp; - TDEV *tdp, *ramdev; - char tmpname[TFSNAMESIZE+1]; - static char devname[TFSNAMESIZE+1]; - - ramdev = (TDEV *)0; - snprintf(tmpname,TFSNAMESIZE,"//%s/",name); - - if (tfsTrace > 0) - printf("tfsramdevice(%s,0x%lx,%ld)\n",name,base,size); - - /* Scan through the current list of files and make sure that - * the name being requested is not the name of a file already - * in TFS... Note that the incoming name can't form even the - * same prefix as any file currently in TFS. - */ - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - fp = (TFILE *)tdp->start; - while(validtfshdr(fp)) { - if ((TFS_FILEEXISTS(fp)) && - (strncmp(tmpname,fp->name,strlen(tmpname)) == 0)) - return(TFSERR_FILEEXISTS); - fp = nextfp(fp,tdp); - } - } - - /* Scan through the device table to find the slot that can - * be used by the "ramdev" device... - */ - tdp = tfsDeviceTbl; - while(tdp->start != TFSEOT) { - if ((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_RAM) - ramdev = tdp; - if (strcmp(tdp->prefix,tmpname) == 0) { - if (size != 0) { - return(TFSERR_FILEEXISTS); - } - else { - if (ramdev != tdp) - return(TFSERR_FILEEXISTS); - } - } - tdp++; - } - - if (ramdev) { - if (size == 0) { - if (strcmp(tmpname,ramdev->prefix) != 0) - return(TFSERR_NOFILE); - - memset((char *)ramdev->start,0,ramdev->end - ramdev->start); - ramdev->prefix = 0; - ramdev->start = 0; - ramdev->devinfo = 0; - ramdev->end = 0; - ramdev->start = TFSEOT; - } - else - return(TFSERR_FILEEXISTS); - } - else { - /* If size is zero, just do nothing and return OK... - */ - if (size == 0) - return(TFS_OKAY); - - /* Minimum size of a TFS partition is 1024 bytes... - */ - if (size < 1024) - return(TFSERR_TOOSMALL); - - strcpy(devname,tmpname); - tdp->prefix = devname; - tdp->start = base; - tdp->sparesize = 0; - tdp->sectorcount = 0; - tdp->devinfo = TFS_DEVTYPE_RAM; - tdp->end = tdp->start + size - 1; - tdp->spare = 0; - memset((char *)tdp->start,0xff,size); - tdp++; - tdp->start = TFSEOT; - } - return(TFS_OKAY); + TFILE *fp; + TDEV *tdp, *ramdev; + char tmpname[TFSNAMESIZE+1]; + static char devname[TFSNAMESIZE+1]; + + ramdev = (TDEV *)0; + snprintf(tmpname,TFSNAMESIZE,"//%s/",name); + + if(tfsTrace > 0) { + printf("tfsramdevice(%s,0x%lx,%ld)\n",name,base,size); + } + + /* Scan through the current list of files and make sure that + * the name being requested is not the name of a file already + * in TFS... Note that the incoming name can't form even the + * same prefix as any file currently in TFS. + */ + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + fp = (TFILE *)tdp->start; + while(validtfshdr(fp)) { + if((TFS_FILEEXISTS(fp)) && + (strncmp(tmpname,fp->name,strlen(tmpname)) == 0)) { + return(TFSERR_FILEEXISTS); + } + fp = nextfp(fp,tdp); + } + } + + /* Scan through the device table to find the slot that can + * be used by the "ramdev" device... + */ + tdp = tfsDeviceTbl; + while(tdp->start != TFSEOT) { + if((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_RAM) { + ramdev = tdp; + } + if(strcmp(tdp->prefix,tmpname) == 0) { + if(size != 0) { + return(TFSERR_FILEEXISTS); + } else { + if(ramdev != tdp) { + return(TFSERR_FILEEXISTS); + } + } + } + tdp++; + } + + if(ramdev) { + if(size == 0) { + if(strcmp(tmpname,ramdev->prefix) != 0) { + return(TFSERR_NOFILE); + } + + memset((char *)ramdev->start,0,ramdev->end - ramdev->start); + ramdev->prefix = 0; + ramdev->start = 0; + ramdev->devinfo = 0; + ramdev->end = 0; + ramdev->start = TFSEOT; + } else { + return(TFSERR_FILEEXISTS); + } + } else { + /* If size is zero, just do nothing and return OK... + */ + if(size == 0) { + return(TFS_OKAY); + } + + /* Minimum size of a TFS partition is 1024 bytes... + */ + if(size < 1024) { + return(TFSERR_TOOSMALL); + } + + strcpy(devname,tmpname); + tdp->prefix = devname; + tdp->start = base; + tdp->sparesize = 0; + tdp->sectorcount = 0; + tdp->devinfo = TFS_DEVTYPE_RAM; + tdp->end = tdp->start + size - 1; + tdp->spare = 0; + memset((char *)tdp->start,0xff,size); + tdp++; + tdp->start = TFSEOT; + } + return(TFS_OKAY); } /* tfsadd(): - * Add a file to the current list. - * If the file already exists AND everything is identical between the - * old and the new (flags, info and data), then return and do nothing; - * else remove the old file prior to adding the new one. + * Add a file to the current list. + * If the file already exists AND everything is identical between the + * old and the new (flags, info and data), then return and do nothing; + * else remove the old file prior to adding the new one. * - * Note: - * At the point when tfsadd is called for a file that currently exists, - * the old file must be removed and a new one is put in its place. This - * opens up the possibility of losing the file if a power-hit or reset was - * to occur between the point at which the old file was removed and the new - * one was put in its place. To overcome this problem, TFS files have a - * flag called TFS_NSTALE. It is a bit that is normally 1, but cleared - * if it becomes stale (hence the name TFS_NSTALE). A file is - * in this mode only for a short time... the time it takes to write the - * new file that replaces the file that was made stale. - * Now, if a reset occurs after the file is stale, depending on - * whether or not the new file was written, it will either be removed or - * used to recreate the original file because the write of the new file - * was chopped off by the power hit. Refer to the function tfsstalecheck() - * for details on the recovery after a reset or powerhit. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Note: + * At the point when tfsadd is called for a file that currently exists, + * the old file must be removed and a new one is put in its place. This + * opens up the possibility of losing the file if a power-hit or reset was + * to occur between the point at which the old file was removed and the new + * one was put in its place. To overcome this problem, TFS files have a + * flag called TFS_NSTALE. It is a bit that is normally 1, but cleared + * if it becomes stale (hence the name TFS_NSTALE). A file is + * in this mode only for a short time... the time it takes to write the + * new file that replaces the file that was made stale. + * Now, if a reset occurs after the file is stale, depending on + * whether or not the new file was written, it will either be removed or + * used to recreate the original file because the write of the new file + * was chopped off by the power hit. Refer to the function tfsstalecheck() + * for details on the recovery after a reset or powerhit. + * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsadd(char *name, char *info, char *flags, uchar *src, int size) { - TDEV *tdp; - TFILE *fp, tf, *sfp; - long bflags; - ulong endoftfsflash, nextfileaddr, thisfileaddr; - ulong crc_pass1, crc_pass2; - int ftot, cleanupcount, err, stale, rc; - - if (!info) info = ""; - if (!flags) flags = ""; - - if (tfsTrace > 0) - printf("tfsadd(%s,%s,%s,0x%lx,%d)\n", name,info,flags,(ulong)src,size); - - /* Check for valid size and name: - */ - if ((size < 0) || (!name) || (*name == 0)) - return(TFSERR_BADARG); - - /* If name or info field length is too long, abort now... - */ - if ((strlen(name) > TFSNAMESIZE) || - ((info) && (strlen(info) > TFSINFOSIZE))) - return(TFSERR_NAMETOOBIG); - - /* The incoming filename cannot match any of the existing - * TFS device names... - */ - tdp = tfsDeviceTbl; - while(tdp->start != TFSEOT) { - if (strcmp(tdp->prefix,name) == 0) - return(TFSERR_FILEEXISTS); - tdp++; - } - - /* If the file is currently opened, then don't allow the add... - */ - if (tfsFileIsOpened(name)) - return(TFSERR_FILEINUSE); - - /* If incoming flags are illegal, abort now... - */ - if (*flags == 0) { - bflags = 0; - } - else { - err = tfsflagsatob(flags,&bflags); - if (err != TFS_OKAY) - return(err); - - /* If we're adding a link, then the size better be zero... - */ - if ((bflags & TFS_SYMLINK) && (size != 0)) - return(TFSERR_LINKERROR); - } - - /* Make sure that there isn't a stale file and a normal file - * of the same name already in TFS... - */ - tfsqstalecheck(); - - /* If size is zero, but the request is not a link, then - * error... - */ - if ((size == 0) && ((bflags & TFS_SYMLINK) != TFS_SYMLINK)) - return(TFSERR_BADARG); - - stale = 0; - cleanupcount = 0; - - /* Take snapshot of source crc. Note that we only run the CRC - * if the IPMOD flag is not set. If this flag is set, then the - * CRC is invalid... - */ - if (!(bflags & TFS_IPMOD)) - crc_pass1 = crc32(src, size); - else - crc_pass1 = 0; - - /* Establish the device that is to be used for the incoming file - * addition request... - */ - tdp = tfsNameToDevice(name); + TDEV *tdp; + TFILE *fp, tf, *sfp; + long bflags; + ulong endoftfsflash, nextfileaddr, thisfileaddr; + ulong crc_pass1, crc_pass2; + int ftot, cleanupcount, err, stale, rc; + + if(!info) { + info = ""; + } + if(!flags) { + flags = ""; + } + + if(tfsTrace > 0) { + printf("tfsadd(%s,%s,%s,0x%lx,%d)\n", name,info,flags,(ulong)src,size); + } + + /* Check for valid size and name: + */ + if((size < 0) || (!name) || (*name == 0)) { + return(TFSERR_BADARG); + } + + /* If name or info field length is too long, abort now... + */ + if((strlen(name) > TFSNAMESIZE) || + ((info) && (strlen(info) > TFSINFOSIZE))) { + return(TFSERR_NAMETOOBIG); + } + + /* The incoming filename cannot match any of the existing + * TFS device names... + */ + tdp = tfsDeviceTbl; + while(tdp->start != TFSEOT) { + if(strcmp(tdp->prefix,name) == 0) { + return(TFSERR_FILEEXISTS); + } + tdp++; + } + + /* If the file is currently opened, then don't allow the add... + */ + if(tfsFileIsOpened(name)) { + return(TFSERR_FILEINUSE); + } + + /* If incoming flags are illegal, abort now... + */ + if(*flags == 0) { + bflags = 0; + } else { + err = tfsflagsatob(flags,&bflags); + if(err != TFS_OKAY) { + return(err); + } + + /* If we're adding a link, then the size better be zero... + */ + if((bflags & TFS_SYMLINK) && (size != 0)) { + return(TFSERR_LINKERROR); + } + } + + /* Make sure that there isn't a stale file and a normal file + * of the same name already in TFS... + */ + tfsqstalecheck(); + + /* If size is zero, but the request is not a link, then + * error... + */ + if((size == 0) && ((bflags & TFS_SYMLINK) != TFS_SYMLINK)) { + return(TFSERR_BADARG); + } + + stale = 0; + cleanupcount = 0; + + /* Take snapshot of source crc. Note that we only run the CRC + * if the IPMOD flag is not set. If this flag is set, then the + * CRC is invalid... + */ + if(!(bflags & TFS_IPMOD)) { + crc_pass1 = crc32(src, size); + } else { + crc_pass1 = 0; + } + + /* Establish the device that is to be used for the incoming file + * addition request... + */ + tdp = tfsNameToDevice(name); #ifndef TFS_DISABLE_AUTODEFRAG tryagain: #endif - fp = (TFILE *)tdp->start; - - /* Find end of current storage: */ - ftot = 0; - while (fp) { - if (fp->hdrsize == ERASED16) - break; - if (TFS_FILEEXISTS(fp)) { - ftot++; - if (!strcmp(TFS_NAME(fp),name)) { - if (!(TFS_STALE(fp))) { - /* If destination file exists, but we do not meet the - * user level requirements, return error now. - */ - if (TFS_USRLVL(fp) > getUsrLvl()) - return(TFSERR_USERDENIED); - - /* If file of the same name exists AND it is identical to - * the new file to be added, then return TFS_OKAY and be - * done; otherwise, remove the old one and continue. - * Two exceptions to this: - * 1. If the current file is stale, then we are here - * because of a stale-file fixup at system startup. - * 2. If the src file is in-place-modify then source - * data is undefined. - */ - if (!(bflags & TFS_IPMOD) && - (!tfscompare(fp,name,info,flags,src,size))) { - return(TFS_OKAY); - } - + fp = (TFILE *)tdp->start; + + /* Find end of current storage: */ + ftot = 0; + while(fp) { + if(fp->hdrsize == ERASED16) { + break; + } + if(TFS_FILEEXISTS(fp)) { + ftot++; + if(!strcmp(TFS_NAME(fp),name)) { + if(!(TFS_STALE(fp))) { + /* If destination file exists, but we do not meet the + * user level requirements, return error now. + */ + if(TFS_USRLVL(fp) > getUsrLvl()) { + return(TFSERR_USERDENIED); + } + + /* If file of the same name exists AND it is identical to + * the new file to be added, then return TFS_OKAY and be + * done; otherwise, remove the old one and continue. + * Two exceptions to this: + * 1. If the current file is stale, then we are here + * because of a stale-file fixup at system startup. + * 2. If the src file is in-place-modify then source + * data is undefined. + */ + if(!(bflags & TFS_IPMOD) && + (!tfscompare(fp,name,info,flags,src,size))) { + return(TFS_OKAY); + } + #ifdef TFS_DISABLE_MAKE_BEFORE_BREAK - err = _tfsunlink(name); - if (err != TFS_OKAY) - printf("%s: %s\n",name,tfserrmsg(err)); + err = _tfsunlink(name); + if(err != TFS_OKAY) { + printf("%s: %s\n",name,tfserrmsg(err)); + } #else - /* If a file of the same name exists but is different - * than the new file, set a flag to indicate that the - * file should be marked stale just prior to - * adding the new file. - */ - stale = 1; + /* If a file of the same name exists but is different + * than the new file, set a flag to indicate that the + * file should be marked stale just prior to + * adding the new file. + */ + stale = 1; #endif - } - } - } - fp = nextfp(fp,tdp); - } - if (!fp) /* If fp is 0, then nextfp() (above) detected corruption. */ - return(TFSERR_CORRUPT); - - /* Calculate location of next file (on mod16 address). This will be - * initially used to see if we have enough space left in flash to store - * the current request; then, if yes, it will become part of the new - * file's header. - */ - thisfileaddr = (ulong)(fp+1); - nextfileaddr = thisfileaddr + size; - if (nextfileaddr & 0xf) - nextfileaddr = (nextfileaddr | 0xf) + 1; - - /* Make sure that the space is available for writing to flash... - * Remember that the end of useable flash space must take into - * account the fact that some space must be left over for the - * defragmentation state tables. Also, the total space needed for - * state tables cannot exceed the size of the sector that will contain - * those tables. - */ - if (TFS_DEVTYPE_ISRAM(tdp)) { - endoftfsflash = tdp->end; - } - else { + } + } + } + fp = nextfp(fp,tdp); + } + if(!fp) { /* If fp is 0, then nextfp() (above) detected corruption. */ + return(TFSERR_CORRUPT); + } + + /* Calculate location of next file (on mod16 address). This will be + * initially used to see if we have enough space left in flash to store + * the current request; then, if yes, it will become part of the new + * file's header. + */ + thisfileaddr = (ulong)(fp+1); + nextfileaddr = thisfileaddr + size; + if(nextfileaddr & 0xf) { + nextfileaddr = (nextfileaddr | 0xf) + 1; + } + + /* Make sure that the space is available for writing to flash... + * Remember that the end of useable flash space must take into + * account the fact that some space must be left over for the + * defragmentation state tables. Also, the total space needed for + * state tables cannot exceed the size of the sector that will contain + * those tables. + */ + if(TFS_DEVTYPE_ISRAM(tdp)) { + endoftfsflash = tdp->end; + } else { #if INCLUDE_FLASH - int ssize; - ulong state_table_overhead; + int ssize; + ulong state_table_overhead; - /* The state table overhead cannot exceed one additional - * sector's space, so we need to check for that... - */ - state_table_overhead = ((ftot+1) * DEFRAGHDRSIZ) + - (tdp->sectorcount * sizeof(struct sectorcrc)); + /* The state table overhead cannot exceed one additional + * sector's space, so we need to check for that... + */ + state_table_overhead = ((ftot+1) * DEFRAGHDRSIZ) + + (tdp->sectorcount * sizeof(struct sectorcrc)); - if (addrtosector((uchar *)(tdp->end),0,&ssize,0) < 0) - return(TFSERR_MEMFAIL); + if(addrtosector((uchar *)(tdp->end),0,&ssize,0) < 0) { + return(TFSERR_MEMFAIL); + } - if (state_table_overhead >= (ulong)ssize) - return(TFSERR_DSIMAX); + if(state_table_overhead >= (ulong)ssize) { + return(TFSERR_DSIMAX); + } - endoftfsflash = (tdp->end + 1) - state_table_overhead; + endoftfsflash = (tdp->end + 1) - state_table_overhead; #else - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); #endif - } + } - if ((nextfileaddr >= endoftfsflash) || - (nextfileaddr < thisfileaddr) || - (!flasherased((uchar *)fp,(uchar *)fp + (size+TFSHDRSIZ)))) { + if((nextfileaddr >= endoftfsflash) || + (nextfileaddr < thisfileaddr) || + (!flasherased((uchar *)fp,(uchar *)fp + (size+TFSHDRSIZ)))) { #ifndef TFS_DISABLE_AUTODEFRAG - if (!cleanupcount) { - err = tfsclean(tdp,0); - if (err != TFS_OKAY) { - printf("tfsadd autoclean failed: %s\n", - (char *)tfsctrl(TFS_ERRMSG,err,0)); - return(err); - } - cleanupcount++; - goto tryagain; - } - else + if(!cleanupcount) { + err = tfsclean(tdp,0); + if(err != TFS_OKAY) { + printf("tfsadd autoclean failed: %s\n", + (char *)tfsctrl(TFS_ERRMSG,err,0)); + return(err); + } + cleanupcount++; + goto tryagain; + } else #endif - return(TFSERR_FLASHFULL); - } - - memset((char *)&tf,0,TFSHDRSIZ); - - /* Do another crc on the source data. If crc_pass1 != crc_pass2 then - * somehow the source is changing. This is typically caused by the fact - * that the source address is within TFS space that was automatically - * defragmented above. There is no need to check source data if the - * source is in-place-modifiable. - */ - if (!(bflags & TFS_IPMOD)) { - crc_pass2 = crc32(src,size); - if (crc_pass1 != crc_pass2) - return(TFSERR_FLAKEYSOURCE); - } - else - crc_pass2 = ERASED32; - - /* Now that we have determined that we have enough space to do the - * copy, if the "stale" flag was set (indicating that there is already - * a file in TFS with the same name as the incoming file), we must now - * mark the file stale... - */ - if (stale) { - sfp = (TFILE *)tdp->start; - while (sfp) { - if (sfp->hdrsize == ERASED16) - break; - if (TFS_FILEEXISTS(sfp)) { - if (!strcmp(TFS_NAME(sfp),name)) { - if (TFS_DEVTYPE_ISRAM(tdp)) { - TFS_FLAGS(sfp) &= ~TFS_NSTALE; - } - else { - if ((err = tfsmakeStale(sfp)) != TFS_OKAY) - return(err); - } - break; - } - } - sfp = nextfp(sfp,tdp); - } - if (!sfp) - return(TFSERR_CORRUPT); - } - - /* Copy name and info data to header. - */ - strcpy(tf.name, name); - strcpy(tf.info, info); - tf.hdrsize = TFSHDRSIZ; - tf.hdrvrsn = TFSHDRVERSION; - tf.filsize = size; - tf.flags = bflags; - tf.flags |= (TFS_ACTIVE | TFS_NSTALE); - tf.filcrc = crc_pass2; - tf.modtime = tfsGetLtime(); + return(TFSERR_FLASHFULL); + } + + memset((char *)&tf,0,TFSHDRSIZ); + + /* Do another crc on the source data. If crc_pass1 != crc_pass2 then + * somehow the source is changing. This is typically caused by the fact + * that the source address is within TFS space that was automatically + * defragmented above. There is no need to check source data if the + * source is in-place-modifiable. + */ + if(!(bflags & TFS_IPMOD)) { + crc_pass2 = crc32(src,size); + if(crc_pass1 != crc_pass2) { + return(TFSERR_FLAKEYSOURCE); + } + } else { + crc_pass2 = ERASED32; + } + + /* Now that we have determined that we have enough space to do the + * copy, if the "stale" flag was set (indicating that there is already + * a file in TFS with the same name as the incoming file), we must now + * mark the file stale... + */ + if(stale) { + sfp = (TFILE *)tdp->start; + while(sfp) { + if(sfp->hdrsize == ERASED16) { + break; + } + if(TFS_FILEEXISTS(sfp)) { + if(!strcmp(TFS_NAME(sfp),name)) { + if(TFS_DEVTYPE_ISRAM(tdp)) { + TFS_FLAGS(sfp) &= ~TFS_NSTALE; + } else { + if((err = tfsmakeStale(sfp)) != TFS_OKAY) { + return(err); + } + } + break; + } + } + sfp = nextfp(sfp,tdp); + } + if(!sfp) { + return(TFSERR_CORRUPT); + } + } + + /* Copy name and info data to header. + */ + strcpy(tf.name, name); + strcpy(tf.info, info); + tf.hdrsize = TFSHDRSIZ; + tf.hdrvrsn = TFSHDRVERSION; + tf.filsize = size; + tf.flags = bflags; + tf.flags |= (TFS_ACTIVE | TFS_NSTALE); + tf.filcrc = crc_pass2; + tf.modtime = tfsGetLtime(); #if TFS_RESERVED - { - int rsvd; - for(rsvd=0;rsvd<TFS_RESERVED;rsvd++) - tf.rsvd[rsvd] = 0xffffffff; - } + { + int rsvd; + for(rsvd=0; rsvd<TFS_RESERVED; rsvd++) { + tf.rsvd[rsvd] = 0xffffffff; + } + } #endif - tf.next = 0; - tf.hdrcrc = 0; - tf.hdrcrc = crc32((uchar *)&tf,TFSHDRSIZ); - tf.next = (TFILE *)nextfileaddr; - - /* Now copy the file and header to flash. - * Note1: the header is copied AFTER the file has been - * successfully copied. If the header was written successfully, - * then the data write failed, the header would be incorrectly - * pointing to an invalid file. To avoid this, simply write the - * data first. - * Note2: if the file is in-place-modifiable, then there is no - * file data to be written to the flash. It will be left as all FFs - * so that the flash can be modified by tfsipmod() later. - */ - - /* Write the file to flash if not TFS_IPMOD: - */ - if (!(tf.flags & TFS_IPMOD)) { - if (TFS_DEVTYPE_ISRAM(tdp)) - memcpy((char *)(fp+1),(char *)src,size); - else { - rc = tfsflashwrite((uchar *)(fp+1),(uchar *)src,size); - if (rc != TFS_OKAY) - return(rc); - } - } - - /* Write the file header to flash: - */ - if (TFS_DEVTYPE_ISRAM(tdp)) - memcpy((char *)fp,(char *)&tf,TFSHDRSIZ); - else { - rc = tfsflashwrite((uchar *)fp,(uchar *)(&tf),TFSHDRSIZ); - if (rc != TFS_OKAY) - return(rc); - } - - /* Double check the CRC now that it is in flash. - */ - if (!(tf.flags & TFS_IPMOD)) { - if (crc32((uchar *)(fp+1), size) != tf.filcrc) - return(TFSERR_BADCRC); - } - - /* If the add was a file that previously existed, then the stale flag - * will be set and the old file needs to be deleted... - */ - if (stale) { - err = _tfsunlink(name); - if (err != TFS_OKAY) - printf("%s: %s\n",name,tfserrmsg(err)); - } - - tfslog(TFSLOG_ADD,name); - return(TFS_OKAY); + tf.next = 0; + tf.hdrcrc = 0; + tf.hdrcrc = crc32((uchar *)&tf,TFSHDRSIZ); + tf.next = (TFILE *)nextfileaddr; + + /* Now copy the file and header to flash. + * Note1: the header is copied AFTER the file has been + * successfully copied. If the header was written successfully, + * then the data write failed, the header would be incorrectly + * pointing to an invalid file. To avoid this, simply write the + * data first. + * Note2: if the file is in-place-modifiable, then there is no + * file data to be written to the flash. It will be left as all FFs + * so that the flash can be modified by tfsipmod() later. + */ + + /* Write the file to flash if not TFS_IPMOD: + */ + if(!(tf.flags & TFS_IPMOD)) { + if(TFS_DEVTYPE_ISRAM(tdp)) { + memcpy((char *)(fp+1),(char *)src,size); + } else { + rc = tfsflashwrite((uchar *)(fp+1),(uchar *)src,size); + if(rc != TFS_OKAY) { + return(rc); + } + } + } + + /* Write the file header to flash: + */ + if(TFS_DEVTYPE_ISRAM(tdp)) { + memcpy((char *)fp,(char *)&tf,TFSHDRSIZ); + } else { + rc = tfsflashwrite((uchar *)fp,(uchar *)(&tf),TFSHDRSIZ); + if(rc != TFS_OKAY) { + return(rc); + } + } + + /* Double check the CRC now that it is in flash. + */ + if(!(tf.flags & TFS_IPMOD)) { + if(crc32((uchar *)(fp+1), size) != tf.filcrc) { + return(TFSERR_BADCRC); + } + } + + /* If the add was a file that previously existed, then the stale flag + * will be set and the old file needs to be deleted... + */ + if(stale) { + err = _tfsunlink(name); + if(err != TFS_OKAY) { + printf("%s: %s\n",name,tfserrmsg(err)); + } + } + + tfslog(TFSLOG_ADD,name); + return(TFS_OKAY); } /* tfsunlink(): - * Delete a file from the current list of files. Note that there - * is no attempt to de-fragment the flash; it simply nulls out the flags - * field of the file. If successful return 0; else return error number. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Delete a file from the current list of files. Note that there + * is no attempt to de-fragment the flash; it simply nulls out the flags + * field of the file. If successful return 0; else return error number. + * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsunlink(char *name) { - if (tfsTrace > 0) - printf("tfsunlink(%s)\n",name); + if(tfsTrace > 0) { + printf("tfsunlink(%s)\n",name); + } - /* If the file is currently opened, then don't allow the deletion... - */ - if (tfsFileIsOpened(name)) - return(TFSERR_FILEINUSE); + /* If the file is currently opened, then don't allow the deletion... + */ + if(tfsFileIsOpened(name)) { + return(TFSERR_FILEINUSE); + } - return(_tfsunlink(name)); + return(_tfsunlink(name)); } int _tfsunlink(char *name) { - int rc; - TFILE *fp; - TDEV *tdp; - ulong flags_marked_deleted; + int rc; + TFILE *fp; + TDEV *tdp; + ulong flags_marked_deleted; - if (tfsTrace > 0) - printf("_tfsunlink(%s)\n",name); + if(tfsTrace > 0) { + printf("_tfsunlink(%s)\n",name); + } - fp = _tfsstat(name,0); - if (!fp) - return(TFSERR_NOFILE); + fp = _tfsstat(name,0); + if(!fp) { + return(TFSERR_NOFILE); + } - if (TFS_USRLVL(fp) > getUsrLvl()) - return(TFSERR_USERDENIED); + if(TFS_USRLVL(fp) > getUsrLvl()) { + return(TFSERR_USERDENIED); + } - flags_marked_deleted = fp->flags & ~TFS_ACTIVE; + flags_marked_deleted = fp->flags & ~TFS_ACTIVE; - tdp = tfsNameToDevice(name); - if (TFS_DEVTYPE_ISRAM(tdp)) - memcpy((char *)&fp->flags,(char *)&flags_marked_deleted,sizeof(long)); - else { - rc = tfsflashwrite((uchar *)&fp->flags, - (uchar *)&flags_marked_deleted, sizeof(long)); - if (rc != TFS_OKAY) - return(rc); - } + tdp = tfsNameToDevice(name); + if(TFS_DEVTYPE_ISRAM(tdp)) { + memcpy((char *)&fp->flags,(char *)&flags_marked_deleted,sizeof(long)); + } else { + rc = tfsflashwrite((uchar *)&fp->flags, + (uchar *)&flags_marked_deleted, sizeof(long)); + if(rc != TFS_OKAY) { + return(rc); + } + } - tfslog(TFSLOG_DEL,name); - return (TFS_OKAY); + tfslog(TFSLOG_DEL,name); + return (TFS_OKAY); } - + int tfslink(char *src, char *target) { - TFILE *tfp; - char linfo[TFSINFOSIZE+1]; - char flags[16]; + TFILE *tfp; + char linfo[TFSINFOSIZE+1]; + char flags[16]; - tfp = tfsstat(src); - if (tfp) { - if (TFS_ISLINK(tfp)) - return(TFSERR_LINKERROR); + tfp = tfsstat(src); + if(tfp) { + if(TFS_ISLINK(tfp)) { + return(TFSERR_LINKERROR); + } - strncpy(linfo,src,TFSINFOSIZE-1); - linfo[TFSINFOSIZE] = 0; - flags[0] = 'l'; - tfsflagsbtoa(tfp->flags,flags+1); - return(tfsadd(target,linfo,flags,0,0)); - } - return(TFSERR_NOFILE); + strncpy(linfo,src,TFSINFOSIZE-1); + linfo[TFSINFOSIZE] = 0; + flags[0] = 'l'; + tfsflagsbtoa(tfp->flags,flags+1); + return(tfsadd(target,linfo,flags,0,0)); + } + return(TFSERR_NOFILE); } @@ -2378,12 +2495,11 @@ static void pre_tfsautoboot_hook(void) { #ifdef PRE_TFSAUTOBOOT_HOOK - extern void PRE_TFSAUTOBOOT_HOOK(); + extern void PRE_TFSAUTOBOOT_HOOK(); - if (tfsMonrcActive == 0) - { - PRE_TFSAUTOBOOT_HOOK(); - } + if(tfsMonrcActive == 0) { + PRE_TFSAUTOBOOT_HOOK(); + } #endif } @@ -2396,9 +2512,9 @@ pre_tfsautoboot_hook(void) * These files can be aborted by an escape character under two * circumstances: * - * 1. There is no password file installed - * 2. The user correctly enters the level-three password when - * prompted by the abort interaction below. + * 1. There is no password file installed + * 2. The user correctly enters the level-three password when + * prompted by the abort interaction below. * * This mechanism maintains security, but only when security is desired. * A system that needs security will have a password file installed; @@ -2415,16 +2531,16 @@ pre_tfsautoboot_hook(void) */ -#define AUTOBOOT_ABORT_NULL 0 -#define AUTOBOOT_ABORT_NO 1 -#define AUTOBOOT_ABORT_YES 2 -#define AUTOBOOT_ABORT_FAILED 3 +#define AUTOBOOT_ABORT_NULL 0 +#define AUTOBOOT_ABORT_NO 1 +#define AUTOBOOT_ABORT_YES 2 +#define AUTOBOOT_ABORT_FAILED 3 #ifndef AUTOBOOT_ABORT_CHAR #ifdef TFS_AUTOBOOT_CANCEL_CHAR -#define AUTOBOOT_ABORT_CHAR TFS_AUTOBOOT_CANCEL_CHAR +#define AUTOBOOT_ABORT_CHAR TFS_AUTOBOOT_CANCEL_CHAR #else -#define AUTOBOOT_ABORT_CHAR 0x03 /* CTRL-C */ +#define AUTOBOOT_ABORT_CHAR 0x03 /* CTRL-C */ #endif #endif @@ -2432,130 +2548,135 @@ int tfsrun_abortableautoboot(char **arglist,int verbose) { #ifdef TFS_AUTOBOOT_ABORTABLE - int err; - static int autoboot_abort; - - /* If a character has been detected at the console, and the - * character is AUTOBOOT_ABORT_CHAR, then, if a password file - * exists, require that the user enter the level-3 password - * to abort the autoboot file... - * Note that this is only done on the first pass through this - * function. All subsequent passes use the result of the initial - * pass. - */ - if (autoboot_abort == AUTOBOOT_ABORT_NULL) { - autoboot_abort = AUTOBOOT_ABORT_NO; - - if (gotachar() && (getchar() == AUTOBOOT_ABORT_CHAR)) { + int err; + static int autoboot_abort; + + /* If a character has been detected at the console, and the + * character is AUTOBOOT_ABORT_CHAR, then, if a password file + * exists, require that the user enter the level-3 password + * to abort the autoboot file... + * Note that this is only done on the first pass through this + * function. All subsequent passes use the result of the initial + * pass. + */ + if(autoboot_abort == AUTOBOOT_ABORT_NULL) { + autoboot_abort = AUTOBOOT_ABORT_NO; + + if(gotachar() && (getchar() == AUTOBOOT_ABORT_CHAR)) { #if INCLUDE_USRLVL - if (passwordFileExists()) { - char passwd[16]; - - /* To allow the user to simply hold down on the abort - * character during a target, reset, this loop will - * absorb a burst of incoming characters. Then, when - * the burst halts, the user will be queried for the - * password. - */ - monDelay(500); - while(gotachar()) { - getchar(); - monDelay(500); - } - - getpass("autoboot-abort password: ",passwd,sizeof(passwd)-1,50); - if (validPassword(passwd,3)) - autoboot_abort = AUTOBOOT_ABORT_YES; - else - autoboot_abort = AUTOBOOT_ABORT_FAILED; - } - else + if(passwordFileExists()) { + char passwd[16]; + + /* To allow the user to simply hold down on the abort + * character during a target, reset, this loop will + * absorb a burst of incoming characters. Then, when + * the burst halts, the user will be queried for the + * password. + */ + monDelay(500); + while(gotachar()) { + getchar(); + monDelay(500); + } + + getpass("autoboot-abort password: ",passwd,sizeof(passwd)-1,50); + if(validPassword(passwd,3)) { + autoboot_abort = AUTOBOOT_ABORT_YES; + } else { + autoboot_abort = AUTOBOOT_ABORT_FAILED; + } + } else #endif - autoboot_abort = AUTOBOOT_ABORT_YES; - } - } - - err = TFS_OKAY; - - switch(autoboot_abort) { - case AUTOBOOT_ABORT_NO: - pre_tfsautoboot_hook(); - err = tfsrun(arglist,verbose); - break; - case AUTOBOOT_ABORT_YES: - printf("%s aborted\n",arglist[0]); - break; - case AUTOBOOT_ABORT_FAILED: - printf("%s abort attempt failed\n",arglist[0]); - pre_tfsautoboot_hook(); - err = tfsrun(arglist,verbose); - break; - } - return(err); + autoboot_abort = AUTOBOOT_ABORT_YES; + } + } + + err = TFS_OKAY; + + switch(autoboot_abort) { + case AUTOBOOT_ABORT_NO: + pre_tfsautoboot_hook(); + err = tfsrun(arglist,verbose); + break; + case AUTOBOOT_ABORT_YES: + printf("%s aborted\n",arglist[0]); + break; + case AUTOBOOT_ABORT_FAILED: + printf("%s abort attempt failed\n",arglist[0]); + pre_tfsautoboot_hook(); + err = tfsrun(arglist,verbose); + break; + } + return(err); #else - pre_tfsautoboot_hook(); - return(tfsrun(arglist,verbose)); -#endif /* TFS_AUTOBOOT_ABORTABLE */ + pre_tfsautoboot_hook(); + return(tfsrun(arglist,verbose)); +#endif /* TFS_AUTOBOOT_ABORTABLE */ } /* tfsrun(): - * Run the named file. Based on the file flags, the file is either - * executed as a COFF/ELF file with all relocation data in the file - * or run as a simple script of monitor commands. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Run the named file. Based on the file flags, the file is either + * executed as a COFF/ELF file with all relocation data in the file + * or run as a simple script of monitor commands. + * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsrun(char **arglist,int verbose) { - int i, err; - TFILE fstat, *fp; - char *name; + int i, err; + TFILE fstat, *fp; + char *name; + + name = arglist[0]; + fp = tfsstat(name); - name = arglist[0]; - fp = tfsstat(name); - - if (!fp) - return (TFSERR_NOFILE); + if(!fp) { + return (TFSERR_NOFILE); + } - tfsfstat(name,&fstat); + tfsfstat(name,&fstat); - if (TFS_USRLVL(fp) > getUsrLvl()) - return(TFSERR_USERDENIED); + if(TFS_USRLVL(fp) > getUsrLvl()) { + return(TFSERR_USERDENIED); + } #if INCLUDE_TFSSCRIPT - /* Store away the argument list so that it is accessible by the script - * or executable application about to be run: - */ - for(i=0;arglist[i];i++) - putargv(i,arglist[i]); - putargv(i,(char *)0); + /* Store away the argument list so that it is accessible by the script + * or executable application about to be run: + */ + for(i=0; arglist[i]; i++) { + putargv(i,arglist[i]); + } + putargv(i,(char *)0); #endif - /* Executable file can be script or binary... - */ - if (!(fp->flags & (TFS_EXEC|TFS_EBIN))) - return(TFSERR_NOTEXEC); - - if (!(fp->flags & TFS_IPMOD)) { - if (crc32((uchar *)(TFS_BASE(fp)), fp->filsize) != fp->filcrc) - return(TFSERR_BADCRC); - } - /* Machine code or script... - * If machine code, then block it if monrc is active. - */ - if (fp->flags & TFS_EBIN) { - if (tfsRunningMonrc()) - err = TFSERR_NORUNMONRC; - else - err = tfsexec(fp,verbose); - } - else { - err = tfsscript(&fstat,verbose); - } - - return(err); + /* Executable file can be script or binary... + */ + if(!(fp->flags & (TFS_EXEC|TFS_EBIN))) { + return(TFSERR_NOTEXEC); + } + + if(!(fp->flags & TFS_IPMOD)) { + if(crc32((uchar *)(TFS_BASE(fp)), fp->filsize) != fp->filcrc) { + return(TFSERR_BADCRC); + } + } + /* Machine code or script... + * If machine code, then block it if monrc is active. + */ + if(fp->flags & TFS_EBIN) { + if(tfsRunningMonrc()) { + err = TFSERR_NORUNMONRC; + } else { + err = tfsexec(fp,verbose); + } + } else { + err = tfsscript(&fstat,verbose); + } + + return(err); } /* tfsrunrcfile(): @@ -2564,9 +2685,9 @@ tfsrun(char **arglist,int verbose) * 1. Call tfsstat("monrc") * 2. Call tfsstat("monrc.bak") * 3. For each device, prepend the device prefix to the monrc name - * and run tfsstat() on that string (i.e.. tfsstat(//A/monrc)). - * This supports a multi-device system in which the monrc file is not - * in the first TFS device. + * and run tfsstat() on that string (i.e.. tfsstat(//A/monrc)). + * This supports a multi-device system in which the monrc file is not + * in the first TFS device. * * If one of the above is found, it will be automatically executed. * Note that only the first one found will be executed. @@ -2580,90 +2701,93 @@ tfsrun(char **arglist,int verbose) void tfsrunrcfile(void) { - int err; - TDEV *tdp; - TFILE *tfp; - char *arglist[2], bigname[TFSNAMESIZE+1], *name; - + int err; + TDEV *tdp; + TFILE *tfp; + char *arglist[2], bigname[TFSNAMESIZE+1], *name; + #if TFS_RUN_DISABLE - return; + return; #endif - if (!tfsInitialized) { - printf("TFS not initialized, tfsrunrcfile aborting.\n"); - return; - } - - name = TFS_RCFILE; - tfp = tfsstat(name); - if (!tfp) { - name = TFS_RCFILE ".bak"; - tfp = tfsstat(name); - } - if (!tfp) { - for(tdp=tfsDeviceTbl; (tdp->start != TFSEOT) ; tdp++) { - sprintf(bigname,"%smonrc",tdp->prefix); - if ((tfp = tfsstat(bigname))) { - name = bigname; - break; - } - } - } - if (!tfp) - return; - - if (TFS_FLAGS(tfp) & (TFS_BRUN | TFS_QRYBRUN)) - printf("Warning: %s is autobootable\n",name); - - arglist[0] = name; - arglist[1] = (char *)0; - - tfsMonrcActive = 1; - err = tfsrun_abortableautoboot(arglist,0); - tfsMonrcActive = 0; - if (err != TFS_OKAY) - printf("%s: %s\n",name,tfserrmsg(err)); - return; + if(!tfsInitialized) { + printf("TFS not initialized, tfsrunrcfile aborting.\n"); + return; + } + + name = TFS_RCFILE; + tfp = tfsstat(name); + if(!tfp) { + name = TFS_RCFILE ".bak"; + tfp = tfsstat(name); + } + if(!tfp) { + for(tdp=tfsDeviceTbl; (tdp->start != TFSEOT) ; tdp++) { + sprintf(bigname,"%smonrc",tdp->prefix); + if((tfp = tfsstat(bigname))) { + name = bigname; + break; + } + } + } + if(!tfp) { + return; + } + + if(TFS_FLAGS(tfp) & (TFS_BRUN | TFS_QRYBRUN)) { + printf("Warning: %s is autobootable\n",name); + } + + arglist[0] = name; + arglist[1] = (char *)0; + + tfsMonrcActive = 1; + err = tfsrun_abortableautoboot(arglist,0); + tfsMonrcActive = 0; + if(err != TFS_OKAY) { + printf("%s: %s\n",name,tfserrmsg(err)); + } + return; } int tfsRunningMonrc(void) { - return(tfsMonrcActive); + return(tfsMonrcActive); } /* tfsnext(): - * Called to retrieve the "next" file in the tfs list. If - * incoming argument is NULL then return the first file in the list. If no - * more files, return NULL; else return the tfshdr structure pointer to the - * next (or first) file in the tfs. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Called to retrieve the "next" file in the tfs list. If + * incoming argument is NULL then return the first file in the list. If no + * more files, return NULL; else return the tfshdr structure pointer to the + * next (or first) file in the tfs. + * MONLIB NOTICE: this function is accessible through monlib.c. */ TFILE * tfsnext(TFILE *fp) { - TDEV *tdp; - TFILE *fpnext; - - if (!fp) { - tdp = tfsDeviceTbl; - fpnext = (TFILE *) tfsDeviceTbl[0].start; - } - else { - tdp = gettfsdev(fp); - fpnext = nextfp(fp,0); - } - - while(tdp->start != TFSEOT) { - while(validtfshdr(fpnext)) { - if (TFS_FILEEXISTS(fpnext)) - return (fpnext); - fpnext = nextfp(fpnext,0); - } - tdp++; - fpnext = (TFILE *)tdp->start; - } - return ((TFILE *) 0); + TDEV *tdp; + TFILE *fpnext; + + if(!fp) { + tdp = tfsDeviceTbl; + fpnext = (TFILE *) tfsDeviceTbl[0].start; + } else { + tdp = gettfsdev(fp); + fpnext = nextfp(fp,0); + } + + while(tdp->start != TFSEOT) { + while(validtfshdr(fpnext)) { + if(TFS_FILEEXISTS(fpnext)) { + return (fpnext); + } + fpnext = nextfp(fpnext,0); + } + tdp++; + fpnext = (TFILE *)tdp->start; + } + return ((TFILE *) 0); } /* tfsBase() and the notion of a "fake" file header... @@ -2673,11 +2797,11 @@ tfsnext(TFILE *fp) * the header to the file header pointer... * * #define TFS_BASE(fp) (char *)(fp)+(fp->hdrsize) - * + * * As of Mar 2007, TFS supports the ability to load an executable image * (usually elf) from outside TFS space by simply using the command... * - * tfs ld 0x12345678,E,info + * tfs ld 0x12345678,E,info * * This is useful for cases where users don't want the large elf image to * be in TFS because each time it is updated, a defrag will occur. If put @@ -2694,137 +2818,147 @@ tfsnext(TFILE *fp) char * tfsBase(TFILE *fp) { - if (fp->rsvd[0] != 0xffffffff) - return((char *)fp->rsvd[0]); - else - return(TFS_BASE(fp)); + if(fp->rsvd[0] != 0xffffffff) { + return((char *)fp->rsvd[0]); + } else { + return(TFS_BASE(fp)); + } } /* tfsstat(): - * Steps through the list of files until it finds the specified - * filename or reaches the end of the list. If found, a pointer to that - * file's structure is returned; else return 0. - * MONLIB NOTICE: this function is accessible through monlib.c. + * Steps through the list of files until it finds the specified + * filename or reaches the end of the list. If found, a pointer to that + * file's structure is returned; else return 0. + * MONLIB NOTICE: this function is accessible through monlib.c. */ TFILE * tfsstat(char *name) { - if (!tfsInitialized) { - printf("TFS not initialized, tfsstat aborting.\n"); - return(0); - } + if(!tfsInitialized) { + printf("TFS not initialized, tfsstat aborting.\n"); + return(0); + } - return(_tfsstat(name,1)); + return(_tfsstat(name,1)); } TFILE * _tfsstat(char *name,int uselink) { - int len; - TFILE *fp; - TDEV *tdp; - char *prefix, *dotslash = "./"; - - if (tfsTrace > 0) - printf("_tfsstat(%s,%d)\n",name,uselink); - - /* Support the ability to have a hex address for a filename... - * This uses a "fake" file header. - */ - if ((name[0] == '0') && (name[1] == 'x')) { - int rsvd; - static TFILE fakehdr; /* WARNING: not reentrant!!! */ - char *comma1, *comma2, tmpname[TFSNAMESIZE+1]; - - strncpy(tmpname,name,sizeof(tmpname)); - - comma1 = comma2 = (char *)0; - if ((comma1 = strchr(tmpname,',')) != 0) - comma2 = strchr(comma1+1,','); - - if (comma1) *comma1 = 0; - if (comma2) *comma2 = 0; - - strcpy(fakehdr.name,tmpname); - if (comma2) - strcpy(fakehdr.info,comma2+1); - else - fakehdr.info[0] = 0; - fakehdr.hdrsize = TFSHDRSIZ; - fakehdr.hdrvrsn = TFSHDRVERSION; - fakehdr.filsize = 0; - if (comma1) - tfsflagsatob(comma1+1, &fakehdr.flags); - else - fakehdr.flags = 0; - fakehdr.flags |= TFS_ACTIVE | TFS_NSTALE; - fakehdr.filcrc = 0; - fakehdr.modtime = tfsGetLtime(); - - for(rsvd=0;rsvd<TFS_RESERVED;rsvd++) - fakehdr.rsvd[rsvd] = 0xffffffff; - fakehdr.rsvd[0] = strtol(name,0,0); - - fakehdr.next = 0; - fakehdr.hdrcrc = 0; - fakehdr.hdrcrc = crc32((uchar *)&fakehdr,TFSHDRSIZ); - fakehdr.next = (TFILE *)0; - return(&fakehdr); - } - - /* Account for the possibility that the filename might have the - * device name prefixed for the first device in the table (or "./"). - */ - tdp = &tfsDeviceTbl[0]; - if (strncmp(name,tdp->prefix,strlen(tdp->prefix)) == 0) { - len = strlen(tdp->prefix); - prefix = tdp->prefix; - } - else if (strncmp(name,dotslash,2) == 0) { - len = 2; - prefix = dotslash; - } - else { - len = 0; - prefix = 0; - } - - if (prefix) { - fp = (TFILE *) tdp->start; - while(validtfshdr(fp)) { - if (TFS_FILEEXISTS(fp) && (strcmp(name+len, fp->name) == 0)) { - if (uselink && TFS_ISLINK(fp)) - return(_tfsstat(TFS_INFO(fp),0)); - else - return(fp); - } - fp = nextfp(fp,tdp); - } - } - - /* Then, if not found, walk through all TFS devices normally... - */ - for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) { - fp = (TFILE *) tdp->start; - while(validtfshdr(fp)) { - if (TFS_FILEEXISTS(fp) && (strcmp(name, fp->name) == 0)) { - if (uselink && TFS_ISLINK(fp)) - return(_tfsstat(TFS_INFO(fp),0)); - else - return(fp); - } - fp = nextfp(fp,tdp); - } - } - return ((TFILE *) 0); + int len; + TFILE *fp; + TDEV *tdp; + char *prefix, *dotslash = "./"; + + if(tfsTrace > 0) { + printf("_tfsstat(%s,%d)\n",name,uselink); + } + + /* Support the ability to have a hex address for a filename... + * This uses a "fake" file header. + */ + if((name[0] == '0') && (name[1] == 'x')) { + int rsvd; + static TFILE fakehdr; /* WARNING: not reentrant!!! */ + char *comma1, *comma2, tmpname[TFSNAMESIZE+1]; + + strncpy(tmpname,name,sizeof(tmpname)); + + comma1 = comma2 = (char *)0; + if((comma1 = strchr(tmpname,',')) != 0) { + comma2 = strchr(comma1+1,','); + } + + if(comma1) { + *comma1 = 0; + } + if(comma2) { + *comma2 = 0; + } + + strcpy(fakehdr.name,tmpname); + if(comma2) { + strcpy(fakehdr.info,comma2+1); + } else { + fakehdr.info[0] = 0; + } + fakehdr.hdrsize = TFSHDRSIZ; + fakehdr.hdrvrsn = TFSHDRVERSION; + fakehdr.filsize = 0; + if(comma1) { + tfsflagsatob(comma1+1, &fakehdr.flags); + } else { + fakehdr.flags = 0; + } + fakehdr.flags |= TFS_ACTIVE | TFS_NSTALE; + fakehdr.filcrc = 0; + fakehdr.modtime = tfsGetLtime(); + + for(rsvd=0; rsvd<TFS_RESERVED; rsvd++) { + fakehdr.rsvd[rsvd] = 0xffffffff; + } + fakehdr.rsvd[0] = strtol(name,0,0); + + fakehdr.next = 0; + fakehdr.hdrcrc = 0; + fakehdr.hdrcrc = crc32((uchar *)&fakehdr,TFSHDRSIZ); + fakehdr.next = (TFILE *)0; + return(&fakehdr); + } + + /* Account for the possibility that the filename might have the + * device name prefixed for the first device in the table (or "./"). + */ + tdp = &tfsDeviceTbl[0]; + if(strncmp(name,tdp->prefix,strlen(tdp->prefix)) == 0) { + len = strlen(tdp->prefix); + prefix = tdp->prefix; + } else if(strncmp(name,dotslash,2) == 0) { + len = 2; + prefix = dotslash; + } else { + len = 0; + prefix = 0; + } + + if(prefix) { + fp = (TFILE *) tdp->start; + while(validtfshdr(fp)) { + if(TFS_FILEEXISTS(fp) && (strcmp(name+len, fp->name) == 0)) { + if(uselink && TFS_ISLINK(fp)) { + return(_tfsstat(TFS_INFO(fp),0)); + } else { + return(fp); + } + } + fp = nextfp(fp,tdp); + } + } + + /* Then, if not found, walk through all TFS devices normally... + */ + for(tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++) { + fp = (TFILE *) tdp->start; + while(validtfshdr(fp)) { + if(TFS_FILEEXISTS(fp) && (strcmp(name, fp->name) == 0)) { + if(uselink && TFS_ISLINK(fp)) { + return(_tfsstat(TFS_INFO(fp),0)); + } else { + return(fp); + } + } + fp = nextfp(fp,tdp); + } + } + return ((TFILE *) 0); } /* tfsfstat(): - * Very similar in purpose to tfsstat(). This version is provided to the + * Very similar in purpose to tfsstat(). This version is provided to the * API as a "defrag-safe" version of tfsstat()... * If tfsstat() is called (returning a pointer into TFS memory space), then - * a defragmentation occurs, that pointer is stale; hence, the need for + * a defragmentation occurs, that pointer is stale; hence, the need for * an alternative that will load the content of the TFILE structure into * an application-supplied block of memory (usually a pointer to a local * TFILE structure). Using tfsfstat avoids this because if a defrag occurs, @@ -2842,37 +2976,40 @@ _tfsstat(char *name,int uselink) int tfsfstat(char *name, TFILE *apptfp) { - TFILE *tfp; - int otrace; + TFILE *tfp; + int otrace; + + otrace = tfsTrace; - otrace = tfsTrace; + if(tfsTrace > 0) { + tfsTrace = 0; + printf("tfsfstat(%s)\n",name); + } - if (tfsTrace > 0) { - tfsTrace = 0; - printf("tfsfstat(%s)\n",name); - } + tfp = tfsstat(name); + tfsTrace = otrace; - tfp = tfsstat(name); - tfsTrace = otrace; - - if (!tfp) - return(-1); + if(!tfp) { + return(-1); + } - memcpy((char *)apptfp,(char *)tfp,sizeof(TFILE)); - return(0); + memcpy((char *)apptfp,(char *)tfp,sizeof(TFILE)); + return(0); } int showTfsError(int errno, char *msg) { - if (errno == TFS_OKAY) - return(TFS_OKAY); + if(errno == TFS_OKAY) { + return(TFS_OKAY); + } - if (msg) - printf("%s: %s\n",msg,tfserrmsg(errno)); - else - printf("%s\n",tfserrmsg(errno)); - return(errno); + if(msg) { + printf("%s: %s\n",msg,tfserrmsg(errno)); + } else { + printf("%s\n",tfserrmsg(errno)); + } + return(errno); } /* tfscfg(): @@ -2884,173 +3021,179 @@ int tfscfg(char *prefix, ulong tfsstart, ulong tfsend, ulong spare) { #if INCLUDE_FLASH - uchar *base; - TDEV *tdp, td; - int idx, sec_start, sec_end, size, flash_not_erased, rc; - - if (tfsTrace) { - printf("tfscfg(%s,0x%lx,0x%lx,0x%lx)\n", - prefix, tfsstart, tfsend, spare); - } - - /* If the alt_tfsdevtbl pointer is initialized to 0xffffffff, then - * we assume that this feature has been disable for this port. - */ - if (alt_tfsdevtbl == (struct tfsdev *)0xffffffff) { - return(TFSERR_NOTAVAILABLE); - } + uchar *base; + TDEV *tdp, td; + int idx, sec_start, sec_end, size, flash_not_erased, rc; + + if(tfsTrace) { + printf("tfscfg(%s,0x%lx,0x%lx,0x%lx)\n", + prefix, tfsstart, tfsend, spare); + } + + /* If the alt_tfsdevtbl pointer is initialized to 0xffffffff, then + * we assume that this feature has been disable for this port. + */ + if(alt_tfsdevtbl == (struct tfsdev *)0xffffffff) { + return(TFSERR_NOTAVAILABLE); + } #ifndef TFS_ALTDEVTBL_BASE - /* We assume that if TFS_ALTDEVTBL_BASE is defined, then it is pointing + /* We assume that if TFS_ALTDEVTBL_BASE is defined, then it is pointing * to fixed area in flash; hence, we don't care if uMon is running out - * of RAM or not (because the default alt_tfsdevtbl[] which would be - * relocated to ram at startup isn't being used). - */ - if (uMonInRam()) { - printf("tfs cfg applies to rom-based images only\n"); - return(TFSERR_MEMFAIL); - } + * of RAM or not (because the default alt_tfsdevtbl[] which would be + * relocated to ram at startup isn't being used). + */ + if(uMonInRam()) { + printf("tfs cfg applies to rom-based images only\n"); + return(TFSERR_MEMFAIL); + } #endif - /* Match incoming prefix with an entry in the TFS device table. - * If prefix pointer is NULL, then use first device in table... - */ - if (prefix == (char *)0) { - tdp=&tfsDeviceTbl[0]; - idx = 0; - } - else { - for(idx=0,tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++,idx++) { - if (!strcmp(prefix,tdp->prefix)) - break; - } - } - if (tdp->start == TFSEOT) - return(TFSERR_BADPREFIX); - - /* If no change, just return success... - */ - if ((tfsstart == tdp->start) && (tfsend == tdp->end)) - return(TFS_OKAY); - - /* If the alternate table entry is already written, then error... - * User must run "tfs cfg restore" first. - */ - if (alt_tfsdevtbl[idx].prefix != (char *)0xffffffff) { - printf("Hint: try 'tfs cfg restore' first.\n"); - return(TFSERR_ALTINUSE); - } - - if (spare == 0xffffffff) - spare = tfsend+1; - - /* Do some checking prior to applying the new configuration... - */ - if (tfsend <= tfsstart) - return(TFSERR_BADARG); - - if (addrtosector((uchar *)tfsstart,&sec_start,0,&base) == -1) - return(TFSERR_BADARG); - - if (tfsstart != (ulong)base) { - printf("Start (0x%lx) is not base address of sector\n",tfsstart); - return(TFSERR_BADARG); - } - - if (addrtosector((uchar *)tfsend,&sec_end,&size,&base) == -1) - return(TFSERR_BADARG); - - if (addrtosector((uchar *)spare,0,&size,&base) == -1) - return(TFSERR_BADARG); - - if (spare != (ulong)base) { - printf("Spare (0x%lx) is not base address of sector\n",spare); - return(TFSERR_BADARG); - } - - flash_not_erased = 0; + /* Match incoming prefix with an entry in the TFS device table. + * If prefix pointer is NULL, then use first device in table... + */ + if(prefix == (char *)0) { + tdp=&tfsDeviceTbl[0]; + idx = 0; + } else { + for(idx=0,tdp=tfsDeviceTbl; tdp->start != TFSEOT; tdp++,idx++) { + if(!strcmp(prefix,tdp->prefix)) { + break; + } + } + } + if(tdp->start == TFSEOT) { + return(TFSERR_BADPREFIX); + } + + /* If no change, just return success... + */ + if((tfsstart == tdp->start) && (tfsend == tdp->end)) { + return(TFS_OKAY); + } + + /* If the alternate table entry is already written, then error... + * User must run "tfs cfg restore" first. + */ + if(alt_tfsdevtbl[idx].prefix != (char *)0xffffffff) { + printf("Hint: try 'tfs cfg restore' first.\n"); + return(TFSERR_ALTINUSE); + } + + if(spare == 0xffffffff) { + spare = tfsend+1; + } + + /* Do some checking prior to applying the new configuration... + */ + if(tfsend <= tfsstart) { + return(TFSERR_BADARG); + } + + if(addrtosector((uchar *)tfsstart,&sec_start,0,&base) == -1) { + return(TFSERR_BADARG); + } + + if(tfsstart != (ulong)base) { + printf("Start (0x%lx) is not base address of sector\n",tfsstart); + return(TFSERR_BADARG); + } + + if(addrtosector((uchar *)tfsend,&sec_end,&size,&base) == -1) { + return(TFSERR_BADARG); + } + + if(addrtosector((uchar *)spare,0,&size,&base) == -1) { + return(TFSERR_BADARG); + } + + if(spare != (ulong)base) { + printf("Spare (0x%lx) is not base address of sector\n",spare); + return(TFSERR_BADARG); + } + + flash_not_erased = 0; #ifdef TFS_ALTDEVTBL_BASE - /* If TFS_ALTDEVTBL_BASE is defined, then the alt_tfsdevtbl value is - * pointing to space that may not be automatically allocated by the - * compiler (as it would have been if TFS_ALTDEVTBL_BASE wasn't - * defined). As a result, we need to check to make sure that the - * space we need is erased and available... - * If this check fails, it probably indicates that the space allocated - * for this structure at build time (possibly in rom_reset.s) is just - * not big enough and needs to be increased at build time. - */ - { - uchar *end = (uchar *)&alt_tfsdevtbl[idx]; - end += sizeof(struct tfsdev) - 1; - if (!flasherased((uchar *)&alt_tfsdevtbl[idx],end)) { - printf("Alternate tfsdev structure area (0x%lx-0x%lx) not erased\n", - (long)alt_tfsdevtbl,(long)end); - flash_not_erased = 1; - } - } + /* If TFS_ALTDEVTBL_BASE is defined, then the alt_tfsdevtbl value is + * pointing to space that may not be automatically allocated by the + * compiler (as it would have been if TFS_ALTDEVTBL_BASE wasn't + * defined). As a result, we need to check to make sure that the + * space we need is erased and available... + * If this check fails, it probably indicates that the space allocated + * for this structure at build time (possibly in rom_reset.s) is just + * not big enough and needs to be increased at build time. + */ + { + uchar *end = (uchar *)&alt_tfsdevtbl[idx]; + end += sizeof(struct tfsdev) - 1; + if(!flasherased((uchar *)&alt_tfsdevtbl[idx],end)) { + printf("Alternate tfsdev structure area (0x%lx-0x%lx) not erased\n", + (long)alt_tfsdevtbl,(long)end); + flash_not_erased = 1; + } + } #endif - if (tfsend < tdp->end) { - if (!flasherased((uchar *)tfsend,(uchar *)tdp->end)) { - printf("flash within 0x%lx -> 0x%lx not erased\n", - tfsend,tdp->end); - flash_not_erased = 1; - } - } - else if (tdp->end < tfsend) { - if (!flasherased((uchar *)tdp->end,(uchar *)tfsend)) { - printf("flash within 0x%lx -> 0x%lx not erased\n", - tdp->end,tfsend); - flash_not_erased = 1; - } - } - if (tfsstart < tdp->start) { - if (!flasherased((uchar *)tfsstart,(uchar *)tdp->start)) { - printf("flash within 0x%lx -> 0x%lx not erased\n", - tfsstart,tdp->start); - flash_not_erased = 1; - } - } - else if (tdp->start < tfsstart) { - if (!flasherased((uchar *)tdp->start,(uchar *)tfsstart)) { - printf("flash within 0x%lx -> 0x%lx not erased\n", - tdp->start,tfsstart); - flash_not_erased = 1; - } - } - - if (flash_not_erased) - return(TFSERR_MEMFAIL); - - td.prefix = tdp->prefix; - td.start = tfsstart; - td.end = tfsend; - td.spare = spare; - td.sparesize = size; - td.sectorcount = sec_end - sec_start + 1; - - /* When a TFS device is re-configured using "tfs cfg", it - * shouldn't do any self-adjustment based on flash because - * the user is forcing the configuration. So, the reconfigured - * device must always have TFS_DEVINFO_DYNAMIC cleared... - */ - tdp->devinfo &= ~TFS_DEVINFO_DYNAMIC; - td.devinfo = tdp->devinfo; - - rc = tfsflashwrite((uchar *)&alt_tfsdevtbl[idx], - (uchar *)&td,sizeof(TDEV)); - - if (rc == TFS_OKAY) { - tdp->start = tfsstart; - tdp->end = tfsend; - tdp->spare = spare; - tdp->sparesize = size; - tdp->sectorcount = sec_end - sec_start + 1; - } - return(rc); + if(tfsend < tdp->end) { + if(!flasherased((uchar *)tfsend,(uchar *)tdp->end)) { + printf("flash within 0x%lx -> 0x%lx not erased\n", + tfsend,tdp->end); + flash_not_erased = 1; + } + } else if(tdp->end < tfsend) { + if(!flasherased((uchar *)tdp->end,(uchar *)tfsend)) { + printf("flash within 0x%lx -> 0x%lx not erased\n", + tdp->end,tfsend); + flash_not_erased = 1; + } + } + if(tfsstart < tdp->start) { + if(!flasherased((uchar *)tfsstart,(uchar *)tdp->start)) { + printf("flash within 0x%lx -> 0x%lx not erased\n", + tfsstart,tdp->start); + flash_not_erased = 1; + } + } else if(tdp->start < tfsstart) { + if(!flasherased((uchar *)tdp->start,(uchar *)tfsstart)) { + printf("flash within 0x%lx -> 0x%lx not erased\n", + tdp->start,tfsstart); + flash_not_erased = 1; + } + } + + if(flash_not_erased) { + return(TFSERR_MEMFAIL); + } + + td.prefix = tdp->prefix; + td.start = tfsstart; + td.end = tfsend; + td.spare = spare; + td.sparesize = size; + td.sectorcount = sec_end - sec_start + 1; + + /* When a TFS device is re-configured using "tfs cfg", it + * shouldn't do any self-adjustment based on flash because + * the user is forcing the configuration. So, the reconfigured + * device must always have TFS_DEVINFO_DYNAMIC cleared... + */ + tdp->devinfo &= ~TFS_DEVINFO_DYNAMIC; + td.devinfo = tdp->devinfo; + + rc = tfsflashwrite((uchar *)&alt_tfsdevtbl[idx], + (uchar *)&td,sizeof(TDEV)); + + if(rc == TFS_OKAY) { + tdp->start = tfsstart; + tdp->end = tfsend; + tdp->spare = spare; + tdp->sparesize = size; + tdp->sectorcount = sec_end - sec_start + 1; + } + return(rc); #else - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); #endif } @@ -3065,47 +3208,51 @@ int tfscfgrestore(void) { #if INCLUDE_FLASH - char *ram; - ulong offset; - uchar *base; - int sec_start, size; - - printf("WARNING: uMon control structure restoration in progress.\n"); - printf("Allow this to complete (2-5 seconds) without interruption\n"); - - if (addrtosector((uchar *)alt_tfsdevtbl,&sec_start,&size,&base) == -1) - return(TFSERR_FLASHFAILURE); - - offset = (ulong)alt_tfsdevtbl - (ulong)base; - ram = (char *)getAppRamStart(); - - if (s_memcpy(ram,(char *)base,size,0,0) == -1) - return(TFSERR_MEMFAIL); - if (s_memset((uchar *)(ram+offset),0xff,TFS_ALTDEVTBL_SIZE,0,0) == -1) - return(TFSERR_MEMFAIL); - - /* In most ports, flashewrite() doesn't return. */ - if (flashewrite((uchar *)base,(uchar *)ram,size) < 0) - return(TFSERR_FLASHFAILURE); - else - return(TFS_OKAY); + char *ram; + ulong offset; + uchar *base; + int sec_start, size; + + printf("WARNING: uMon control structure restoration in progress.\n"); + printf("Allow this to complete (2-5 seconds) without interruption\n"); + + if(addrtosector((uchar *)alt_tfsdevtbl,&sec_start,&size,&base) == -1) { + return(TFSERR_FLASHFAILURE); + } + + offset = (ulong)alt_tfsdevtbl - (ulong)base; + ram = (char *)getAppRamStart(); + + if(s_memcpy(ram,(char *)base,size,0,0) == -1) { + return(TFSERR_MEMFAIL); + } + if(s_memset((uchar *)(ram+offset),0xff,TFS_ALTDEVTBL_SIZE,0,0) == -1) { + return(TFSERR_MEMFAIL); + } + + /* In most ports, flashewrite() doesn't return. */ + if(flashewrite((uchar *)base,(uchar *)ram,size) < 0) { + return(TFSERR_FLASHFAILURE); + } else { + return(TFS_OKAY); + } #else - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); #endif } int tfsclean_on(void) { - TfsCleanEnable++; - return(TfsCleanEnable); + TfsCleanEnable++; + return(TfsCleanEnable); } int tfsclean_off(void) { - TfsCleanEnable--; - return(TfsCleanEnable); + TfsCleanEnable--; + return(TfsCleanEnable); } /* tfsclean_nps(): @@ -3120,120 +3267,131 @@ tfsclean_off(void) int tfsclean_nps(TDEV *tdp, char *ramstart, ulong ramsize) { - TFILE *tfp; - ulong appramstart; - uchar *tbuf, *ramend, *cp1, *cp2; - int dtot, nfadd, len, chkstat; + TFILE *tfp; + ulong appramstart; + uchar *tbuf, *ramend, *cp1, *cp2; + int dtot, nfadd, len, chkstat; #if INCLUDE_FLASH - TFILE *lasttfp; + TFILE *lasttfp; #endif - if (TfsCleanEnable < 0) - return(TFSERR_CLEANOFF); - - if (ramstart) - appramstart = (ulong)ramstart; - else - appramstart = getAppRamStart(); - - if (ramsize) - ramend = (uchar *)appramstart + appramstart; - else - ramend = 0; - - /* Determine how many "dead" files exist. */ - dtot = 0; - tfp = (TFILE *)tdp->start; - while(validtfshdr(tfp)) { - if (!TFS_FILEEXISTS(tfp)) - dtot++; - tfp = nextfp(tfp,tdp); - } - - if (dtot == 0) - return(TFS_OKAY); - - printf("TFS device '%s' non-powersafe defragmentation\n",tdp->prefix); - - tbuf = (uchar *)appramstart; - tfp = (TFILE *)(tdp->start); + if(TfsCleanEnable < 0) { + return(TFSERR_CLEANOFF); + } + + if(ramstart) { + appramstart = (ulong)ramstart; + } else { + appramstart = getAppRamStart(); + } + + if(ramsize) { + ramend = (uchar *)appramstart + appramstart; + } else { + ramend = 0; + } + + /* Determine how many "dead" files exist. */ + dtot = 0; + tfp = (TFILE *)tdp->start; + while(validtfshdr(tfp)) { + if(!TFS_FILEEXISTS(tfp)) { + dtot++; + } + tfp = nextfp(tfp,tdp); + } + + if(dtot == 0) { + return(TFS_OKAY); + } + + printf("TFS device '%s' non-powersafe defragmentation\n",tdp->prefix); + + tbuf = (uchar *)appramstart; + tfp = (TFILE *)(tdp->start); #if INCLUDE_FLASH - lasttfp = tfp; + lasttfp = tfp; #endif - nfadd = tdp->start; - while(validtfshdr(tfp)) { - if (TFS_FILEEXISTS(tfp)) { - len = TFS_SIZE(tfp) + sizeof(struct tfshdr); - if (len % TFS_FSIZEMOD) - len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD); - nfadd += len; - - if (ramend && ((tbuf+len) > ramend)) { - printf("Insufficient ram, aborting defrag.\n"); - return(TFSERR_MEMFAIL); - } - - if (s_memcpy((char *)tbuf,(char *)tfp,len,0,0) != 0) - return(TFSERR_MEMFAIL); - - ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; - tbuf += len; - } + nfadd = tdp->start; + while(validtfshdr(tfp)) { + if(TFS_FILEEXISTS(tfp)) { + len = TFS_SIZE(tfp) + sizeof(struct tfshdr); + if(len % TFS_FSIZEMOD) { + len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD); + } + nfadd += len; + + if(ramend && ((tbuf+len) > ramend)) { + printf("Insufficient ram, aborting defrag.\n"); + return(TFSERR_MEMFAIL); + } + + if(s_memcpy((char *)tbuf,(char *)tfp,len,0,0) != 0) { + return(TFSERR_MEMFAIL); + } + + ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; + tbuf += len; + } #if INCLUDE_FLASH - lasttfp = tfp; + lasttfp = tfp; #endif - tfp = nextfp(tfp,tdp); - } - - /* We've now copied all of the active files from flash to ram. - * Now we want to see how much of the flash space needs to be - * erased. We only need to erase the sectors that have changed... - */ - cp1 = (uchar *)tdp->start; - cp2 = (uchar *)appramstart; - while(cp2 < tbuf) { - if (*cp1 != *cp2) - break; - cp1++; cp2++; - } + tfp = nextfp(tfp,tdp); + } + + /* We've now copied all of the active files from flash to ram. + * Now we want to see how much of the flash space needs to be + * erased. We only need to erase the sectors that have changed... + */ + cp1 = (uchar *)tdp->start; + cp2 = (uchar *)appramstart; + while(cp2 < tbuf) { + if(*cp1 != *cp2) { + break; + } + cp1++; + cp2++; + } #if INCLUDE_FLASH - if ((cp2 != tbuf) || (!TFS_FILEEXISTS(lasttfp))) { - int first, last; - - if (addrtosector(cp1,&first,0,0) == -1) - return(TFSERR_FLASHFAILURE); - - if (addrtosector((uchar *)tdp->end,&last,0,0) == -1) - return(TFSERR_FLASHFAILURE); - printf("Erasing sectors %d-%d...\n",first,last); - while(first<last) { - if (flasherase(first++) == 0) - return(TFSERR_FLASHFAILURE); - } - } + if((cp2 != tbuf) || (!TFS_FILEEXISTS(lasttfp))) { + int first, last; + + if(addrtosector(cp1,&first,0,0) == -1) { + return(TFSERR_FLASHFAILURE); + } + + if(addrtosector((uchar *)tdp->end,&last,0,0) == -1) { + return(TFSERR_FLASHFAILURE); + } + printf("Erasing sectors %d-%d...\n",first,last); + while(first<last) { + if(flasherase(first++) == 0) { + return(TFSERR_FLASHFAILURE); + } + } + } #endif - /* Copy data placed in RAM back to flash: */ - printf("Restoring flash...\n"); - if (TFS_DEVTYPE_ISRAM(tdp)) { - memcpy((char *)(tdp->start),(char *)appramstart, - (tbuf-(uchar*)appramstart)); - } - else { + /* Copy data placed in RAM back to flash: */ + printf("Restoring flash...\n"); + if(TFS_DEVTYPE_ISRAM(tdp)) { + memcpy((char *)(tdp->start),(char *)appramstart, + (tbuf-(uchar *)appramstart)); + } else { #if INCLUDE_FLASH - int err; + int err; - err = AppFlashWrite((uchar *)(tdp->start),(uchar *)appramstart, - (tbuf-(uchar*)appramstart)); - if (err < 0) + err = AppFlashWrite((uchar *)(tdp->start),(uchar *)appramstart, + (tbuf-(uchar *)appramstart)); + if(err < 0) #endif - return(TFSERR_FLASHFAILURE); - } + return(TFSERR_FLASHFAILURE); + } - /* All defragmentation is done, so verify sanity of files... */ - chkstat = tfscheck(tdp,1); + /* All defragmentation is done, so verify sanity of files... */ + chkstat = tfscheck(tdp,1); - return(chkstat); + return(chkstat); } /* tfsclean(): @@ -3251,129 +3409,132 @@ tfsclean_nps(TDEV *tdp, char *ramstart, ulong ramsize) int tfsclean(TDEV *tdp,int verbose) { - TFILE *tfp, *tfp1, *tfpnxt; - int cleanresult, size; - char *cp; - - if (TFS_DEVTYPE_ISRAM(tdp)) { - cp = 0; - tfp = (TFILE *)tdp->start; - while(validtfshdr(tfp)) { - tfpnxt = nextfp(tfp,tdp); - if (TFS_DELETED(tfp)) { - if (cp == 0) - cp = (char *)tfp; - } - else { - if (cp != 0) { - size = TFS_SIZE(tfp) + TFSHDRSIZ; - if (size & 0xf) - size = (size | 0xf) + 1; - memcpy(cp,(char *)tfp,size); - tfp1 = (TFILE *)cp; - tfp1->next = (TFILE *)(cp+size); - tfp1->hdrcrc = tfshdrcrc(tfp1); - cp += size; - } - } - tfp = tfpnxt; - } - if (cp) - memset(cp,0xff,(char *)(tdp->end)-cp); - cleanresult = TFS_OKAY; - } - else { - cleanresult = _tfsclean(tdp,0,verbose); - if (cleanresult != TFS_OKAY) { - if (getenv("APP_EXITONCLEANERROR")) - appexit(0); + TFILE *tfp, *tfp1, *tfpnxt; + int cleanresult, size; + char *cp; + + if(TFS_DEVTYPE_ISRAM(tdp)) { + cp = 0; + tfp = (TFILE *)tdp->start; + while(validtfshdr(tfp)) { + tfpnxt = nextfp(tfp,tdp); + if(TFS_DELETED(tfp)) { + if(cp == 0) { + cp = (char *)tfp; + } + } else { + if(cp != 0) { + size = TFS_SIZE(tfp) + TFSHDRSIZ; + if(size & 0xf) { + size = (size | 0xf) + 1; + } + memcpy(cp,(char *)tfp,size); + tfp1 = (TFILE *)cp; + tfp1->next = (TFILE *)(cp+size); + tfp1->hdrcrc = tfshdrcrc(tfp1); + cp += size; + } + } + tfp = tfpnxt; + } + if(cp) { + memset(cp,0xff,(char *)(tdp->end)-cp); + } + cleanresult = TFS_OKAY; + } else { + cleanresult = _tfsclean(tdp,0,verbose); + if(cleanresult != TFS_OKAY) { + if(getenv("APP_EXITONCLEANERROR")) { + appexit(0); + } #if INCLUDE_TFSSCRIPT - if (getenv("SCR_EXITONCLEANERROR")) - ScriptExitFlag = EXIT_SCRIPT; + if(getenv("SCR_EXITONCLEANERROR")) { + ScriptExitFlag = EXIT_SCRIPT; + } #endif - } - } + } + } - return(cleanresult); + return(cleanresult); } -#else /* INCLUDE_TFS */ +#else /* INCLUDE_TFS */ char * tfserrmsg(int errno) { - return(0); + return(0); } int tfsinit(void) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } int tfsfstat(char *name, TFILE *apptfp) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } TFILE * tfsstat(char *name) { - return ((TFILE *) 0); + return ((TFILE *) 0); } int tfslink(char *src, char *target) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } TFILE * tfsnext(TFILE *fp) { - return ((TFILE *) 0); + return ((TFILE *) 0); } int tfsrun(char **arglist,int verbose) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } int tfsunlink(char *name) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } int tfsadd(char *name, char *info, char *flags, uchar *src, int size) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } long tfsctrl(int rqst,long arg1,long arg2) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } long tfstell(int fd) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } int tfsRunningMonrc(void) { - return(0); + return(0); } int tfsspace(char *addr) { - return(0); + return(0); } -#endif /* INCLUDE_TFS else */ +#endif /* INCLUDE_TFS else */ |