Beispiel #1
0
/* 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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
/* 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;
}
Beispiel #14
0
/* 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;
}
Beispiel #15
0
/**
 * 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);
	}
    }
}
Beispiel #16
0
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;
}
Beispiel #17
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);
}