/* Get minisection sector nr per given mini sector offset */ int get_minisection_sector(int sector) { int *fat=NULL; int sectn=0; int sectb=0; int nextsector; nextsector = minisectionstart; fat = get_fat(nextsector); sectn=0; while (sector>sectn) { sectn++; sectb++; if (sectb>=(sectorsize/64)) { sectb=0; /* Get fat entry for next table; */ fat = get_fat(nextsector); nextsector = fat[nextsector]; } } return nextsector; }
void read_fat(DOS_FS *fs) { int eff_size; unsigned long i; void *first,*second,*use; int first_ok,second_ok; eff_size = ((fs->clusters+2)*fs->fat_bits+7)/8; first = alloc(eff_size); second = alloc(eff_size); fs_read(fs->fat_start,eff_size,first); fs_read(fs->fat_start+fs->fat_size,eff_size,second); use = first; if (memcmp(first,second,eff_size) != 0) { FAT_ENTRY first_media, second_media; get_fat(&first_media,first,0,fs); get_fat(&second_media,second,0,fs); first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); if (first_ok && !second_ok) { printf("FATs differ - using first FAT.\n"); fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); } if (!first_ok && second_ok) { printf("FATs differ - using second FAT.\n"); fs_write(fs->fat_start,eff_size,use = second); } if (first_ok && second_ok) { if (interactive) { printf("FATs differ but appear to be intact. Use which FAT ?\n" "1) Use first FAT\n2) Use second FAT\n"); if (get_key("12","?") == '1') fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); else fs_write(fs->fat_start,eff_size,use = second); } else { printf("FATs differ but appear to be intact. Using first " "FAT.\n"); fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); } } if (!first_ok && !second_ok) { printf("Both FATs appear to be corrupt. Giving up.\n"); exit(1); } } fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2)); for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],use,i,fs); for (i = 2; i < fs->clusters+2; i++) if (fs->fat[i].value >= fs->clusters+2 && (fs->fat[i].value < FAT_MIN_BAD(fs))) { printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", i-2,fs->fat[i].value,fs->clusters+2-1); set_fat(fs,i,-1); } free(first); free(second); }
DWORD allocate_contiguous_clusters ( /* Returns the first sector in LBA (0:error or not contiguous) */ FIL* fp, /* Pointer to the open file object */ DWORD len /* Number of bytes to allocate */ ) { DWORD csz, tcl, ncl, ccl, cl; if (f_lseek(fp, 0) || !len) /* Check if the given parameters are valid */ return 0; csz = 512UL * fp->fs->csize; /* Cluster size in unit of byte (assuming 512 bytes/sector) */ tcl = (len + csz - 1) / csz; /* Total number of clusters required */ len = tcl * csz; /* Round-up file size to the cluster boundary */ /* Check if the existing cluster chain is contiguous */ if (len == fp->fsize) { ncl = 0; ccl = fp->sclust; do { cl = get_fat(fp->fs, ccl); /* Get the cluster status */ if (cl + 1 < 3) return 0; /* Hard error? */ if (cl != ccl + 1 && cl < fp->fs->n_fatent) break; /* Not contiguous? */ ccl = cl; } while (++ncl < tcl); if (ncl == tcl) /* Is the file contiguous? */ return clust2sect(fp->fs, fp->sclust); /* File is contiguous. Return the start sector */ } /* File is not contiguous */ #if _FS_READONLY return 0; /* Exit if in read-only cfg. */ #else if (!(fp->flag & FA_WRITE)) return 0; /* Exit if the file object is for read-only */ if (f_truncate(fp)) return 0; /* Remove the non-contiguous chain */ /* Find a free contiguous area */ ccl = cl = 2; ncl = 0; do { if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */ if (get_fat(fp->fs, cl)) { /* Encounterd a cluster in use */ do { /* Skip the block of used clusters */ cl++; if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */ } while (get_fat(fp->fs, cl)); ccl = cl; ncl = 0; } cl++; ncl++; } while (ncl < tcl); /* Create a contiguous cluster chain */ fp->fs->last_clust = ccl - 1; if (f_lseek(fp, len)) return 0; return clust2sect(fp->fs, fp->sclust); /* Return file start sector */ #endif }
static int32_t inter_fs_read( uint16_t blk, uint32_t offset, uint8_t *pbuf, uint32_t size ) { int32_t rtn; uint32_t i, cnt, c_size; rtn = DNAND_NO_ERROR; if( size == 0 ) { return(rtn); } cnt = (offset+size+DNAND_FS_BLK_SIZE-1)/DNAND_FS_BLK_SIZE; for( i=0; i<cnt; i++ ) { if( offset >= DNAND_FS_BLK_SIZE ) { offset -= DNAND_FS_BLK_SIZE; blk = get_fat( blk ); continue; } if( (offset+size) >= DNAND_FS_BLK_SIZE ) { c_size = DNAND_FS_BLK_SIZE-offset; } else { c_size = size; } if( (blk < DNAND_FS_BLK_DATA_ST)||(blk >= DNAND_FS_BLK_NUM) ) { rtn = DNAND_EOF_ERROR; break; } else { rtn = dnand_blk_read( blk, offset, pbuf, c_size ); if( rtn != DNAND_NO_ERROR ) { break; } } offset = 0; size -= c_size; pbuf += c_size; blk = get_fat( blk ); } return(rtn); }
FRESULT pf_write ( const void* buff, /* Pointer to the data to be written */ UINT btw, /* Number of bytes to write (0:Finalize the current write operation) */ UINT* bw /* Pointer to number of bytes written */ ) { CLUST clst; DWORD sect, remain; const BYTE *p = buff; BYTE cs; UINT wcnt; FATFS *fs = FatFs; *bw = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; if (!btw) { /* Finalize request */ if ((fs->flag & FA__WIP) && disk_writep(0, 0)) ABORT(FR_DISK_ERR); fs->flag &= ~FA__WIP; return FR_OK; } else { /* Write data request */ if (!(fs->flag & FA__WIP)) /* Round-down fptr to the sector boundary */ fs->fptr &= 0xFFFFFE00; } remain = fs->fsize - fs->fptr; if (btw > remain) btw = (UINT)remain; /* Truncate btw by remaining bytes */ while (btw) { /* Repeat until all data transferred */ if ((UINT)fs->fptr % 512 == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ if (fs->fptr == 0) /* On the top of the file? */ clst = fs->org_clust; else clst = get_fat(fs->curr_clust); if (clst <= 1) ABORT(FR_DISK_ERR); fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) ABORT(FR_DISK_ERR); fs->dsect = sect + cs; if (disk_writep(0, fs->dsect)) ABORT(FR_DISK_ERR); /* Initiate a sector write operation */ fs->flag |= FA__WIP; } wcnt = 512 - (UINT)fs->fptr % 512; /* Number of bytes to write to the sector */ if (wcnt > btw) wcnt = btw; if (disk_writep(p, wcnt)) ABORT(FR_DISK_ERR); /* Send data to the sector */ fs->fptr += wcnt; p += wcnt; /* Update pointers and counters */ btw -= wcnt; *bw += wcnt; if ((UINT)fs->fptr % 512 == 0) { if (disk_writep(0, 0)) ABORT(FR_DISK_ERR); /* Finalize the currtent secter write operation */ fs->flag &= ~FA__WIP; } } return FR_OK; }
static FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table */ DIR *dj /* Pointer to directory object */ ) { CLUST clst; u16 i; FATFS *fs = FatFs; i = dj->index + 1; if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ return FR_NO_FILE; if (!(i & (16-1))) { /* Sector changed? */ dj->sect++; /* Next sector */ if (dj->clust == 0) { /* Static table */ if (i >= fs->n_rootdir) /* Report EOT when end of table */ return FR_NO_FILE; } else { /* Dynamic table */ if (((i / 16) & (fs->csize-1)) == 0) { /* Cluster changed? */ clst = get_fat(dj->clust); /* Get next cluster */ if (clst <= 1) return FR_DISK_ERR; if (clst >= fs->max_clust) /* When it reached end of dynamic table */ return FR_NO_FILE; /* Report EOT */ dj->clust = clst; /* Initialize data for new cluster */ dj->sect = clust2sect(clst); } } } dj->index = i; return FR_OK; }
FRESULT pf_write ( const void* buff, /* Pointer to the data to be written */ u16 btw, /* Number of bytes to write (0:Finalize the current write operation) */ u16* bw /* Pointer to number of bytes written */ ) { CLUST clst; u32 sect, remain; const u8 *p = buff; u16 wcnt; FATFS *fs = FatFs; *bw = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; if (!btw) { /* Finalize request */ if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort; fs->flag &= ~FA__WIP; return FR_OK; } else { /* Write data request */ if (!(fs->flag & FA__WIP)) /* Round down fptr to the sector boundary */ fs->fptr &= 0xFFFFFE00; } remain = fs->fsize - fs->fptr; if (btw > remain) btw = (u16)remain; /* Truncate btw by remaining bytes */ while (btw) { /* Repeat until all data transferred */ if (((u16)fs->fptr % 512) == 0) { /* On the sector boundary? */ if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) goto fw_abort; fs->curr_clust = clst; /* Update current cluster */ fs->csect = 0; /* Reset sector offset in the cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) goto fw_abort; fs->dsect = sect + fs->csect++; if (disk_writep(0, fs->dsect)) goto fw_abort; /* Initiate a sector write operation */ fs->flag |= FA__WIP; } wcnt = 512 - ((u16)fs->fptr % 512); /* Number of bytes to write to the sector */ if (wcnt > btw) wcnt = btw; if (disk_writep(p, wcnt)) goto fw_abort; /* Send data to the sector */ fs->fptr += wcnt; p += wcnt; /* Update pointers and counters */ btw -= wcnt; *bw += wcnt; if (((u16)fs->fptr % 512) == 0) { if (disk_writep(0, 0)) goto fw_abort; /* Finalize the currtent secter write operation */ fs->flag &= ~FA__WIP; } } return FR_OK; fw_abort: fs->flag = 0; return FR_DISK_ERR; }
FRESULT pf_read ( void* dest, /* Pointer to the destination object */ WORD btr, /* Number of bytes to read (bit15:destination) */ WORD* br /* Pointer to number of bytes read */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; WORD rcnt; BYTE *rbuff = dest; FATFS *fs = FatFs; *br = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_READ)) return FR_INVALID_OBJECT; remain = fs->fsize - fs->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fs->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) { fs->flag = 0; return FR_DISK_ERR; } fs->curr_clust = clst; /* Update current cluster */ fs->csect = 0; /* Reset sector offset in the cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) { fs->flag = 0; return FR_DISK_ERR; } sect += fs->csect; fs->dsect = sect; fs->csect++; /* Next sector address in the cluster */ } rcnt = 512 - ((WORD)fs->fptr % 512); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; if (fs->flag & FA_STREAM) { dr = disk_readp(dest, fs->dsect, (WORD)(fs->fptr % 512), (WORD)(rcnt | 0x8000)); } else { dr = disk_readp(rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); } if (dr) { fs->flag = 0; return (dr == RES_STRERR) ? FR_STREAM_ERR : FR_DISK_ERR; } } return FR_OK; }
FRESULT pf_write ( const void* buff, /* Pointer to the data to be written */ WORD btw, /* Number of bytes to write (0:Finalize the current write operation) */ WORD* bw /* Pointer to number of bytes written */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; WORD rcnt; BYTE cs; const BYTE *rbuff = buff; FATFS *fs = FatFs; *bw = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; remain = fs->fsize - fs->fptr; if (btw > remain) btw = (WORD)remain; /* Truncate btr by remaining bytes */ while (btw) { /* Repeat until all data transferred */ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) goto fr_abort; fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) goto fr_abort; fs->dsect = sect + cs; } rcnt = (WORD)(512 - (fs->fptr % 512)); /* Get partial sector data from sector buffer */ if (rcnt > btw) rcnt = btw; dr = disk_writep(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); if (dr) goto fr_abort; fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ btw -= rcnt; *bw += rcnt; } return FR_OK; fr_abort: fs->flag = 0; return FR_DISK_ERR; }
FRESULT pf_read ( void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ WORD btr, /* Number of bytes to read */ WORD* br /* Pointer to number of bytes read */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; WORD rcnt; BYTE cs, *rbuff = buff; FATFS *fs = FatFs; *br = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; //led_sign_ff(5); remain = fs->fsize - fs->fptr; if (btr > remain) btr = (WORD)remain; /* Truncate btr by remaining bytes */ while (btr) { /* Repeat until all data transferred */ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) goto fr_abort; fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) goto fr_abort; fs->dsect = sect + cs; } rcnt = (WORD)(512 - (fs->fptr % 512)); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); if (dr) goto fr_abort; fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ btr -= rcnt; *br += rcnt; } return FR_OK; fr_abort: fs->flag = 0; return FR_DISK_ERR; }
FRESULT pf_lseek ( DWORD ofs /* File pointer from top of file */ ) { CLUST clst; DWORD bcs, sect, ifptr; FATFS *fs = FatFs; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; if (ofs > fs->fsize) ofs = fs->fsize; /* Clip offset with the file size */ ifptr = fs->fptr; fs->fptr = 0; if (ofs > 0) { bcs = (DWORD)fs->csize * 512; /* Cluster size (byte) */ if (ifptr > 0 && (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ fs->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ ofs -= fs->fptr; clst = fs->curr_clust; } else { /* When seek to back cluster, */ clst = fs->org_clust; /* start from the first cluster */ fs->curr_clust = clst; } while (ofs > bcs) { /* Cluster following loop */ clst = get_fat(clst); /* Follow cluster chain */ if (clst <= 1 || clst >= fs->max_clust) goto fe_abort; fs->curr_clust = clst; fs->fptr += bcs; ofs -= bcs; } fs->fptr += ofs; sect = clust2sect(clst); /* Current sector */ if (!sect) goto fe_abort; fs->csect = (BYTE)(ofs / 512); /* Sector offset in the cluster */ if (ofs % 512) fs->dsect = sect + fs->csect++; } return FR_OK; fe_abort: fs->flag = 0; return FR_DISK_ERR; }
FRESULT pf_read ( FATFS* fs, /* Filesystem descriptor */ void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ UINT btr, /* Number of bytes to read */ UINT* br /* Pointer to number of bytes read */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; UINT rcnt; BYTE cs, *rbuff = buff; *br = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; remain = fs->fsize - fs->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ while (btr) { /* Repeat until all data transferred */ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ if (fs->fptr == 0) /* On the top of the file? */ clst = fs->org_clust; else clst = get_fat(fs, fs->curr_clust); if (clst <= 1) ABORT(FR_DISK_ERR); fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs, fs->curr_clust); /* Get current sector */ if (!sect) ABORT(FR_DISK_ERR); fs->dsect = sect + cs; } rcnt = 512 - (UINT)fs->fptr % 512; /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; dr = disk_readp(&fs->disk, !buff ? 0 : rbuff, fs->dsect, (UINT)fs->fptr % 512, rcnt); if (dr) ABORT(FR_DISK_ERR); fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ btr -= rcnt; *br += rcnt; } return FR_OK; }
/* Read stream from table - callee needs to free memory */ char* read_stream(int start, int size) { char *lbuf=malloc(4); int lsize=0; int *fat=NULL; // current minitab int sector; sector=start; while ((lsize)<size) { lbuf = realloc(lbuf,lsize+sectorsize); memcpy(lbuf + lsize,get_buf_offset(sector), sectorsize); lsize += sectorsize; fat = get_fat(sector); sector = fat[sector]; } return lbuf; }
/* Get mini FAT table for a given minisector */ int* get_mtab(int sector) { int *fat=NULL; char *mtab=NULL; int mtabn=0; int nextsector; nextsector = minifatsector; while (mtabn<sector) { mtabn++; if (sector>((mtabn*sectorsize)/4)) { /* Get fat entry for next table; */ fat = get_fat(nextsector); nextsector = fat[nextsector]; mtabn++; } } mtab=get_buf_offset(nextsector); return (int*)mtab; }
/** * Build a bookkeeping structure from the partition's FAT table. * If the partition has multiple FATs and they don't agree, try to pick a winner, * and queue a command to overwrite the loser. * One error that is fixed here is a cluster that links to something out of range. * * @param[inout] fs Information about the filesystem */ void read_fat(DOS_FS * fs) { int eff_size; unsigned long i; void *first, *second = NULL; int first_ok, second_ok; unsigned long total_num_clusters; /* Clean up from previous pass */ if (fs->fat) free(fs->fat); if (fs->cluster_owner) free(fs->cluster_owner); fs->fat = NULL; fs->cluster_owner = NULL; total_num_clusters = fs->clusters + 2UL; eff_size = (total_num_clusters * fs->fat_bits + 7) / 8ULL; first = alloc(eff_size); fs_read(fs->fat_start, eff_size, first); if (fs->nfats > 1) { second = alloc(eff_size); fs_read(fs->fat_start + fs->fat_size, eff_size, second); } if (second && memcmp(first, second, eff_size) != 0) { FAT_ENTRY first_media, second_media; get_fat(&first_media, first, 0, fs); get_fat(&second_media, second, 0, fs); first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); if (first_ok && !second_ok) { printf("FATs differ - using first FAT.\n"); fs_write(fs->fat_start + fs->fat_size, eff_size, first); } if (!first_ok && second_ok) { printf("FATs differ - using second FAT.\n"); fs_write(fs->fat_start, eff_size, second); memcpy(first, second, eff_size); } if (first_ok && second_ok) { if (interactive) { printf("FATs differ but appear to be intact. Use which FAT ?\n" "1) Use first FAT\n2) Use second FAT\n"); if (get_key("12", "?") == '1') { fs_write(fs->fat_start + fs->fat_size, eff_size, first); } else { fs_write(fs->fat_start, eff_size, second); memcpy(first, second, eff_size); } } else { printf("FATs differ but appear to be intact. Using first " "FAT.\n"); fs_write(fs->fat_start + fs->fat_size, eff_size, first); } } if (!first_ok && !second_ok) { printf("Both FATs appear to be corrupt. Giving up.\n"); exit(1); } } if (second) { free(second); } fs->fat = (unsigned char *)first; fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *)); memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *))); /* Truncate any cluster chains that link to something out of range */ for (i = 2; i < fs->clusters + 2; i++) { FAT_ENTRY curEntry; get_fat(&curEntry, fs->fat, i, fs); if (curEntry.value == 1) { printf("Cluster %ld out of range (1). Setting to EOF.\n", i - 2); set_fat(fs, i, -1); } if (curEntry.value >= fs->clusters + 2 && (curEntry.value < FAT_MIN_BAD(fs))) { printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", i - 2, curEntry.value, fs->clusters + 2 - 1); set_fat(fs, i, -1); } } }
int main (int argc, char* argv[]) { UINT csz; HANDLE wh; DWORD wb, szvol; int ai = 1, truncation = 0; const char *outfile; /* Initialize parameters */ if (argc >= 2 && *argv[ai] == '-') { if (!strcmp(argv[ai], "-t")) { truncation = 1; ai++; argc--; } else { argc = 0; } } if (argc < 3) { printf("usage: mkfatimg [-t] <source node> <output file> <volume size> [<cluster size>]\n" " -t: Truncate unused area for read only volume.\n" " <source node>: Source node\n" " <output file>: FAT volume image file\n" " <volume size>: Size of temporary volume size in unit of KiB\n" " <cluster size>: Size of cluster in unit of byte (default:512)\n" ); return 1; } strcpy(SrcPath, argv[ai++]); outfile = argv[ai++]; RamDiskSize = atoi(argv[ai++]) * 2; csz = (argc >= 5) ? atoi(argv[ai++]) : 512; /* Create an FAT volume */ f_mount(&FatFs, "", 0); if (f_mkfs("", 1, csz)) { printf("Failed to create FAT volume. Adjust volume size or cluster size.\n"); return 2; } /* Copy directory tree onto the FAT volume */ if (!maketree()) return 3; if (!Files) { printf("No file in the source directory."); return 3; } szvol = LD_WORD(RamDisk + BPB_TotSec16); if (!szvol) szvol = LD_DWORD(RamDisk + BPB_TotSec32); if (truncation) { DWORD ent, nent; DWORD szf, szfp, edf, edfp; DWORD szd, szdp, edd, eddp; /* Truncate unused root directory entries */ if (FatFs.fs_type != FS_FAT32) { printf("\nTruncating unused root directory area..."); for (nent = ent = 0; ent < FatFs.n_rootdir; ent++) { if (RamDisk[FatFs.dirbase * 512 + ent * 32]) nent = ent + 1; } szd = (nent + 15) / 16; szdp = FatFs.n_rootdir / 16; if (szd < szdp) { edd = FatFs.dirbase + szd; eddp = FatFs.database; MoveMemory(RamDisk + (edd * 512), RamDisk + (eddp * 512), (szvol - eddp) * 512); szvol -= szdp - szd; FatFs.database -= szdp - szd; ST_WORD(RamDisk + BPB_RootEntCnt, szd * 16); } } /* Truncate unused data area and FAT */ printf("\nTruncating unused data area..."); for (nent = ent = 2; ent < FatFs.n_fatent; ent++) { if (get_fat(&FatFs, ent)) nent = ent + 1; } switch (FatFs.fs_type) { case FS_FAT12: szf = (nent * 3 / 2 + (nent & 1) + 511) / 512; break; case FS_FAT16: szf = (nent * 2 + 511) / 512; if (nent - 2 < MIN_FAT16) nent = 0; break; default: szf = (nent * 4 + 511) / 512; if (nent - 2 < MIN_FAT32) nent = 0; break; } if (!nent) { printf("different FAT sub-type is needed. Adjust volume size or cluster size.\n"); return 3; } szfp = LD_WORD(RamDisk + BPB_FATSz16) * RamDisk[BPB_NumFATs]; if (!szfp) szfp = LD_DWORD(RamDisk + BPB_FATSz32) * RamDisk[BPB_NumFATs]; edf = FatFs.fatbase + szf; edfp = (FatFs.fs_type == FS_FAT32) ? FatFs.database : FatFs.dirbase; MoveMemory(RamDisk + (edf * 512), RamDisk + (edfp * 512), (szvol - edfp) * 512); szvol -= (szfp - szf) + FatFs.csize * (FatFs.n_fatent - nent); if (FatFs.fs_type == FS_FAT32) { ST_DWORD(RamDisk + BPB_FATSz32, szf); } else { ST_WORD(RamDisk + BPB_FATSz16, szf); } RamDisk[BPB_NumFATs] = 1; if (szvol < 0x10000) { ST_WORD(RamDisk + BPB_TotSec16, szvol); ST_DWORD(RamDisk + BPB_TotSec32, 0); } else { ST_WORD(RamDisk + BPB_TotSec16, 0); ST_DWORD(RamDisk + BPB_TotSec32, szvol); } } /* Output the FAT volume to the file */ printf("\nWriting output file..."); wh = CreateFile(outfile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if (wh == INVALID_HANDLE_VALUE) { printf("Failed to create output file.\n"); return 4; } szvol *= 512; WriteFile(wh, RamDisk, szvol, &wb, 0); CloseHandle(wh); if (szvol != wb) { DeleteFile(argv[2]); printf("Failed to write output file.\n"); return 4; } printf("\n%u files and %u directories in a %u bytes of FAT volume.\n", Files, Dirs, szvol); return 0; }
static int32_t inter_fs_write( uint32_t cid, uint16_t blk, uint32_t offset, uint8_t *pbuf, uint32_t size ) { int32_t rtn; uint32_t i, cnt, c_size; uint16_t a_blk, prevblk, nextblk; uint8_t *p_kbuf; if( size == 0 ) { return(DNAND_NO_ERROR); } if( cid >= DNAND_FS_CLID_NUM ) { return(DNAND_PARAM_ERROR); } if( ( (blk<DNAND_FS_BLK_DATA_ST)||(blk>=DNAND_FS_BLK_NUM) )&& (blk != DNAND_FS_BLK_UNUSE) ) { return(DNAND_MNG_ERROR); } rtn = DNAND_NO_ERROR; cnt = (offset+size+DNAND_FS_BLK_SIZE-1)/DNAND_FS_BLK_SIZE; a_blk = alloc_fat(); if( a_blk >= DNAND_FS_BLK_NUM ) { return(DNAND_NOSPC_ERROR); } prevblk = DNAND_FS_BLK_UNUSE; p_kbuf = (uint8_t*)kmalloc(DNAND_FS_BLK_SIZE, GFP_KERNEL); if( p_kbuf == NULL ) { return(DNAND_NOMEM_ERROR); } for( i=0; i<cnt; i++ ) { if( offset >= DNAND_FS_BLK_SIZE ) { if( (blk>=DNAND_FS_BLK_DATA_ST)&&(blk<DNAND_FS_BLK_NUM) ) { offset -= DNAND_FS_BLK_SIZE; prevblk = blk; blk = get_fat( prevblk ); continue; } memset(p_kbuf, 0x00, DNAND_FS_BLK_SIZE); rtn = dnand_blk_write( a_blk, 0, p_kbuf, DNAND_FS_BLK_SIZE ); offset -= DNAND_FS_BLK_SIZE; } else { if( (offset+size) >= DNAND_FS_BLK_SIZE ) { c_size = DNAND_FS_BLK_SIZE-offset; } else { c_size = size; } if( c_size < DNAND_FS_BLK_SIZE ) { if( (blk>=DNAND_FS_BLK_DATA_ST)&&(blk<DNAND_FS_BLK_NUM) ) { rtn = dnand_blk_read( blk, 0, p_kbuf, DNAND_FS_BLK_SIZE ); if( rtn == DNAND_NO_ERROR ) { memcpy( p_kbuf+offset, pbuf, c_size ); rtn = dnand_blk_write( a_blk, 0, p_kbuf, DNAND_FS_BLK_SIZE ); } } else { memset( p_kbuf, 0x00, DNAND_FS_BLK_SIZE ); memcpy( p_kbuf+offset, pbuf, c_size ); rtn = dnand_blk_write( a_blk, 0, p_kbuf, DNAND_FS_BLK_SIZE ); } } else { rtn = dnand_blk_write( a_blk, 0, pbuf, c_size ); } offset = 0; size -= c_size; pbuf += c_size; } if( rtn != DNAND_NO_ERROR ) { break; } nextblk = get_fat( blk ); blk = nextblk; if( ((nextblk >= DNAND_FS_BLK_DATA_ST)&&(nextblk < DNAND_FS_BLK_NUM)) || (nextblk == DNAND_FS_BLK_EOF) ) { set_fat( a_blk, nextblk ); } else { set_fat( a_blk, DNAND_FS_BLK_EOF ); } if( (prevblk >= DNAND_FS_BLK_DATA_ST)&&(prevblk < DNAND_FS_BLK_NUM) ) { set_fat( prevblk, a_blk ); } if( i == 0 ) { set_clid( cid, a_blk ); } prevblk = a_blk; if( (i+1) < cnt ) { a_blk = alloc_fat(); if( a_blk >= DNAND_FS_BLK_NUM ) { rtn = DNAND_NOSPC_ERROR; break; } } } kfree(p_kbuf); return(rtn); }