📄 tfs.c
字号:
/* 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.
*/
int
_tfsinit(TDEV *tdpin)
{
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);
}
int
tfsinit(void)
{
if (tfsTrace > 0)
printf("tfsinit()\n");
return(_tfsinit(0));
}
/* tfsSpaceErased():
* Return 0 if the space pointed to by the incoming arguments is not
* erased; else 1.
*/
int
tfsSpaceErased(uchar *begin,int size)
{
uchar *end;
end = begin+size;
while(begin < end) {
if (*begin != 0xff)
return(0);
begin++;
}
return(1);
}
/* tfsFtot():
* 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;
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.
*/
int
tfsFileIsOpened(char *name)
{
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);
}
/* tfsunopen():
* 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);
}
/* 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.
*
*
* 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 = gettfsdev_fromprefix((char *)arg1,0);
if (!tdp)
retval = TFSERR_BADARG;
else
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():
* Given the filename, return the device pointer associated with
* that filename. The device used depends on the prefix of
* the incoming file name. If the incoming prefix doesn't match
* any of the devices in the table, then return a pointer to the
* first device in the table (assumed to be the default).
*/
TDEV *
tfsNameToDevice(char *name)
{
TDEV *tdp;
for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
if (!strncmp(name,tdp->prefix,strlen(tdp->prefix)))
break;
}
if (tdp->start == TFSEOT)
tdp = tfsDeviceTbl;
return(tdp);
}
/* tfsramdevice():
* Create (or remove) a temporary (RAM-based) TFS device..
* This function is callable from both the API and the CLI.
* The TFS device table is established with one extra slot.
* The purpose of that slot is to allow the user to establish
* a temporary, ram-based TFS device. This function supports
* that capability.
*/
int
tfsramdevice(char *name,long base,long size)
{
TDEV *tdp;
int ramdevexists = 0;
char tmpname[TFSNAMESIZE+1];
static char devname[TFSNAMESIZE+1];
snprintf(tmpname,TFSNAMESIZE,"//Flash_Block_%s/",name);
if (tfsTrace > 0)
printf("tfsramdevice(%s,0x%lx,%ld)\n",name,base,size);
/* Scan through the device table to find the slot that can
* be used by the "ramdev" device...
*/
tdp = tfsDeviceTbl;
while(tdp->start != TFSEOT) {
if (strcmp(tdp->prefix,tmpname) == 0) {
ramdevexists = 1;
if (size != 0)
return(TFSERR_FILEEXISTS);
}
tdp++;
}
if (size == 0) {
if (ramdevexists) {
memset((char *)tdp->start,0,tdp->end-tdp->start);
tdp->start = 0;
tdp->devinfo = 0;
tdp->end = 0;
tdp--;
tdp->start = TFSEOT;
devname[0] = 0;
}
else
return(TFSERR_NOFILE);
}
else {
if (devname[0] != 0)
return(TFSERR_FILEEXISTS);
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.
*
* 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, state_table_overhead;
int ftot, cleanupcount, err, stale, ssize, 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -