/* _tfsclean(): * This is an alternative to the complicated defragmentation above. * It simply scans through the file list and copies all valid files * to RAM; then flash is erased and the RAM is copied back to flash. * <<< WARNING >>> * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY * ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE. */ int _tfsclean(TDEV *tdp, int notused, int verbose) { TFILE *tfp; uchar *tbuf; ulong appramstart; int dtot, nfadd, len, err, chkstat; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); appramstart = getAppRamStart(); /* 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("Reconstructing device %s with %d dead file%s removed...\n", tdp->prefix, dtot,dtot>1 ? "s":""); tbuf = (char *)appramstart; tfp = (TFILE *)(tdp->start); 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 (s_memcpy(tbuf,(uchar *)tfp,len,0,0) != 0) return(TFSERR_MEMFAIL); ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; tbuf += len; } tfp = nextfp(tfp,tdp); } /* Erase the flash device: */ err = _tfsinit(tdp); if (err != TFS_OKAY) return(err); /* Copy data placed in RAM back to flash: */ err = AppFlashWrite((ulong *)(tdp->start),(ulong *)appramstart, (tbuf-(uchar*)appramstart)); if (err < 0) return(TFSERR_FLASHFAILURE); /* All defragmentation is done, so verify sanity of files... */ chkstat = tfscheck(tdp,verbose); return(chkstat); }
/* _tfsclean(): * This is an alternative to the complicated defragmentation above. * It simply scans through the file list and copies all valid files * to RAM; then flash is erased and the RAM is copied back to flash. * <<< WARNING >>> * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY * ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE. */ int _tfsclean(TDEV *tdp, int notused, int verbose) { ulong appramstart; TFILE *tfp, *lasttfp; uchar *tbuf, *cp1, *cp2; int dtot, nfadd, len, err, chkstat; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); appramstart = getAppRamStart(); /* 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; lasttfp = tfp = (TFILE *)(tdp->start); 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 (s_memcpy((char *)tbuf,(char *)tfp,len,0,0) != 0) return(TFSERR_MEMFAIL); ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; tbuf += len; } lasttfp = tfp; 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); } } #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 { #if INCLUDE_FLASH err = AppFlashWrite((uchar *)(tdp->start),(uchar *)appramstart, (tbuf-(uchar*)appramstart)); if (err < 0) #endif return(TFSERR_FLASHFAILURE); } /* All defragmentation is done, so verify sanity of files... */ chkstat = tfscheck(tdp,verbose); return(chkstat); }
void BoardInfoInit(void) { short len; ushort crc; struct boardinfo *bip; int maxpromptsize, erased; struct boardinfoverify *bipv; uchar buf[BOARDINFO_BUFMAX]; char c, snum[8], prfmt[16], *prefill; sprintf(snum,"%d",BOARDINFO_SECTOR); /* Step through each bip entry and see if the data area is either * empty or the crc16 passed. If either is true, then allow * If every entry in the board-information area is either empty * or the crc test passes, we can just return... */ erased = 0; maxpromptsize = 0; boardinfo_error = 0; bip = boardinfotbl; while((bip->array) && (!boardinfo_error)) { BINFOPRINT(("Boardinfo item: %s (%s)",bip->varname,bip->prompt)); if(bip->array[0] != 0xff) { BINFOPRINT((" not")); bipv = (struct boardinfoverify *)&bip->array[bip->size-BIVSIZE]; /* If len and crc are set, then use those fields to sanity * check the data... */ if((bipv->len != 0xffff) && (bipv->crc16 != 0xffff)) { if((bipv->len > bip->size) || (xcrc16(bip->array,bipv->len) != bipv->crc16)) { boardinfo_error = 1; } } } else { erased++; } BINFOPRINT((" erased\n")); /* Gather data to determine the largest prompt... */ len = strlen(bip->prompt); if(len > maxpromptsize) { maxpromptsize = len; } bip++; } /* If there was no error, and the board info area is not erased, * we return here assuming the data is valid. */ if((boardinfo_error == 0) && (erased == 0)) { sectorProtect(snum,1); return; } /* If there was some kind of error reading any of the fields in the * board-info area, then either return or clear the error and interact * with the user to re-load the data... */ if(boardinfo_error != 0) { #ifdef BOARDINFO_REENTER_ON_ERROR printf("\nError reading board-info data, re-enter data..."); boardinfo_error = 0; #else printf("\nError reading board-info data in sector %d.\n", BOARDINFO_SECTOR); return; #endif } sprintf(prfmt,"%%%ds : ",maxpromptsize); printf("%s: board information field initialization...\n",PLATFORM_NAME); /* Un-protect the sector used for board information... */ sectorProtect(snum,0); do { /* Erase the sector used for board information... */ if(AppFlashErase(BOARDINFO_SECTOR) < 0) { boardinfo_error = 1; break; } /* Step through each entry in the boardinfo table and query * the user for input to be stored... */ bip = boardinfotbl; while(bip->array) { bipv = (struct boardinfoverify *)&bip->array[bip->size-BIVSIZE]; if(bip->def) { prefill = bip->def; } else { prefill = 0; } printf(prfmt,bip->prompt); len = 0; if(getline_p((char *)buf,bip->size-BIVSIZE,0,prefill) != 0) { len = strlen(buf)+1; if(AppFlashWrite(bip->array,buf,len) < 0) { boardinfo_error = 1; break; } crc = xcrc16(buf,len); } if(len) { if(AppFlashWrite((uchar *)(&bipv->len), (uchar *)&len,sizeof(len)) < 0) { boardinfo_error = 1; break; } if(AppFlashWrite((uchar *)(&bipv->crc16), (uchar *)&crc,sizeof(crc)) < 0) { boardinfo_error = 1; break; } } bip++; } if(boardinfo_error) { break; } bip = boardinfotbl; printf("\nNew system settings:\n\n"); while(bip->array) { #ifdef BOARDINFO_SHOW_RAW printMem(bip->array,bip->size,1); #else printf("%24s: %s\n",bip->prompt, bip->array[0] == 0xff ? "" : (char *)bip->array); #endif bip++; } putstr("\nHit ENTER to accept, any other key to re-enter..."); c = getchar(); putchar('\n'); } while((c != '\r') && (c != '\n')); sectorProtect(snum,1); }