/* fatfsPut(): * Copy data or file to a FATFS file. * * Input: * char *fatfspath * Pointer to FATFS file and path. * char *src * Pointer to TFS filename or a addr,len string. * The expected "addr,len" syntax is 0xADDR,LEN or 0xADDR,0xLEN. */ static int fatfsPut(char *src, char *fatfspath) { FILEINFO fi; char tfs, *p, *cp; uint32_t successcount, len, size, rc; if (strncmp(src,"0x",2) == 0) { tfs = 0; p = (char *)strtoul(src,&cp,0); cp++; len = strtoul(cp,0,0); } else { #if INCLUDE_TFS TFILE *tfp; tfs = 1; if ((tfp = tfsstat(src)) == 0) { printf("Can't find file '%s' in TFS\n",src); return(CMD_FAILURE); } p = TFS_BASE(tfp); len = TFS_SIZE(tfp); #else printf("TFS not built in\n"); return(-1); #endif } /* Copy 'len' bytes from 'p' to DOSFS file 'fatfspath'... */ if (DFS_OpenFile(&vi, (uint8_t *)fatfspath, DFS_WRITE, sector, &fi)) { printf("error opening '%s'\n",fatfspath); return(-1); } while(len > 0) { if (len >= SECTOR_SIZE) size = SECTOR_SIZE; else size = len; rc = DFS_WriteFile(&fi, sector2, (uint8_t *)p, &successcount, size); if ((rc != DFS_OK) || (successcount != size)) { printf("error writing '%s'\n",fatfspath); return(-1); } p += size; len -= size; } return(0); }
/* tfsipmod(): * Modify "in-place" a portion of a file in TFS. * This is a cheap and dirty way to modify a file... * The idea is that a file is created with a lot of writeable flash space * (data = 0xff). This function can then be called to immediately modify * blocks of space in that flash. It will not do any tfsunlink/tfsadd, and * it doesn't even require a tfsopen() tfsclose() wrapper. Its a fast and * efficient way to modify flash in the file system. * Arguments: * name = name of the file to be in-place-modified; * buf = new data to be written to flash; * offset = offset into file into which new data is to be written; * size = size of new data (in bytes). * * With offset of -1, set offset to location containing first 0xff value. * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsipmod(char *name,char *buf,int offset,int size) { int rc; TFILE *fp; uchar *cp; fp = tfsstat(name); if (!fp) return (TFSERR_NOFILE); if (!(fp->flags & TFS_IPMOD)) return(TFSERR_NOTIPMOD); if (offset == -1) { cp = (uchar *)(TFS_BASE(fp)); for (offset=0;offset<fp->filsize;offset++,cp++) { if (*cp == 0xff) break; } } else if (offset < -1) return(TFSERR_BADARG); if ((offset + size) > fp->filsize) return(TFSERR_WRITEMAX); /* BUG fixed: 2/21/2001: * The (ulong *) cast was done prior to adding offset to the base. * This caused the offset to be quadrupled. */ rc = tfsflashwrite((uchar *)(TFS_BASE(fp)+offset),(uchar *)buf,size); if (rc != TFS_OKAY) return(rc); tfslog(TFSLOG_IPM,name); return(TFS_OKAY); }
int Strace(int argc,char *argv[]) { char *symfile, fname[64]; TFILE *tfp; ulong *framepointer, pc, fp, offset; int tfd, opt, maxdepth, pass, verbose, bullseye; tfd = fp = 0; maxdepth = 20; verbose = 0; pc = ExceptionAddr; while ((opt=getopt(argc,argv,"d:F:P:rs:v")) != -1) { switch(opt) { case 'd': maxdepth = atoi(optarg); break; case 'F': fp = strtoul(optarg,0,0); break; case 'P': pc = strtoul(optarg,0,0); break; case 'r': showregs(); break; case 'v': verbose = 1; break; default: return(0); } } if (!fp) getreg("A6", (ulong *)&framepointer); else framepointer = (ulong *)fp; /* Start by detecting the presence of a symbol table file... */ symfile = getenv("SYMFILE"); if (!symfile) symfile = SYMFILE; tfp = tfsstat(symfile); if (tfp) { tfd = tfsopen(symfile,TFS_RDONLY,0); if (tfd < 0) tfp = (TFILE *)0; } /* Show current position: */ printf(" 0x%08lx",pc); if (tfp) { AddrToSym(tfd,pc,fname,&offset); printf(": %s()",fname); if (offset) printf(" + 0x%lx",offset); } putchar('\n'); /* Now step through the stack frame... */ bullseye = pass = 0; while(maxdepth) { /* ADD_CODE_HERE */ } if (!maxdepth) printf("Max depth termination\n"); if (tfp) { tfsclose(tfd,0); } return(0); }
int nandCmd(int argc,char *argv[]) { unsigned long addr; char *cmd, *dest, *src; int opt, len, rc; rc = 0; nandVerbose = 0; while((opt=getopt(argc,argv,"v")) != -1) { switch(opt) { case 'v': nandVerbose++; break; default: return(CMD_PARAM_ERROR); } } if(argc < optind+1) { return(CMD_PARAM_ERROR); } cmd = argv[optind]; if(nandVerbose) { printf("CMD: %s\n",cmd); } if(strcmp(cmd,"init") == 0) { nandInit(); } else if(strcmp(cmd,"info") == 0) { nandInfo(); } else if(strcmp(cmd,"erase") == 0) { if(argc != optind+3) { return(CMD_PARAM_ERROR); } addr = strtoul(argv[optind+1],0,0); len = (int)strtol(argv[optind+2],0,0); nandEraseChunk((char *)addr,len); } else if(strcmp(cmd,"write") == 0) { if(argc != optind+4) { return(CMD_PARAM_ERROR); } addr = strtoul(argv[optind+1],0,0); src = (char *)strtoul(argv[optind+2],0,0); len = (int)strtol(argv[optind+3],0,0); nandWriteChunk((char *)addr,src,len); } else if(strcmp(cmd,"read") == 0) { if(argc != optind+4) { return(CMD_PARAM_ERROR); } addr = strtoul(argv[optind+1],0,0); dest = (char *)strtoul(argv[optind+2],0,0); len = (int)strtol(argv[optind+3],0,0); nandReadChunk((char *)addr,dest,len); } #ifdef FLASHRAM_BASE else if(strcmp(cmd,"tfsload") == 0) { } else if(strcmp(cmd,"tfsstore") == 0) { } else if(strcmp(cmd,"tfserase") == 0) { } else if(strcmp(cmd, "tfsls") == 0) { int ftot; char *addr; TFILE tfshdr, *fp; ftot = 0; fp = &tfshdr; addr = (char *)BASE_OF_NAND; while(addr < (char *)END_OF_NAND) { char fbuf[32], *flags; if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf("nandReadChunk failed %d\n",rc); break; } if(fp->hdrsize == 0xffff) { break; } if(TFS_FILEEXISTS(fp)) { if(ftot == 0) { printf(" Name Size Offset Flags Info\n"); } ftot++; flags = tfsflagsbtoa(TFS_FLAGS(fp),fbuf); if((!flags) || (!fbuf[0])) { flags = " "; } printf(" %-23s %7ld 0x%08lx %-5s %s\n",TFS_NAME(fp), TFS_SIZE(fp),(unsigned long)(addr+TFSHDRSIZ), flags,TFS_INFO(fp)); } addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } } } else if(strcmp(cmd, "tfsrm") == 0) { char *addr; TFILE tfshdr, *fp; char *arg2 = argv[optind+1]; fp = &tfshdr; addr = (char *)BASE_OF_NAND; while(addr < (char *)END_OF_NAND) { if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf("nandReadChunk failed %d\n",rc); break; } if(fp->hdrsize == 0xffff) { printf("%s not found\n",arg2); break; } if(strcmp(TFS_NAME(fp),arg2) == 0) { if(TFS_FILEEXISTS(fp)) { fp->flags &= ~TFS_ACTIVE; if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf(" write_hdr failed %d\n",rc); } break; } } addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } } } else if(strcmp(cmd, "tfsadd") == 0) { int size; long bflags; TFILE tfshdr, *fp; char *addr; char *src, *name, *info; char *arg2 = argv[optind+1]; char *arg3 = argv[optind+2]; char *arg4 = argv[optind+3]; char *icomma, *fcomma; info = ""; bflags = 0; name = arg2; addr = (char *)BASE_OF_NAND; /* The incoming arguments can be either just the filename (in which * case we assume the source is the file in TFS with the same name), * or the filename, source address and size... */ if(argc == optind+2) { // Just filename? if((fp = tfsstat(name)) == (TFILE *)0) { printf("File '%s' not in TFS\n",name); return(CMD_FAILURE); } name = fp->name; info = fp->info; bflags = fp->flags; size = fp->filsize; src = (char *)(fp + 1); fp = &tfshdr; memset((char *)fp,0,TFSHDRSIZ); } else if(argc == optind+4) { // Filename with addr and len // Extract flags and info fields (if any) from the name... fcomma = strchr(name,','); if(fcomma) { icomma = strchr(fcomma+1,','); if(icomma) { *icomma = 0; info = icomma+1; } *fcomma = 0; bflags = tfsctrl(TFS_FATOB,(long)(fcomma+1),0); } fp = &tfshdr; memset((char *)fp,0,TFSHDRSIZ); size = (int)strtol(arg4,0,0); src = (char *)strtoul(arg3,0,0); } else { return(CMD_PARAM_ERROR); } while(addr < (char *)END_OF_NAND) { if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { break; } if(fp->hdrsize == 0xffff) { unsigned long nextfileaddr; /* We're at the address in NAND where we can add the new * file, but first we need to make sure there's enough * room... */ if((TFSHDRSIZ + size + 16) >= ((char *)END_OF_NAND - addr)) { printf(" not enough space\n"); return(CMD_FAILURE); } /* Copy name and info data to header. */ strcpy(fp->name, name); strcpy(fp->info, info); fp->hdrsize = TFSHDRSIZ; fp->hdrvrsn = TFSHDRVERSION; fp->filsize = size; fp->flags = bflags; fp->flags |= (TFS_ACTIVE | TFS_NSTALE); fp->filcrc = crc32((unsigned char *)src,size); fp->modtime = tfsGetLtime(); #if TFS_RESERVED { int rsvd; for(rsvd=0; rsvd<TFS_RESERVED; rsvd++) { fp->rsvd[rsvd] = 0xffffffff; } } #endif fp->next = 0; fp->hdrcrc = 0; fp->hdrcrc = crc32((unsigned char *)fp,TFSHDRSIZ); nextfileaddr = NAND_TFSRAM_BASE - NAND_TFS_BASE + (long)addr + TFSHDRSIZ + size; if(nextfileaddr & 0xf) { nextfileaddr = (nextfileaddr | 0xf) + 1; } fp->next = (TFILE *)nextfileaddr; printf(" writing %s...\n",arg2); if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf(" write_hdr failed %d\n",rc); } if((rc = nandWriteChunk(addr+TFSHDRSIZ,src,size)) < 0) { printf(" write_file failed %d\n",rc); } break; } if(strcmp(TFS_NAME(fp),arg2) == 0) { if(TFS_FILEEXISTS(fp)) { printf(" removing %s...\n",arg2); fp->flags &= ~TFS_ACTIVE; if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf(" write_hdr failed %d\n",rc); } } } addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } } } else if(strcmp(cmd, "tfsstat") == 0) { char *addr, *oaddr; TFILE tfshdr, *fp; unsigned long meminuse, memdead; fp = &tfshdr; meminuse = memdead = 0; addr = (char *)BASE_OF_NAND; while(addr < (char *)END_OF_NAND) { if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf("nandReadChunk failed %d\n",rc); break; } if(fp->hdrsize == 0xffff) { break; } oaddr = addr; addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } if(TFS_FILEEXISTS(fp)) { meminuse += addr - oaddr; } else { memdead += addr - oaddr; } } printf("Total: 0x%x, used: 0x%x, dead: 0x%x, avail: 0x%x\n", SIZE_OF_NAND, meminuse, memdead, SIZE_OF_NAND - (meminuse + memdead)); } #endif else { return(CMD_PARAM_ERROR); } return(CMD_SUCCESS); }
void tfslog(int action, char *string) { #if TFS_CHANGELOG_SIZE static char *tfslogaction[] = { "ADD", "DEL", "IPM", " ON", "OFF" }; extern void *setTmpMaxUsrLvl(); static char buf[TFS_CHANGELOG_SIZE]; TFILE *tfp; int (*fptr)(); char *eol, *eob, *logaction, tbuf[32]; int newfsize, fsize, lsize, tfd, err, len, tbuflen; switch(action) { case TFSLOG_ADD: /* Return here if logging is off, */ case TFSLOG_DEL: /* or this tfslog() call is on the */ case TFSLOG_IPM: /* TFS_CHANGELOG_FILE itself. */ if (!tfsLogging || !strcmp(string,TFS_CHANGELOG_FILE)) return; break; case TFSLOG_ON: if (tfsLogging == 1) return; tfsLogging = 1; break; case TFSLOG_OFF: if (tfsLogging == 0) return; tfsLogging = 0; break; } /* Force the getUsrLvl() function to return MAX: */ fptr = (int(*)())setTmpMaxUsrLvl(); logaction = tfslogaction[action]; tfp = tfsstat(TFS_CHANGELOG_FILE); tfsGetAtime(0,tbuf,sizeof(tbuf)); tbuflen = strlen(tbuf); if (tfp) { tfd = tfsopen(TFS_CHANGELOG_FILE,TFS_RDONLY,0); fsize = tfsread(tfd,buf,TFS_CHANGELOG_SIZE); tfsclose(tfd,0); newfsize = (fsize+strlen(logaction)+strlen(string)+3); if (tbuflen) newfsize += tbuflen + 3; eob = buf + fsize; /* If newfsize is greater than the maximum size the file is * allowed to grow, then keep removing the first line * (oldest entry) until new size is within the limit... */ if (newfsize > TFS_CHANGELOG_SIZE) { lsize = 0; eol = buf; while ((newfsize-lsize) > TFS_CHANGELOG_SIZE) { while((*eol != '\r') && (*eol != '\n')) eol++; while((*eol == '\r') || (*eol == '\n')) eol++; lsize = eol-buf; } fsize -= lsize; newfsize -= lsize; eob -= lsize; memcpy(buf,eol,fsize); } if (tbuflen) sprintf(eob,"%s: %s @ %s\n",logaction,string,tbuf); else sprintf(eob,"%s: %s\n",logaction,string); err = _tfsunlink(TFS_CHANGELOG_FILE); if (err < 0) printf("%s: %s\n",TFS_CHANGELOG_FILE, (char *)tfsctrl(TFS_ERRMSG,err,0)); err = tfsadd(TFS_CHANGELOG_FILE,0,"u3",buf,newfsize); if (err < 0) printf("%s: %s\n",TFS_CHANGELOG_FILE, (char *)tfsctrl(TFS_ERRMSG,err,0)); } else { if (tbuflen) len = sprintf(buf,"%s: %s @ %s\n",logaction,string,tbuf); else len = sprintf(buf,"%s: %s\n",logaction,string); err = tfsadd(TFS_CHANGELOG_FILE,0,"u3",buf,len); if (err < 0) printf("%s: %s\n",TFS_CHANGELOG_FILE, (char *)tfsctrl(TFS_ERRMSG,err,0)); } /* Restore the original getUsrLvl() functionality: */ clrTmpMaxUsrLvl(fptr); #endif }
/* tfsopen(): * Open a file for reading or creation. If file is opened for writing, * then the caller must provide a RAM buffer pointer to be used for * the file storage until it is transferred to flash by tfsclose(). * Note that the "buf" pointer is only needed for opening a file for * creation or append (writing). * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsopen(char *file,long flagmode,char *buf) { register int i; int errno, retval; long fmode; TFILE *fp; struct tfsdat *slot; errno = TFS_OKAY; fmode = flagmode & (TFS_RDONLY | TFS_APPEND | TFS_CREATE | TFS_CREATERM); /* See if file exists... */ fp = tfsstat(file); /* If file exists, do a crc32 on the data. * If the file is in-place-modifiable, then the only legal flagmode * is TFS_RDONLY. Plus, in this case, the crc32 test is skipped. */ if (fp) { if (!((fmode == TFS_RDONLY) && (fp->flags & TFS_IPMOD))) { if (crc32((unsigned char *)TFS_BASE(fp),fp->filsize) != fp->filcrc) { retval = TFSERR_BADCRC; goto done; } } } /* This switch verifies... * - that the file exists if TFS_RDONLY or TFS_APPEND * - that the file does not exist if TFS_CREATE */ switch(fmode) { case TFS_RDONLY: /* Read existing file only, no change to file at all. */ if (!fp) { if (_tfsstat(file,0)) errno = TFSERR_LINKERROR; else errno = TFSERR_NOFILE; } else { if ((fp->flags & TFS_UNREAD) && (TFS_USRLVL(fp) > getUsrLvl())) errno = TFSERR_USERDENIED; } break; case TFS_APPEND: /* Append to the end of the current file. */ if (!fp) errno = TFSERR_NOFILE; else { if (TFS_USRLVL(fp) > getUsrLvl()) errno = TFSERR_USERDENIED; } break; case TFS_CREATERM: /* Create a new file, allow tfsadd() to remove */ fmode = TFS_CREATE; /* it if it exists. */ break; case TFS_CREATE: /* Create a new file, error if it exists. */ if (fp) errno = TFSERR_FILEEXISTS; break; case (TFS_APPEND|TFS_CREATE): /* If both mode bits are set, clear one */ if (fp) { /* based on the presence of the file. */ if (TFS_USRLVL(fp) > getUsrLvl()) errno = TFSERR_USERDENIED; fmode = TFS_APPEND; } else { fmode = TFS_CREATE; } break; default: errno = TFSERR_BADARG; break; } if (errno != TFS_OKAY) { retval = errno; goto done; } /* Find an empty slot... */ slot = tfsSlots; for (i=0;i<TFS_MAXOPEN;i++,slot++) { if (slot->offset == -1) break; } /* Populate the slot structure if a slot is found to be * available... */ if (i < TFS_MAXOPEN) { retval = i; slot->hwp = 0; slot->offset = 0; slot->flagmode = fmode; if (fmode & TFS_CREATE) { strncpy(slot->hdr.name,file,TFSNAMESIZE); slot->flagmode |= (flagmode & TFS_FLAGMASK); slot->base = (uchar *)buf; } else if (fmode & TFS_APPEND) { memcpy((char *)&slot->hdr,(char *)fp,sizeof(struct tfshdr)); if (s_memcpy((char *)buf,(char *)(TFS_BASE(fp)), fp->filsize,0,0) != 0) { retval = TFSERR_MEMFAIL; goto done; } slot->flagmode = fp->flags; slot->flagmode |= TFS_APPEND; slot->base = (uchar *)buf; slot->hwp = fp->filsize; slot->offset = fp->filsize; } else { slot->base = (uchar *) (TFS_BASE(fp)); memcpy((char *)&slot->hdr,(char *)fp,sizeof(struct tfshdr)); } } else { retval = TFSERR_NOSLOT; } done: if (tfsTrace > 0) printf("tfsopen(%s,0x%lx,0x%lx)=%d\n",file,flagmode,(ulong)buf,retval); return(retval); }