|
|
|
@ -22,6 +22,7 @@
|
|
|
|
|
#include "ff.h" /* Declarations of FatFs API */
|
|
|
|
|
#include "diskio.h" /* Declarations of device I/O functions */
|
|
|
|
|
|
|
|
|
|
DISKOPS *FfDiskOps; /* Global pointer to disk control ops */
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
@ -1077,10 +1078,10 @@ static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fs->wflag) { /* Is the disk access window dirty? */
|
|
|
|
|
if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write it back into the volume */
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write it back into the volume */
|
|
|
|
|
fs->wflag = 0; /* Clear window dirty flag */
|
|
|
|
|
if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */
|
|
|
|
|
if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */
|
|
|
|
|
if (fs->n_fats == 2) FfDiskOps->disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
res = FR_DISK_ERR;
|
|
|
|
@ -1104,7 +1105,7 @@ static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */
|
|
|
|
|
res = sync_window(fs); /* Flush the window */
|
|
|
|
|
#endif
|
|
|
|
|
if (res == FR_OK) { /* Fill sector window with new data */
|
|
|
|
|
if (disk_read(fs->pdrv, fs->win, sect, 1) != RES_OK) {
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, fs->win, sect, 1) != RES_OK) {
|
|
|
|
|
sect = (LBA_t)0 - 1; /* Invalidate window if read data is not valid */
|
|
|
|
|
res = FR_DISK_ERR;
|
|
|
|
|
}
|
|
|
|
@ -1141,11 +1142,11 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
|
|
|
|
|
st_dword(fs->win + FSI_Nxt_Free, fs->last_clst);
|
|
|
|
|
/* Write it into the FSInfo sector */
|
|
|
|
|
fs->winsect = fs->volbase + 1;
|
|
|
|
|
disk_write(fs->pdrv, fs->win, fs->winsect, 1);
|
|
|
|
|
FfDiskOps->disk_write(fs->pdrv, fs->win, fs->winsect, 1);
|
|
|
|
|
fs->fsi_flag = 0;
|
|
|
|
|
}
|
|
|
|
|
/* Make sure that no pending write process in the lower layer */
|
|
|
|
|
if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
@ -1494,7 +1495,7 @@ static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
|
|
|
|
#if FF_USE_TRIM
|
|
|
|
|
rt[0] = clst2sect(fs, scl); /* Start of data area to be freed */
|
|
|
|
|
rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area to be freed */
|
|
|
|
|
disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform storage device that the data in the block may be erased */
|
|
|
|
|
FfDiskOps->disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform storage device that the data in the block may be erased */
|
|
|
|
|
#endif
|
|
|
|
|
scl = ecl = nxt;
|
|
|
|
|
}
|
|
|
|
@ -1691,13 +1692,13 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */
|
|
|
|
|
if (szb > SS(fs)) { /* Buffer allocated? */
|
|
|
|
|
mem_set(ibuf, 0, szb);
|
|
|
|
|
szb /= SS(fs); /* Bytes -> Sectors */
|
|
|
|
|
for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */
|
|
|
|
|
for (n = 0; n < fs->csize && FfDiskOps->disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */
|
|
|
|
|
ff_memfree(ibuf);
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */
|
|
|
|
|
for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */
|
|
|
|
|
for (n = 0; n < fs->csize && FfDiskOps->disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */
|
|
|
|
|
}
|
|
|
|
|
return (n == fs->csize) ? FR_OK : FR_DISK_ERR;
|
|
|
|
|
}
|
|
|
|
@ -3397,7 +3398,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|
|
|
|
|
|
|
|
|
mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */
|
|
|
|
|
if (fs->fs_type != 0) { /* If the volume has been mounted */
|
|
|
|
|
stat = disk_status(fs->pdrv);
|
|
|
|
|
stat = FfDiskOps->disk_status(fs->pdrv);
|
|
|
|
|
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
|
|
|
|
|
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */
|
|
|
|
|
return FR_WRITE_PROTECTED;
|
|
|
|
@ -3411,7 +3412,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|
|
|
|
|
|
|
|
|
fs->fs_type = 0; /* Clear the filesystem object */
|
|
|
|
|
fs->pdrv = LD2PD(vol); /* Volume hosting physical drive */
|
|
|
|
|
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
|
|
|
|
|
stat = FfDiskOps->disk_initialize(fs->pdrv); /* Initialize the physical drive */
|
|
|
|
|
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
|
|
|
|
|
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
|
|
|
|
|
}
|
|
|
|
@ -3419,7 +3420,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|
|
|
|
return FR_WRITE_PROTECTED;
|
|
|
|
|
}
|
|
|
|
|
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
|
|
|
|
|
if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -3607,7 +3608,7 @@ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */
|
|
|
|
|
if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */
|
|
|
|
|
#if FF_FS_REENTRANT
|
|
|
|
|
if (lock_fs(obj->fs)) { /* Obtain the filesystem object */
|
|
|
|
|
if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
|
|
|
|
|
if (!(FfDiskOps->disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
|
|
|
|
|
res = FR_OK;
|
|
|
|
|
} else {
|
|
|
|
|
unlock_fs(obj->fs, FR_OK);
|
|
|
|
@ -3616,7 +3617,7 @@ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */
|
|
|
|
|
res = FR_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
|
|
|
|
|
if (!(FfDiskOps->disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
|
|
|
|
|
res = FR_OK;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
@ -3857,7 +3858,7 @@ FRESULT f_open (
|
|
|
|
|
} else {
|
|
|
|
|
fp->sect = sc + (DWORD)(ofs / SS(fs));
|
|
|
|
|
#if !FF_FS_TINY
|
|
|
|
|
if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3932,7 +3933,7 @@ FRESULT f_read (
|
|
|
|
|
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
|
|
|
|
|
cc = fs->csize - csect;
|
|
|
|
|
}
|
|
|
|
|
if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
|
|
|
|
|
#if FF_FS_TINY
|
|
|
|
|
if (fs->wflag && fs->winsect - sect < cc) {
|
|
|
|
@ -3951,11 +3952,11 @@ FRESULT f_read (
|
|
|
|
|
if (fp->sect != sect) { /* Load data sector if not in cache */
|
|
|
|
|
#if !FF_FS_READONLY
|
|
|
|
|
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
fp->sect = sect;
|
|
|
|
@ -4036,7 +4037,7 @@ FRESULT f_write (
|
|
|
|
|
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
|
|
|
|
|
#else
|
|
|
|
|
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
@ -4048,7 +4049,7 @@ FRESULT f_write (
|
|
|
|
|
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
|
|
|
|
|
cc = fs->csize - csect;
|
|
|
|
|
}
|
|
|
|
|
if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
#if FF_FS_MINIMIZE <= 2
|
|
|
|
|
#if FF_FS_TINY
|
|
|
|
|
if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
|
|
|
|
@ -4073,7 +4074,7 @@ FRESULT f_write (
|
|
|
|
|
#else
|
|
|
|
|
if (fp->sect != sect && /* Fill sector cache with file data */
|
|
|
|
|
fp->fptr < fp->obj.objsize &&
|
|
|
|
|
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
|
|
|
|
FfDiskOps->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
|
|
|
|
ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
@ -4118,7 +4119,7 @@ FRESULT f_sync (
|
|
|
|
|
if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */
|
|
|
|
|
#if !FF_FS_TINY
|
|
|
|
|
if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
@ -4462,11 +4463,11 @@ FRESULT f_lseek (
|
|
|
|
|
#if !FF_FS_TINY
|
|
|
|
|
#if !FF_FS_READONLY
|
|
|
|
|
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */
|
|
|
|
|
#endif
|
|
|
|
|
fp->sect = dsc;
|
|
|
|
|
}
|
|
|
|
@ -4542,11 +4543,11 @@ FRESULT f_lseek (
|
|
|
|
|
#if !FF_FS_TINY
|
|
|
|
|
#if !FF_FS_READONLY
|
|
|
|
|
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
|
|
|
|
#endif
|
|
|
|
|
fp->sect = nsect;
|
|
|
|
|
}
|
|
|
|
@ -4901,7 +4902,7 @@ FRESULT f_truncate (
|
|
|
|
|
fp->flag |= FA_MODIFIED;
|
|
|
|
|
#if !FF_FS_TINY
|
|
|
|
|
if (res == FR_OK && (fp->flag & FA_DIRTY)) {
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
|
|
|
|
|
res = FR_DISK_ERR;
|
|
|
|
|
} else {
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
@ -5654,11 +5655,11 @@ FRESULT f_forward (
|
|
|
|
|
if (fp->sect != sect) { /* Fill sector cache with file data */
|
|
|
|
|
#if !FF_FS_READONLY
|
|
|
|
|
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
|
|
|
|
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
fp->flag &= (BYTE)~FA_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
|
|
|
|
}
|
|
|
|
|
dbuf = fp->buf;
|
|
|
|
|
#endif
|
|
|
|
@ -5700,7 +5701,7 @@ static FRESULT create_partition (
|
|
|
|
|
BYTE *pte, hd, n_hd, sc, n_sc;
|
|
|
|
|
|
|
|
|
|
/* Get drive size */
|
|
|
|
|
if (disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
|
|
|
|
|
#if FF_LBA64
|
|
|
|
|
if (sz_drv >= FF_MIN_GPT) { /* Create partitions in GPT */
|
|
|
|
@ -5711,7 +5712,7 @@ static FRESULT create_partition (
|
|
|
|
|
static const BYTE gpt_mbr[16] = {0x00, 0x00, 0x02, 0x00, 0xEE, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
|
|
|
|
|
|
|
|
#if FF_MAX_SS != FF_MIN_SS
|
|
|
|
|
if (disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; /* Get sector size */
|
|
|
|
|
if (FfDiskOps->disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; /* Get sector size */
|
|
|
|
|
if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
|
|
|
|
|
#else
|
|
|
|
|
ss = FF_MAX_SS;
|
|
|
|
@ -5747,8 +5748,8 @@ static FRESULT create_partition (
|
|
|
|
|
}
|
|
|
|
|
if ((pi + 1) * SZ_GPTE % ss == 0) { /* Write the buffer if it is filled up */
|
|
|
|
|
for (i = 0; i < ss; bcc = crc32(bcc, buf[i++])) ; /* Calculate table check sum */
|
|
|
|
|
if (disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Primary table */
|
|
|
|
|
if (disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Secondary table */
|
|
|
|
|
if (FfDiskOps->disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Primary table */
|
|
|
|
|
if (FfDiskOps->disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Secondary table */
|
|
|
|
|
}
|
|
|
|
|
} while (++pi < GPT_ITEMS);
|
|
|
|
|
|
|
|
|
@ -5766,7 +5767,7 @@ static FRESULT create_partition (
|
|
|
|
|
rnd = make_rand(rnd, buf + GPTH_DskGuid, 16); /* Disk GUID */
|
|
|
|
|
for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */
|
|
|
|
|
st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */
|
|
|
|
|
if (disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
|
|
|
|
|
/* Create secondary GPT header */
|
|
|
|
|
st_qword(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */
|
|
|
|
@ -5775,13 +5776,13 @@ static FRESULT create_partition (
|
|
|
|
|
st_dword(buf + GPTH_Bcc, 0);
|
|
|
|
|
for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */
|
|
|
|
|
st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */
|
|
|
|
|
if (disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
|
|
|
|
|
/* Create protective MBR */
|
|
|
|
|
mem_set(buf, 0, ss);
|
|
|
|
|
mem_cpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */
|
|
|
|
|
st_word(buf + BS_55AA, 0xAA55);
|
|
|
|
|
if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
|
|
|
@ -5821,7 +5822,7 @@ static FRESULT create_partition (
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
st_word(buf + BS_55AA, 0xAA55); /* MBR signature */
|
|
|
|
|
if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */
|
|
|
|
|
if (FfDiskOps->disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FR_OK;
|
|
|
|
@ -5860,14 +5861,14 @@ FRESULT f_mkfs (
|
|
|
|
|
if (!opt) opt = &defopt; /* Use default parameter if it is not given */
|
|
|
|
|
|
|
|
|
|
/* Get physical drive status (sz_drv, sz_blk, ss) */
|
|
|
|
|
ds = disk_initialize(pdrv);
|
|
|
|
|
ds = FfDiskOps->disk_initialize(pdrv);
|
|
|
|
|
if (ds & STA_NOINIT) return FR_NOT_READY;
|
|
|
|
|
if (ds & STA_PROTECT) return FR_WRITE_PROTECTED;
|
|
|
|
|
sz_blk = opt->align;
|
|
|
|
|
if (sz_blk == 0 && disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1;
|
|
|
|
|
if (sz_blk == 0 && FfDiskOps->disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1;
|
|
|
|
|
if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1;
|
|
|
|
|
#if FF_MAX_SS != FF_MIN_SS
|
|
|
|
|
if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (FfDiskOps->disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
|
|
|
|
|
if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
|
|
|
|
|
#else
|
|
|
|
|
ss = FF_MAX_SS;
|
|
|
|
@ -5892,7 +5893,7 @@ FRESULT f_mkfs (
|
|
|
|
|
b_vol = sz_vol = 0;
|
|
|
|
|
if (FF_MULTI_PARTITION && ipart != 0) { /* Is the volume associated with any specific partition? */
|
|
|
|
|
/* Get partition location from the existing partition table */
|
|
|
|
|
if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */
|
|
|
|
|
if (FfDiskOps->disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */
|
|
|
|
|
if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */
|
|
|
|
|
#if FF_LBA64
|
|
|
|
|
if (buf[MBR_Table + PTE_System] == 0xEE) { /* GPT protective MBR? */
|
|
|
|
@ -5900,13 +5901,13 @@ FRESULT f_mkfs (
|
|
|
|
|
QWORD pt_lba;
|
|
|
|
|
|
|
|
|
|
/* Get the partition location from GPT */
|
|
|
|
|
if (disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load GPT header sector (next to MBR) */
|
|
|
|
|
if (FfDiskOps->disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load GPT header sector (next to MBR) */
|
|
|
|
|
if (!test_gpt_header(buf)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if GPT header is valid */
|
|
|
|
|
n_ent = ld_dword(buf + GPTH_PtNum); /* Number of entries */
|
|
|
|
|
pt_lba = ld_qword(buf + GPTH_PtOfs); /* Table start sector */
|
|
|
|
|
ofs = i = 0;
|
|
|
|
|
while (n_ent) { /* Find MS Basic partition with order of ipart */
|
|
|
|
|
if (ofs == 0 && disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */
|
|
|
|
|
if (ofs == 0 && FfDiskOps->disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */
|
|
|
|
|
if (!mem_cmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) { /* MS basic data partition? */
|
|
|
|
|
b_vol = ld_qword(buf + ofs + GPTE_FstLba);
|
|
|
|
|
sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1;
|
|
|
|
@ -5925,7 +5926,7 @@ FRESULT f_mkfs (
|
|
|
|
|
sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */
|
|
|
|
|
}
|
|
|
|
|
} else { /* The volume is associated with a physical drive */
|
|
|
|
|
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (!(fsopt & FM_SFD)) { /* To be partitioned? */
|
|
|
|
|
/* Create a single-partition on the drive in this function */
|
|
|
|
|
#if FF_LBA64
|
|
|
|
@ -5974,7 +5975,7 @@ FRESULT f_mkfs (
|
|
|
|
|
if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume for exFAT? */
|
|
|
|
|
#if FF_USE_TRIM
|
|
|
|
|
lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1; /* Inform storage device that the volume area may be erased */
|
|
|
|
|
disk_ioctl(pdrv, CTRL_TRIM, lba);
|
|
|
|
|
FfDiskOps->disk_ioctl(pdrv, CTRL_TRIM, lba);
|
|
|
|
|
#endif
|
|
|
|
|
/* Determine FAT location, data location and number of clusters */
|
|
|
|
|
if (sz_au == 0) { /* AU auto-selection */
|
|
|
|
@ -6024,7 +6025,7 @@ FRESULT f_mkfs (
|
|
|
|
|
i += 2; szb_case += 2;
|
|
|
|
|
if (si == 0 || i == sz_buf * ss) { /* Write buffered data when buffer full or end of process */
|
|
|
|
|
n = (i + ss - 1) / ss;
|
|
|
|
|
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
sect += n; i = 0;
|
|
|
|
|
}
|
|
|
|
|
} while (si);
|
|
|
|
@ -6039,7 +6040,7 @@ FRESULT f_mkfs (
|
|
|
|
|
for (i = 0; nb >= 8 && i < sz_buf * ss; buf[i++] = 0xFF, nb -= 8) ;
|
|
|
|
|
for (b = 1; nb != 0 && i < sz_buf * ss; buf[i] |= b, b <<= 1, nb--) ;
|
|
|
|
|
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
|
|
|
|
|
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
sect += n; nsect -= n;
|
|
|
|
|
} while (nsect);
|
|
|
|
|
|
|
|
|
@ -6060,7 +6061,7 @@ FRESULT f_mkfs (
|
|
|
|
|
if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */
|
|
|
|
|
} while (nb != 0 && i < sz_buf * ss);
|
|
|
|
|
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
|
|
|
|
|
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
sect += n; nsect -= n;
|
|
|
|
|
} while (nsect);
|
|
|
|
|
|
|
|
|
@ -6077,7 +6078,7 @@ FRESULT f_mkfs (
|
|
|
|
|
sect = b_data + sz_au * (tbl[0] + tbl[1]); nsect = sz_au; /* Start of the root directory and number of sectors */
|
|
|
|
|
do { /* Fill root directory sectors */
|
|
|
|
|
n = (nsect > sz_buf) ? sz_buf : nsect;
|
|
|
|
|
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
mem_set(buf, 0, ss);
|
|
|
|
|
sect += n; nsect -= n;
|
|
|
|
|
} while (nsect);
|
|
|
|
@ -6106,23 +6107,23 @@ FRESULT f_mkfs (
|
|
|
|
|
for (i = sum = 0; i < ss; i++) { /* VBR checksum */
|
|
|
|
|
if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum);
|
|
|
|
|
}
|
|
|
|
|
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
/* Extended bootstrap record (+1..+8) */
|
|
|
|
|
mem_set(buf, 0, ss);
|
|
|
|
|
st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */
|
|
|
|
|
for (j = 1; j < 9; j++) {
|
|
|
|
|
for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
|
|
|
|
|
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
}
|
|
|
|
|
/* OEM/Reserved record (+9..+10) */
|
|
|
|
|
mem_set(buf, 0, ss);
|
|
|
|
|
for ( ; j < 11; j++) {
|
|
|
|
|
for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
|
|
|
|
|
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
}
|
|
|
|
|
/* Sum record (+11) */
|
|
|
|
|
for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */
|
|
|
|
|
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else
|
|
|
|
@ -6204,7 +6205,7 @@ FRESULT f_mkfs (
|
|
|
|
|
|
|
|
|
|
#if FF_USE_TRIM
|
|
|
|
|
lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1; /* Inform storage device that the volume area may be erased */
|
|
|
|
|
disk_ioctl(pdrv, CTRL_TRIM, lba);
|
|
|
|
|
FfDiskOps->disk_ioctl(pdrv, CTRL_TRIM, lba);
|
|
|
|
|
#endif
|
|
|
|
|
/* Create FAT VBR */
|
|
|
|
|
mem_set(buf, 0, ss);
|
|
|
|
@ -6240,19 +6241,19 @@ FRESULT f_mkfs (
|
|
|
|
|
mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
|
|
|
|
|
}
|
|
|
|
|
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
|
|
|
|
|
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
|
|
|
|
|
|
|
|
|
|
/* Create FSINFO record if needed */
|
|
|
|
|
if (fsty == FS_FAT32) {
|
|
|
|
|
disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */
|
|
|
|
|
FfDiskOps->disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */
|
|
|
|
|
mem_set(buf, 0, ss);
|
|
|
|
|
st_dword(buf + FSI_LeadSig, 0x41615252);
|
|
|
|
|
st_dword(buf + FSI_StrucSig, 0x61417272);
|
|
|
|
|
st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
|
|
|
|
|
st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */
|
|
|
|
|
st_word(buf + BS_55AA, 0xAA55);
|
|
|
|
|
disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */
|
|
|
|
|
disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
|
|
|
|
|
FfDiskOps->disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */
|
|
|
|
|
FfDiskOps->disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initialize FAT area */
|
|
|
|
@ -6269,7 +6270,7 @@ FRESULT f_mkfs (
|
|
|
|
|
nsect = sz_fat; /* Number of FAT sectors */
|
|
|
|
|
do { /* Fill FAT sectors */
|
|
|
|
|
n = (nsect > sz_buf) ? sz_buf : nsect;
|
|
|
|
|
if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
mem_set(buf, 0, ss); /* Rest of FAT all are cleared */
|
|
|
|
|
sect += n; nsect -= n;
|
|
|
|
|
} while (nsect);
|
|
|
|
@ -6279,7 +6280,7 @@ FRESULT f_mkfs (
|
|
|
|
|
nsect = (fsty == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */
|
|
|
|
|
do {
|
|
|
|
|
n = (nsect > sz_buf) ? sz_buf : nsect;
|
|
|
|
|
if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
sect += n; nsect -= n;
|
|
|
|
|
} while (nsect);
|
|
|
|
|
}
|
|
|
|
@ -6305,9 +6306,9 @@ FRESULT f_mkfs (
|
|
|
|
|
if (FF_MULTI_PARTITION && ipart != 0) { /* Volume is in the existing partition */
|
|
|
|
|
if (!FF_LBA64 || !(fsopt & 0x80)) {
|
|
|
|
|
/* Update system ID in the partition table */
|
|
|
|
|
if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */
|
|
|
|
|
if (FfDiskOps->disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */
|
|
|
|
|
buf[MBR_Table + (ipart - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */
|
|
|
|
|
if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */
|
|
|
|
|
if (FfDiskOps->disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */
|
|
|
|
|
}
|
|
|
|
|
} else { /* Volume as a new single partition */
|
|
|
|
|
if (!(fsopt & FM_SFD)) { /* Create partition table if not in SFD */
|
|
|
|
@ -6317,7 +6318,7 @@ FRESULT f_mkfs (
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
if (FfDiskOps->disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
|
|
|
|
|
|
|
|
|
LEAVE_MKFS(FR_OK);
|
|
|
|
|
}
|
|
|
|
@ -6340,7 +6341,7 @@ FRESULT f_fdisk (
|
|
|
|
|
DSTATUS stat;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stat = disk_initialize(pdrv);
|
|
|
|
|
stat = FfDiskOps->disk_initialize(pdrv);
|
|
|
|
|
if (stat & STA_NOINIT) return FR_NOT_READY;
|
|
|
|
|
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
|
|
|
|
|
#if FF_USE_LFN == 3
|
|
|
|
|