diff --git a/src/diskio.c b/src/diskio.c deleted file mode 100644 index 76d2f2a..0000000 --- a/src/diskio.c +++ /dev/null @@ -1,228 +0,0 @@ -/*-----------------------------------------------------------------------*/ -/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ -/*-----------------------------------------------------------------------*/ -/* If a working storage control module is available, it should be */ -/* attached to the FatFs via a glue function rather than modifying it. */ -/* This is an example of glue functions to attach various exsisting */ -/* storage control modules to the FatFs module with a defined API. */ -/*-----------------------------------------------------------------------*/ - -#include "diskio.h" /* FatFs lower layer API */ -#include "usbdisk.h" /* Example: Header file of existing USB MSD control module */ -#include "atadrive.h" /* Example: Header file of existing ATA harddisk control module */ -#include "sdcard.h" /* Example: Header file of existing MMC/SDC contorl module */ - -/* Definitions of physical drive number for each drive */ -#define ATA 0 /* Example: Map ATA harddisk to physical drive 0 */ -#define MMC 1 /* Example: Map MMC/SD card to physical drive 1 */ -#define USB 2 /* Example: Map USB MSD to physical drive 2 */ - - -/*-----------------------------------------------------------------------*/ -/* Get Drive Status */ -/*-----------------------------------------------------------------------*/ - -DSTATUS disk_status ( - BYTE pdrv /* Physical drive nmuber to identify the drive */ -) -{ - DSTATUS stat; - int result; - - switch (pdrv) { - case ATA : - result = ATA_disk_status(); - - // translate the reslut code here - - return stat; - - case MMC : - result = MMC_disk_status(); - - // translate the reslut code here - - return stat; - - case USB : - result = USB_disk_status(); - - // translate the reslut code here - - return stat; - } - return STA_NOINIT; -} - - - -/*-----------------------------------------------------------------------*/ -/* Inidialize a Drive */ -/*-----------------------------------------------------------------------*/ - -DSTATUS disk_initialize ( - BYTE pdrv /* Physical drive nmuber to identify the drive */ -) -{ - DSTATUS stat; - int result; - - switch (pdrv) { - case ATA : - result = ATA_disk_initialize(); - - // translate the reslut code here - - return stat; - - case MMC : - result = MMC_disk_initialize(); - - // translate the reslut code here - - return stat; - - case USB : - result = USB_disk_initialize(); - - // translate the reslut code here - - return stat; - } - return STA_NOINIT; -} - - - -/*-----------------------------------------------------------------------*/ -/* Read Sector(s) */ -/*-----------------------------------------------------------------------*/ - -DRESULT disk_read ( - BYTE pdrv, /* Physical drive nmuber to identify the drive */ - BYTE *buff, /* Data buffer to store read data */ - DWORD sector, /* Sector address in LBA */ - UINT count /* Number of sectors to read */ -) -{ - DRESULT res; - int result; - - switch (pdrv) { - case ATA : - // translate the arguments here - - result = ATA_disk_read(buff, sector, count); - - // translate the reslut code here - - return res; - - case MMC : - // translate the arguments here - - result = MMC_disk_read(buff, sector, count); - - // translate the reslut code here - - return res; - - case USB : - // translate the arguments here - - result = USB_disk_read(buff, sector, count); - - // translate the reslut code here - - return res; - } - - return RES_PARERR; -} - - - -/*-----------------------------------------------------------------------*/ -/* Write Sector(s) */ -/*-----------------------------------------------------------------------*/ - -DRESULT disk_write ( - BYTE pdrv, /* Physical drive nmuber to identify the drive */ - const BYTE *buff, /* Data to be written */ - DWORD sector, /* Sector address in LBA */ - UINT count /* Number of sectors to write */ -) -{ - DRESULT res; - int result; - - switch (pdrv) { - case ATA : - // translate the arguments here - - result = ATA_disk_write(buff, sector, count); - - // translate the reslut code here - - return res; - - case MMC : - // translate the arguments here - - result = MMC_disk_write(buff, sector, count); - - // translate the reslut code here - - return res; - - case USB : - // translate the arguments here - - result = USB_disk_write(buff, sector, count); - - // translate the reslut code here - - return res; - } - - return RES_PARERR; -} - - - -/*-----------------------------------------------------------------------*/ -/* Miscellaneous Functions */ -/*-----------------------------------------------------------------------*/ - -DRESULT disk_ioctl ( - BYTE pdrv, /* Physical drive nmuber (0..) */ - BYTE cmd, /* Control code */ - void *buff /* Buffer to send/receive control data */ -) -{ - DRESULT res; - int result; - - switch (pdrv) { - case ATA : - - // Process of the command for the ATA drive - - return res; - - case MMC : - - // Process of the command for the MMC/SD card - - return res; - - case USB : - - // Process of the command the USB drive - - return res; - } - - return RES_PARERR; -} - diff --git a/src/diskio.h b/src/diskio.h index 3c7cac9..eb51a9f 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -9,7 +9,6 @@ extern "C" { #endif -#include "integer.h" /* Status of Disk Functions */ @@ -29,11 +28,9 @@ typedef enum { /* Prototypes for disk control functions */ -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); +DRESULT disk_read (void *drv, BYTE* buff, DWORD sector, UINT count); +DRESULT disk_write (void *drv, const BYTE* buff, DWORD sector, UINT count); +DRESULT disk_ioctl (void *drv, BYTE cmd, void* buff); /* Disk Status Bits (DSTATUS) */ @@ -51,6 +48,8 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ +#define IOCTL_INIT 5 +#define IOCTL_STATUS 6 /* Generic command (Not used by FatFs) */ #define CTRL_POWER 5 /* Get/Set power status */ diff --git a/src/ff.c b/src/ff.c index 2cca972..a8a68fb 100644 --- a/src/ff.c +++ b/src/ff.c @@ -492,13 +492,8 @@ typedef struct { #if _VOLUMES < 1 || _VOLUMES > 9 #error Wrong _VOLUMES setting #endif -static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ static WORD Fsid; /* File system mount ID */ -#if _FS_RPATH != 0 && _VOLUMES >= 2 -static BYTE CurrVol; /* Current drive */ -#endif - #if _FS_LOCK != 0 static FILESEM Files[_FS_LOCK]; /* Open object lock semaphores */ #endif @@ -2805,67 +2800,6 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ -/*-----------------------------------------------------------------------*/ -/* Get logical drive number from path name */ -/*-----------------------------------------------------------------------*/ - -static -int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ - const TCHAR** path /* Pointer to pointer to the path name */ -) -{ - const TCHAR *tp, *tt; - UINT i; - int vol = -1; -#if _STR_VOLUME_ID /* Find string drive id */ - static const char* const str[] = {_VOLUME_STRS}; - const char *sp; - char c; - TCHAR tc; -#endif - - - if (*path) { /* If the pointer is not a null */ - for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find ':' in the path */ - if (*tt == ':') { /* If a ':' is exist in the path name */ - tp = *path; - i = *tp++ - '0'; - if (i < 10 && tp == tt) { /* Is there a numeric drive id? */ - if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */ - vol = (int)i; - *path = ++tt; - } - } -#if _STR_VOLUME_ID - else { /* No numeric drive number, find string drive id */ - i = 0; tt++; - do { - sp = str[i]; tp = *path; - do { /* Compare a string drive id with path name */ - c = *sp++; tc = *tp++; - if (IsLower(tc)) tc -= 0x20; - } while (c && (TCHAR)c == tc); - } while ((c || tp != tt) && ++i < _VOLUMES); /* Repeat for each id until pattern match */ - if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */ - vol = (int)i; - *path = tt; - } - } -#endif - return vol; - } -#if _FS_RPATH != 0 && _VOLUMES >= 2 - vol = CurrVol; /* Current drive */ -#else - vol = 0; /* Drive 0 */ -#endif - } - return vol; -} - - - - /*-----------------------------------------------------------------------*/ /* Load a sector and check if it is an FAT boot sector */ /*-----------------------------------------------------------------------*/ @@ -2898,35 +2832,22 @@ BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk er static FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ - FATFS** rfs, /* Pointer to pointer to the found file system object */ + FATFS* fs, /* Pointer to the file system object */ BYTE mode /* !=0: Check write protection for write access */ ) { BYTE fmt, *pt; - int vol; DSTATUS stat; DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; WORD nrsv; - FATFS *fs; UINT i; - /* Get logical drive number from the path name */ - *rfs = 0; - vol = get_ldnumber(path); - if (vol < 0) return FR_INVALID_DRIVE; - - /* Check if the file system object is valid or not */ - fs = FatFs[vol]; /* Get pointer to the file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ - ENTER_FF(fs); /* Lock the volume */ - *rfs = fs; /* Return pointer to the file system object */ mode &= ~FA_READ; /* Desired access mode, write access or not */ if (fs->fs_type) { /* If the volume has been mounted */ - stat = disk_status(fs->drv); + disk_ioctl(fs->drv, IOCTL_STATUS, &stat); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ return FR_WRITE_PROTECTED; @@ -2939,8 +2860,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ fs->fs_type = 0; /* Clear the file system object */ - fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize the physical drive */ + disk_ioctl(fs->drv, IOCTL_INIT, &stat); /* 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 */ } @@ -2954,17 +2874,17 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ bsect = 0; fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */ - if (fmt == 2 || (fmt < 2 && LD2PT(vol))) { /* Not an FAT boot sector or forced partition number */ + if (fmt == 2 || (fmt < 2 && LD2PT(fs))) { /* Not an FAT boot sector or forced partition number */ for (i = 0; i < 4; i++) { /* Get partition offset */ pt = fs->win + MBR_Table + i * SZ_PTE; br[i] = pt[4] ? ld_dword(&pt[8]) : 0; } - i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ + i = LD2PT(fs); /* Partition number: 0:auto, 1-4:forced */ if (i) i--; do { /* Find an FAT volume */ bsect = br[i]; fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ - } while (!LD2PT(vol) && fmt >= 2 && ++i < 4); + } while (!LD2PT(fs) && fmt >= 2 && ++i < 4); } if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ @@ -3124,9 +3044,10 @@ FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ { _FDID *obj = (_FDID*)dfp; /* Assuming .obj in the FIL/DIR is the first member */ FRESULT res; + DSTATUS stat; - if (!dfp || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) { + if (!dfp || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || disk_ioctl(obj->fs->drv, IOCTL_STATUS, &stat) != RES_OK || (stat & STA_NOINIT)) { *fs = 0; /* The object is invalid */ res = FR_INVALID_OBJECT; } else { @@ -3153,46 +3074,35 @@ FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ /*-----------------------------------------------------------------------*/ FRESULT f_mount ( - FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/ - const TCHAR* path, /* Logical drive number to be mounted/unmounted */ - BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */ + FATFS* fs /* Pointer to the file system object to mount */ ) { - FATFS *cfs; - int vol; FRESULT res; - const TCHAR *rp = path; - - - vol = get_ldnumber(&rp); - if (vol < 0) return FR_INVALID_DRIVE; - cfs = FatFs[vol]; /* Pointer to fs object */ - - if (cfs) { -#if _FS_LOCK != 0 - clear_lock(cfs); -#endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; -#endif - cfs->fs_type = 0; /* Clear old fs object */ - } - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ + fs->fs_type = 0; /* Clear new fs object */ #if _FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; + if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; #endif - } - FatFs[vol] = fs; /* Register new fs object */ - - if (!fs || opt != 1) return FR_OK; /* Do not mount now, it will be mounted later */ - res = find_volume(&path, &fs, 0); /* Force mounted the volume */ + res = find_volume(fs, 0); /* Force mounted the volume */ LEAVE_FF(fs, res); } +FRESULT f_umount ( + FATFS* fs /* Pointer to the file system object to unmount */ +) +{ +#if _FS_LOCK + clear_lock(fs); +#endif +#if _FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(fs->sobj)) return FR_INT_ERR; +#endif + fs->fs_type = 0; /* Clear old fs object */ + + return FR_OK; +} /*-----------------------------------------------------------------------*/ @@ -3200,6 +3110,7 @@ FRESULT f_mount ( /*-----------------------------------------------------------------------*/ FRESULT f_open ( + FATFS *fs, FIL* fp, /* Pointer to the blank file object */ const TCHAR* path, /* Pointer to the file name */ BYTE mode /* Access mode and file open mode flags */ @@ -3207,7 +3118,6 @@ FRESULT f_open ( { FRESULT res; DIR dj; - FATFS *fs; #if !_FS_READONLY DWORD dw, cl; #endif @@ -3219,7 +3129,7 @@ FRESULT f_open ( /* Get logical drive number */ mode &= _FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; - res = find_volume(&path, &fs, mode); + res = find_volume(fs, mode); if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(dj); @@ -3728,35 +3638,17 @@ FRESULT f_close ( /*-----------------------------------------------------------------------*/ #if _FS_RPATH >= 1 -#if _VOLUMES >= 2 -FRESULT f_chdrive ( - const TCHAR* path /* Drive number */ -) -{ - int vol; - - - vol = get_ldnumber(&path); - if (vol < 0) return FR_INVALID_DRIVE; - - CurrVol = (BYTE)vol; - - return FR_OK; -} -#endif - - FRESULT f_chdir ( + FATFS *fs, const TCHAR* path /* Pointer to the directory path */ ) { FRESULT res; DIR dj; - FATFS *fs; DEF_NAMBUF; /* Get logical drive number */ - res = find_volume(&path, &fs, 0); + res = find_volume(fs, 0); if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(dj); @@ -3799,13 +3691,13 @@ FRESULT f_chdir ( #if _FS_RPATH >= 2 FRESULT f_getcwd ( + FATFS *fs, TCHAR* buff, /* Pointer to the directory path */ UINT len /* Size of path */ ) { FRESULT res; DIR dj; - FATFS *fs; UINT i, n; DWORD ccl; TCHAR *tp; @@ -3815,7 +3707,7 @@ FRESULT f_getcwd ( *buff = 0; /* Get logical drive number */ - res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ + res = find_volume(fs, 0); /* Get current volume */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(dj); @@ -3849,10 +3741,6 @@ FRESULT f_getcwd ( } tp = buff; if (res == FR_OK) { -#if _VOLUMES >= 2 - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; -#endif if (i == len) { /* Root-directory */ *tp++ = '/'; } else { /* Sub-directroy */ @@ -4039,12 +3927,12 @@ FRESULT f_lseek ( /*-----------------------------------------------------------------------*/ FRESULT f_opendir ( + FATFS *fs, DIR* dp, /* Pointer to directory object to create */ const TCHAR* path /* Pointer to the directory path */ ) { FRESULT res; - FATFS *fs; _FDID *obj; DEF_NAMBUF; @@ -4053,7 +3941,7 @@ FRESULT f_opendir ( /* Get logical drive number */ obj = &dp->obj; - res = find_volume(&path, &fs, 0); + res = find_volume(fs, 0); if (res == FR_OK) { obj->fs = fs; INIT_NAMBUF(*dp); @@ -4230,6 +4118,7 @@ FRESULT f_findfirst ( /*-----------------------------------------------------------------------*/ FRESULT f_stat ( + FATFS *fs, const TCHAR* path, /* Pointer to the file path */ FILINFO* fno /* Pointer to file information to return */ ) @@ -4240,7 +4129,8 @@ FRESULT f_stat ( /* Get logical drive number */ - res = find_volume(&path, &dj.obj.fs, 0); + res = find_volume(fs, 0); + dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(dj); res = follow_path(&dj, path); /* Follow the file path */ @@ -4265,13 +4155,11 @@ FRESULT f_stat ( /*-----------------------------------------------------------------------*/ FRESULT f_getfree ( - const TCHAR* path, /* Path name of the logical drive number */ - DWORD* nclst, /* Pointer to a variable to return number of free clusters */ - FATFS** fatfs /* Pointer to return pointer to corresponding file system object */ + FATFS *fs, + DWORD* nclst /* Pointer to a variable to return number of free clusters */ ) { FRESULT res; - FATFS *fs; DWORD nfree, clst, sect, stat; UINT i; BYTE *p; @@ -4279,9 +4167,8 @@ FRESULT f_getfree ( /* Get logical drive number */ - res = find_volume(&path, &fs, 0); + res = find_volume(fs, 0); if (res == FR_OK) { - *fatfs = fs; /* Return ptr to the fs object */ /* If free_clst is valid, return it without full cluster scan */ if (fs->free_clst <= fs->n_fatent - 2) { *nclst = fs->free_clst; @@ -4402,13 +4289,13 @@ FRESULT f_truncate ( /*-----------------------------------------------------------------------*/ FRESULT f_unlink ( + FATFS *fs, const TCHAR* path /* Pointer to the file or directory path */ ) { FRESULT res; DIR dj, sdj; DWORD dclst = 0; - FATFS *fs; #if _FS_EXFAT _FDID obj; #endif @@ -4416,7 +4303,7 @@ FRESULT f_unlink ( /* Get logical drive number */ - res = find_volume(&path, &fs, FA_WRITE); + res = find_volume(fs, FA_WRITE); dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(dj); @@ -4497,12 +4384,12 @@ FRESULT f_unlink ( /*-----------------------------------------------------------------------*/ FRESULT f_mkdir ( + FATFS *fs, const TCHAR* path /* Pointer to the directory path */ ) { FRESULT res; DIR dj; - FATFS *fs; BYTE *dir; UINT n; DWORD dsc, dcl, pcl, tm; @@ -4510,7 +4397,7 @@ FRESULT f_mkdir ( /* Get logical drive number */ - res = find_volume(&path, &fs, FA_WRITE); + res = find_volume(fs, FA_WRITE); dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(dj); @@ -4591,20 +4478,19 @@ FRESULT f_mkdir ( /*-----------------------------------------------------------------------*/ FRESULT f_rename ( + FATFS *fs, const TCHAR* path_old, /* Pointer to the object name to be renamed */ const TCHAR* path_new /* Pointer to the new name */ ) { FRESULT res; DIR djo, djn; - FATFS *fs; BYTE buf[_FS_EXFAT ? SZDIRE * 2 : 24], *dir; DWORD dw; DEF_NAMBUF; - get_ldnumber(&path_new); /* Ignore drive number of new name */ - res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive number of the old object */ + res = find_volume(fs, FA_WRITE); if (res == FR_OK) { djo.obj.fs = fs; INIT_NAMBUF(djo); @@ -4695,6 +4581,7 @@ FRESULT f_rename ( /*-----------------------------------------------------------------------*/ FRESULT f_chmod ( + FATFS *fs, const TCHAR* path, /* Pointer to the file path */ BYTE attr, /* Attribute bits */ BYTE mask /* Attribute mask to change */ @@ -4702,11 +4589,10 @@ FRESULT f_chmod ( { FRESULT res; DIR dj; - FATFS *fs; DEF_NAMBUF; - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive number */ + res = find_volume(fs, FA_WRITE); /* Get logical drive number */ dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(dj); @@ -4740,18 +4626,17 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ FRESULT f_utime ( + FATFS *fs, const TCHAR* path, /* Pointer to the file/directory name */ const FILINFO* fno /* Pointer to the time stamp to be set */ ) { FRESULT res; DIR dj; - FATFS *fs; DEF_NAMBUF; - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive number */ - dj.obj.fs = fs; + res = find_volume(fs, FA_WRITE); /* Get logical drive number */ if (res == FR_OK) { INIT_NAMBUF(dj); res = follow_path(&dj, path); /* Follow the file path */ @@ -4787,21 +4672,20 @@ FRESULT f_utime ( /*-----------------------------------------------------------------------*/ FRESULT f_getlabel ( - const TCHAR* path, /* Path name of the logical drive number */ + FATFS *fs, TCHAR* label, /* Pointer to a buffer to return the volume label */ DWORD* vsn /* Pointer to a variable to return the volume serial number */ ) { FRESULT res; DIR dj; - FATFS *fs; UINT si, di; #if _LFN_UNICODE || _FS_EXFAT WCHAR w; #endif /* Get logical drive number */ - res = find_volume(&path, &fs, 0); + res = find_volume(fs, 0); /* Get volume label */ if (res == FR_OK && label) { @@ -4876,12 +4760,12 @@ FRESULT f_getlabel ( /*-----------------------------------------------------------------------*/ FRESULT f_setlabel ( + FATFS *fs, const TCHAR* label /* Pointer to the volume label to set */ ) { FRESULT res; DIR dj; - FATFS *fs; BYTE dirvn[22]; UINT i, j, slen; WCHAR w; @@ -4889,7 +4773,7 @@ FRESULT f_setlabel ( /* Get logical drive number */ - res = find_volume(&label, &fs, FA_WRITE); + res = find_volume(fs, FA_WRITE); if (res != FR_OK) LEAVE_FF(fs, res); dj.obj.fs = fs; @@ -5149,20 +5033,18 @@ FRESULT f_forward ( FRESULT f_mkfs ( - const TCHAR* path, /* Logical drive number */ + FATFS *fs, BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ UINT au /* Size of allocation unit in unit of byte or sector */ ) { static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - int vol; - BYTE fmt, md, sys, *tbl, pdrv, part; + BYTE fmt, md, sys, *tbl, part; void *pdrv; DWORD n_clst, vs, n, wsect; UINT i; DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ - FATFS *fs; DSTATUS stat; #if _USE_TRIM DWORD eb[2]; @@ -5171,16 +5053,13 @@ FRESULT f_mkfs ( /* Check mounted drive and clear work area */ if (sfd > 1) return FR_INVALID_PARAMETER; - vol = get_ldnumber(&path); /* Get target volume */ - if (vol < 0) return FR_INVALID_DRIVE; - fs = FatFs[vol]; /* Check if the volume has work area */ if (!fs) return FR_NOT_ENABLED; fs->fs_type = 0; - pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ + pdrv = fs->drv; /* Physical drive */ + part = LD2PT(fs); /* Partition (0:auto detect, 1-4:get from partition table)*/ /* Get disk statics */ - stat = disk_initialize(pdrv); + disk_ioctl(pdrv, IOCTL_INIT, &stat); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if _MAX_SS != _MIN_SS /* Get disk sector size */ @@ -5405,7 +5284,7 @@ FRESULT f_mkfs ( /*-----------------------------------------------------------------------*/ FRESULT f_fdisk ( - BYTE pdrv, /* Physical drive number */ + void *pdrv, /* Physical drive */ const DWORD szt[], /* Pointer to the size table for each partitions */ void* work /* Pointer to the working buffer */ ) @@ -5416,7 +5295,7 @@ FRESULT f_fdisk ( DWORD sz_disk, sz_part, s_part; - stat = disk_initialize(pdrv); + disk_ioctl(pdrv, IOCTL_INIT, &stat); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; @@ -5468,309 +5347,3 @@ FRESULT f_fdisk ( #endif /* _MULTI_PARTITION */ #endif /* _USE_MKFS && !_FS_READONLY */ - - - - -#if _USE_STRFUNC -/*-----------------------------------------------------------------------*/ -/* Get a string from the file */ -/*-----------------------------------------------------------------------*/ - -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (characters) */ - FIL* fp /* Pointer to the file object */ -) -{ - int n = 0; - TCHAR c, *p = buff; - BYTE s[2]; - UINT rc; - - - while (n < len - 1) { /* Read characters until buffer gets filled */ -#if _LFN_UNICODE -#if _STRF_ENCODE == 3 /* Read a character in UTF-8 */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = s[0]; - if (c >= 0x80) { - if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequence */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = (c & 0x1F) << 6 | (s[0] & 0x3F); - if (c < 0x80) c = '?'; - } else { - if (c < 0xF0) { /* Three-byte sequence */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F); - if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequence */ - c = '?'; - } - } - } -#elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = s[1] + (s[0] << 8); -#elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = s[0] + (s[1] << 8); -#else /* Read a character in ANSI/OEM */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = s[0]; - if (IsDBCS1(c)) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = (c << 8) + s[0]; - } - c = ff_convert(c, 1); /* OEM -> Unicode */ - if (!c) c = '?'; -#endif -#else /* Read a character without conversion */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = s[0]; -#endif - if (_USE_STRFUNC == 2 && c == '\r') continue; /* Strip '\r' */ - *p++ = c; - n++; - if (c == '\n') break; /* Break on EOL */ - } - *p = 0; - return n ? buff : 0; /* When no data read (eof or error), return with error. */ -} - - - - -#if !_FS_READONLY -#include -/*-----------------------------------------------------------------------*/ -/* Put a character to the file */ -/*-----------------------------------------------------------------------*/ - -typedef struct { - FIL* fp; - int idx, nchr; - BYTE buf[64]; -} putbuff; - - -static -void putc_bfd ( - putbuff* pb, - TCHAR c -) -{ - UINT bw; - int i; - - - if (_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ - putc_bfd(pb, '\r'); - } - - i = pb->idx; /* Buffer write index (-1:error) */ - if (i < 0) return; - -#if _LFN_UNICODE -#if _STRF_ENCODE == 3 /* Write a character in UTF-8 */ - if (c < 0x80) { /* 7-bit */ - pb->buf[i++] = (BYTE)c; - } else { - if (c < 0x800) { /* 11-bit */ - pb->buf[i++] = (BYTE)(0xC0 | c >> 6); - } else { /* 16-bit */ - pb->buf[i++] = (BYTE)(0xE0 | c >> 12); - pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F)); - } - pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F)); - } -#elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */ - pb->buf[i++] = (BYTE)(c >> 8); - pb->buf[i++] = (BYTE)c; -#elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */ - pb->buf[i++] = (BYTE)c; - pb->buf[i++] = (BYTE)(c >> 8); -#else /* Write a character in ANSI/OEM */ - c = ff_convert(c, 0); /* Unicode -> OEM */ - if (!c) c = '?'; - if (c >= 0x100) - pb->buf[i++] = (BYTE)(c >> 8); - pb->buf[i++] = (BYTE)c; -#endif -#else /* Write a character without conversion */ - pb->buf[i++] = (BYTE)c; -#endif - - if (i >= (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */ - f_write(pb->fp, pb->buf, (UINT)i, &bw); - i = (bw == (UINT)i) ? 0 : -1; - } - pb->idx = i; - pb->nchr++; -} - - - -int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - putbuff pb; - UINT nw; - - - pb.fp = fp; /* Initialize output buffer */ - pb.nchr = pb.idx = 0; - - putc_bfd(&pb, c); /* Put a character */ - - if ( pb.idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK - && (UINT)pb.idx == nw) return pb.nchr; - return EOF; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - putbuff pb; - UINT nw; - - - pb.fp = fp; /* Initialize output buffer */ - pb.nchr = pb.idx = 0; - - while (*str) /* Put the string */ - putc_bfd(&pb, *str++); - - if ( pb.idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK - && (UINT)pb.idx == nw) return pb.nchr; - return EOF; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a formatted string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_printf ( - FIL* fp, /* Pointer to the file object */ - const TCHAR* fmt, /* Pointer to the format string */ - ... /* Optional arguments... */ -) -{ - va_list arp; - BYTE f, r; - UINT nw, i, j, w; - DWORD v; - TCHAR c, d, str[32], *p; - putbuff pb; - - - pb.fp = fp; /* Initialize output buffer */ - pb.nchr = pb.idx = 0; - - va_start(arp, fmt); - - for (;;) { - c = *fmt++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - putc_bfd(&pb, c); - continue; - } - w = f = 0; - c = *fmt++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *fmt++; - } else { - if (c == '-') { /* Flag: left justified */ - f = 2; c = *fmt++; - } - } - while (IsDigit(c)) { /* Precision */ - w = w * 10 + c - '0'; - c = *fmt++; - } - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 4; c = *fmt++; - } - if (!c) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - p = va_arg(arp, TCHAR*); - for (j = 0; p[j]; j++) ; - if (!(f & 2)) { - while (j++ < w) putc_bfd(&pb, ' '); - } - while (*p) putc_bfd(&pb, *p++); - while (j++ < w) putc_bfd(&pb, ' '); - continue; - case 'C' : /* Character */ - putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown type (pass-through) */ - putc_bfd(&pb, c); continue; - } - - /* Get an argument and put it in numeral */ - v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); - if (d == 'D' && (v & 0x80000000)) { - v = 0 - v; - f |= 8; - } - i = 0; - do { - d = (TCHAR)(v % r); v /= r; - if (d > 9) d += (c == 'x') ? 0x27 : 0x07; - str[i++] = d + '0'; - } while (v && i < sizeof str / sizeof str[0]); - if (f & 8) str[i++] = '-'; - j = i; d = (f & 1) ? '0' : ' '; - while (!(f & 2) && j++ < w) putc_bfd(&pb, d); - do putc_bfd(&pb, str[--i]); while (i); - while (j++ < w) putc_bfd(&pb, d); - } - - va_end(arp); - - if ( pb.idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK - && (UINT)pb.idx == nw) return pb.nchr; - return EOF; -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_STRFUNC */ diff --git a/src/ff.h b/src/ff.h index 5f9c041..ab1fbe1 100644 --- a/src/ff.h +++ b/src/ff.h @@ -23,8 +23,28 @@ extern "C" { #endif -#include "integer.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ +#include + +/* This type MUST be 8-bit */ +typedef uint8_t BYTE; + +/* These types MUST be 16-bit */ +typedef int16_t SHORT; +typedef uint16_t WORD; +typedef uint16_t WCHAR; + +/* These types MUST be 16-bit or 32-bit */ +typedef int INT; +typedef unsigned int UINT; + +/* These types MUST be 32-bit */ +typedef int32_t LONG; +typedef uint32_t DWORD; + +/* This type MUST be 64-bit (Remove this for C89 compatibility) */ +typedef uint64_t QWORD; + +#include FFCONF_H /* FatFs configuration options */ #if _FATFS != _FFCONF #error Wrong configuration file (ffconf.h). #endif @@ -33,19 +53,10 @@ extern "C" { /* Definitions of volume management */ -#if _MULTI_PARTITION /* Multiple partition configuration */ -typedef struct { - BYTE pd; /* Physical drive number */ - BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ -} PARTITION; -extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ - +#if _MULTI_PARTITION /* Multiple partition configuration */ +#define LD2PT(fs) (fs->part) /* Get partition index */ #else /* Single partition configuration */ -#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ -#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ - +#define LD2PT(fs) 0 /* Find first valid partition or in SFD */ #endif @@ -76,8 +87,11 @@ typedef char TCHAR; /* File system object structure (FATFS) */ typedef struct { + void *drv; // block device underlying this filesystem +#if _MULTI_PARTITION /* Multiple partition configuration */ + BYTE part; // Partition: 0:Auto detect, 1-4:Forced partition +#endif BYTE fs_type; /* File system type (0:N/A) */ - BYTE drv; /* Physical drive number */ BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE wflag; /* win[] flag (b0:dirty) */ BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ @@ -242,39 +256,35 @@ typedef enum { /*--------------------------------------------------------------*/ /* FatFs module application interface */ -FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_open (FATFS *fs, FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of a file object */ FRESULT f_truncate (FIL* fp); /* Truncate file */ FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ -FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_opendir (FATFS *fs, DIR* dp, const TCHAR* path); /* Open a directory */ FRESULT f_closedir (DIR* dp); /* Close an open directory */ FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ -FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ -FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ -FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ -FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ -FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of the file/dir */ -FRESULT f_chdir (const TCHAR* path); /* Change current directory */ -FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ -FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ -FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ -FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ -FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_mkdir (FATFS *fs, const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (FATFS *fs, const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (FATFS *fs, const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (FATFS *fs, const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (FATFS *fs, const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */ +FRESULT f_utime (FATFS *fs, const TCHAR* path, const FILINFO* fno); /* Change timestamp of the file/dir */ +FRESULT f_chdir (FATFS *fs, const TCHAR* path); /* Change current directory */ +FRESULT f_getcwd (FATFS *fs, TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (FATFS *fs, DWORD* nclst); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (FATFS *fs, TCHAR* label, DWORD* vsn); /* Get volume label */ +FRESULT f_setlabel (FATFS *fs, const TCHAR* label); /* Set volume label */ FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ -FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ -FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */ -FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ -int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ -int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ -int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ +FRESULT f_mount (FATFS* fs); /* Mount/Unmount a logical drive */ +FRESULT f_umount (FATFS* fs); /* Unmount a logical drive */ +FRESULT f_mkfs (FATFS* fs, BYTE sfd, UINT au); /* Create a file system on the volume */ +FRESULT f_fdisk (void *pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) #define f_error(fp) ((fp)->err) diff --git a/src/integer.h b/src/integer.h deleted file mode 100644 index 66d7e3b..0000000 --- a/src/integer.h +++ /dev/null @@ -1,38 +0,0 @@ -/*-------------------------------------------*/ -/* Integer type definitions for FatFs module */ -/*-------------------------------------------*/ - -#ifndef _FF_INTEGER -#define _FF_INTEGER - -#ifdef _WIN32 /* FatFs development platform */ - -#include -#include -typedef unsigned __int64 QWORD; - - -#else /* Embedded platform */ - -/* These types MUST be 16-bit or 32-bit */ -typedef int INT; -typedef unsigned int UINT; - -/* This type MUST be 8-bit */ -typedef unsigned char BYTE; - -/* These types MUST be 16-bit */ -typedef short SHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; - -/* These types MUST be 32-bit */ -typedef long LONG; -typedef unsigned long DWORD; - -/* This type MUST be 64-bit (Remove this for C89 compatibility) */ -typedef unsigned long long QWORD; - -#endif - -#endif diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..9f4f72b --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +fatfs1 diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..e1b9f58 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,7 @@ +all: fatfs1 + +fatfs1: ../src/ff.c ../src/option/ccsbcs.c util.c fatfs1.c + gcc -g -I.. -std=c99 -DFFCONF_H='"tests/fatfs1_conf.h"' $^ -o $@ + +test: fatfs1 + ./fatfs1 | diff - fatfs1.exp diff --git a/tests/fatfs1.c b/tests/fatfs1.c new file mode 100644 index 0000000..7350b96 --- /dev/null +++ b/tests/fatfs1.c @@ -0,0 +1,217 @@ +#include +#include +#include +#include + +#include "tests/util.h" +#include "src/ff.h" +#include "src/diskio.h" + +#define NSEC (128) +#define SEC_SIZE (512) +static uint8_t ram_bdev[NSEC * SEC_SIZE]; + +struct _bdev_t { + int pdrv; +}; + +DRESULT disk_read(void *bdev_in, BYTE *buff, DWORD sector, UINT count) { + struct _bdev_t *bdev = bdev_in; + printf("disk_read(%d, %u, %u)\n", bdev->pdrv, sector, count); + memcpy(buff, ram_bdev + sector * SEC_SIZE, count * SEC_SIZE); + return RES_OK; +} + +static DWORD sector_no_hash = -1; +DRESULT disk_write(void *bdev_in, const BYTE *buff, DWORD sector, UINT count) { + struct _bdev_t *bdev = bdev_in; + printf("disk_write(%d, %u, %u, ", bdev->pdrv, sector, count); + if (sector == sector_no_hash) { + // some sectors have non-deterministic data + printf(""); + } else { + printf("0x%08x", hash_djb2(buff, count * SEC_SIZE)); + } + printf(")\n"); + memcpy(ram_bdev + sector * SEC_SIZE, buff, count * SEC_SIZE); + return RES_OK; +} + +DRESULT disk_ioctl(void *bdev_in, BYTE cmd, void *buff) { + struct _bdev_t *bdev = bdev_in; + printf("disk_ioctl(%d, %u)\n", bdev->pdrv, cmd); + switch (cmd) { + case CTRL_SYNC: break; + case GET_SECTOR_COUNT: *((DWORD*)buff) = NSEC; break; + case GET_SECTOR_SIZE: *((WORD*)buff) = SEC_SIZE; break; + case GET_BLOCK_SIZE: *((DWORD*)buff) = 1; break; + case IOCTL_INIT: *((DSTATUS*)buff) = 0; break; + case IOCTL_STATUS: *((DSTATUS*)buff) = 0; break; + default: assert(0); + } + return RES_OK; +} + +DWORD get_fattime(void) { + printf("get_fattime()\n"); + return 0; +} + +int main() { + struct _bdev_t bdev = {0}; + FATFS fatfs; + fatfs.drv = &bdev; + + printf("== MKFS ==\n"); + { + FRESULT res = f_mkfs(&fatfs, 1, 0); + printf("mkfs res=%d\n", res); + } + + printf("== MOUNT ==\n"); + { + FRESULT res = f_mount(&fatfs); + printf("mount res=%d\n", res); + } + + printf("== SET LABEL ==\n"); + { + FRESULT res = f_setlabel(&fatfs, "LABEL"); + printf("setlabel res=%d\n", res); + } + + printf("== GET LABEL ==\n"); + { + uint8_t buf[256]; + DWORD vsn; + FRESULT res = f_getlabel(&fatfs, (TCHAR*)buf, &vsn); + printf("getlabel res=%d label=%.12s vsn=%u\n", res, buf, vsn); + } + + printf("== FILE CREATION ==\n"); + { + FIL fp; + FRESULT res = f_open(&fatfs, &fp, "/test.txt", FA_WRITE | FA_CREATE_ALWAYS); + printf("open res=%d\n", res); + UINT n; + res = f_write(&fp, "test file\n", 10, &n); + printf("write res=%d n=%u\n", res, n); + sector_no_hash = 34; + res = f_close(&fp); + sector_no_hash = -1; + printf("close res=%d\n", res); + } + + printf("== FILE READ ==\n"); + { + FIL fp; + FRESULT res = f_open(&fatfs, &fp, "/test.txt", FA_READ); + printf("open res=%d\n", res); + uint8_t buf[100]; + UINT n; + res = f_read(&fp, buf, 100, &n); + printf("read res=%d n=%u\n", res, n); + hexdump(buf, n, 16); + res = f_close(&fp); + printf("close res=%d\n", res); + } + + printf("== STAT ==\n"); + { + FILINFO fno; + FRESULT res = f_stat(&fatfs, "/test.txt", &fno); + printf("stat res=%d size=%u date=%u time=%u attrib=%u\n", res, fno.fsize, fno.fdate, fno.ftime, fno.fattrib); + } + + printf("== FILE CREATION, LONG NAME AND LOTS OF DATA ==\n"); + { + FIL fp; + FRESULT res = f_open(&fatfs, &fp, "/filename-that-is-long.txt", FA_WRITE | FA_CREATE_ALWAYS); + printf("open res=%d\n", res); + UINT n; + for (int i = 0; i < 10; ++i) { + res = f_write(&fp, "More data for the test file. Need to have enough characters to fill more than one 512-byte sector.\n", 100, &n); + printf("write res=%d n=%u\n", res, n); + } + res = f_close(&fp); + printf("close res=%d\n", res); + } + + printf("== FILE SEEK AND READ ==\n"); + { + FIL fp; + FRESULT res = f_open(&fatfs, &fp, "/filename-that-is-long.txt", FA_READ); + printf("open res=%d\n", res); + res = f_lseek(&fp, 800); + printf("lseek res=%d\n", res); + printf("tell %d\n", f_tell(&fp)); + uint8_t buf[100]; + UINT n; + res = f_read(&fp, buf, 100, &n); + printf("read res=%d n=%u\n", res, n); + hexdump(buf, n, 16); + res = f_close(&fp); + printf("close res=%d\n", res); + } + + printf("== MKDIR ==\n"); + { + FRESULT res = f_mkdir(&fatfs, "/dir"); + printf("mkdir res=%d\n", res); + } + + printf("== DIRECTORY LISTING ==\n"); + { + DIR dp; + FRESULT res = f_opendir(&fatfs, &dp, "/"); + printf("opendir res=%d\n", res); + FILINFO fno; + for (;;){ + res = f_readdir(&dp, &fno); + if (res != FR_OK || fno.fname[0] == 0) { + break; + } + #if _USE_LFN + // note: lfname is empty string if it fits in 12 chars in fname + printf("readdir res=%d size=%u name=/%s/ lname=/%s/\n", res, fno.fsize, fno.altname, fno.fname); + #else + printf("readdir res=%d size=%u name=/%s/\n", res, fno.fsize, fno.fname); + #endif + } + res = f_closedir(&dp); + printf("closedir res=%d\n", res); + } + + printf("== RENAME FILE ==\n"); + { + FRESULT res = f_rename(&fatfs, "/test.txt", "/test2.txt"); + printf("unlink res=%d\n", res); + } + + printf("== UNLINK FILE ==\n"); + { + FRESULT res = f_unlink(&fatfs, "/test2.txt"); + printf("unlink res=%d\n", res); + } + + printf("== RENAME DIR ==\n"); + { + FRESULT res = f_rename(&fatfs, "/dir", "/dir2"); + printf("unlink res=%d\n", res); + } + + printf("== UNLINK DIR ==\n"); + { + FRESULT res = f_unlink(&fatfs, "/dir2"); + printf("unlink res=%d\n", res); + } + + printf("== FREE SPACE ==\n"); + { + DWORD nclst; + FRESULT res = f_getfree(&fatfs, &nclst); + printf("getfree res=%d nclst=%u\n", res, nclst); + } + + return 0; +} diff --git a/tests/fatfs1.exp b/tests/fatfs1.exp new file mode 100644 index 0000000..c539ee2 --- /dev/null +++ b/tests/fatfs1.exp @@ -0,0 +1,195 @@ +== MKFS == +disk_ioctl(0, 5) +disk_ioctl(0, 1) +disk_ioctl(0, 3) +get_fattime() +disk_write(0, 0, 1, 0x56c0aabe) +disk_write(0, 1, 1, 0x9ca634d5) +disk_write(0, 2, 1, 0x082d5505) +disk_write(0, 3, 1, 0x082d5505) +disk_write(0, 4, 1, 0x082d5505) +disk_write(0, 5, 1, 0x082d5505) +disk_write(0, 6, 1, 0x082d5505) +disk_write(0, 7, 1, 0x082d5505) +disk_write(0, 8, 1, 0x082d5505) +disk_write(0, 9, 1, 0x082d5505) +disk_write(0, 10, 1, 0x082d5505) +disk_write(0, 11, 1, 0x082d5505) +disk_write(0, 12, 1, 0x082d5505) +disk_write(0, 13, 1, 0x082d5505) +disk_write(0, 14, 1, 0x082d5505) +disk_write(0, 15, 1, 0x082d5505) +disk_write(0, 16, 1, 0x082d5505) +disk_write(0, 17, 1, 0x082d5505) +disk_write(0, 18, 1, 0x082d5505) +disk_write(0, 19, 1, 0x082d5505) +disk_write(0, 20, 1, 0x082d5505) +disk_write(0, 21, 1, 0x082d5505) +disk_write(0, 22, 1, 0x082d5505) +disk_write(0, 23, 1, 0x082d5505) +disk_write(0, 24, 1, 0x082d5505) +disk_write(0, 25, 1, 0x082d5505) +disk_write(0, 26, 1, 0x082d5505) +disk_write(0, 27, 1, 0x082d5505) +disk_write(0, 28, 1, 0x082d5505) +disk_write(0, 29, 1, 0x082d5505) +disk_write(0, 30, 1, 0x082d5505) +disk_write(0, 31, 1, 0x082d5505) +disk_write(0, 32, 1, 0x082d5505) +disk_write(0, 33, 1, 0x082d5505) +disk_ioctl(0, 0) +mkfs res=0 +== MOUNT == +disk_ioctl(0, 5) +disk_read(0, 0, 1) +mount res=0 +== SET LABEL == +disk_ioctl(0, 6) +disk_read(0, 2, 1) +disk_write(0, 2, 1, 0x0d96b58b) +disk_ioctl(0, 0) +setlabel res=0 +== GET LABEL == +disk_ioctl(0, 6) +disk_read(0, 0, 1) +getlabel res=0 label=LABEL vsn=0 +== FILE CREATION == +disk_ioctl(0, 6) +disk_read(0, 2, 1) +get_fattime() +open res=0 +disk_ioctl(0, 6) +disk_write(0, 2, 1, 0xa8b3f35d) +disk_read(0, 1, 1) +write res=0 n=10 +disk_ioctl(0, 6) +disk_write(0, 34, 1, ) +get_fattime() +disk_write(0, 1, 1, 0x5343a9c5) +disk_read(0, 2, 1) +disk_write(0, 2, 1, 0x6ae708d5) +disk_ioctl(0, 0) +disk_ioctl(0, 6) +close res=0 +== FILE READ == +disk_ioctl(0, 6) +open res=0 +disk_ioctl(0, 6) +disk_read(0, 34, 1) +read res=0 n=10 +0000 74 65 73 74 20 66 69 6c 65 0a test file. +disk_ioctl(0, 6) +disk_ioctl(0, 6) +close res=0 +== STAT == +disk_ioctl(0, 6) +stat res=0 size=10 date=0 time=0 attrib=32 +== FILE CREATION, LONG NAME AND LOTS OF DATA == +disk_ioctl(0, 6) +get_fattime() +open res=0 +disk_ioctl(0, 6) +disk_write(0, 2, 1, 0xb1d034cb) +disk_read(0, 1, 1) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +disk_write(0, 35, 1, 0x4049ed30) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +write res=0 n=100 +disk_ioctl(0, 6) +disk_write(0, 36, 1, 0x37a6ca6c) +get_fattime() +disk_write(0, 1, 1, 0x7f57e755) +disk_read(0, 2, 1) +disk_write(0, 2, 1, 0xdd0a2fc3) +disk_ioctl(0, 0) +disk_ioctl(0, 6) +close res=0 +== FILE SEEK AND READ == +disk_ioctl(0, 6) +open res=0 +disk_ioctl(0, 6) +disk_read(0, 1, 1) +disk_read(0, 36, 1) +lseek res=0 +tell 800 +disk_ioctl(0, 6) +read res=0 n=100 +0000 4d 6f 72 65 20 64 61 74 61 20 66 6f 72 20 74 68 More data for th +0010 65 20 74 65 73 74 20 66 69 6c 65 2e 20 20 4e 65 e test file. Ne +0020 65 64 20 74 6f 20 68 61 76 65 20 65 6e 6f 75 67 ed to have enoug +0030 68 20 63 68 61 72 61 63 74 65 72 73 20 74 6f 20 h characters to +0040 66 69 6c 6c 20 6d 6f 72 65 20 74 68 61 6e 20 6f fill more than o +0050 6e 65 20 35 31 32 2d 62 79 74 65 20 73 65 63 74 ne 512-byte sect +0060 6f 72 2e 0a or.. +disk_ioctl(0, 6) +disk_ioctl(0, 6) +close res=0 +== MKDIR == +disk_ioctl(0, 6) +disk_read(0, 2, 1) +disk_read(0, 1, 1) +disk_write(0, 1, 1, 0xa5c7187a) +get_fattime() +disk_write(0, 37, 1, 0x2953772e) +disk_read(0, 2, 1) +disk_write(0, 2, 1, 0x55944b21) +disk_ioctl(0, 0) +mkdir res=0 +== DIRECTORY LISTING == +disk_ioctl(0, 6) +opendir res=0 +disk_ioctl(0, 6) +readdir res=0 size=10 name=/TEST.TXT/ lname=/test.txt/ +disk_ioctl(0, 6) +readdir res=0 size=1000 name=/FILENA~1.TXT/ lname=/filename-that-is-long.txt/ +disk_ioctl(0, 6) +readdir res=0 size=0 name=/DIR/ lname=/dir/ +disk_ioctl(0, 6) +disk_ioctl(0, 6) +closedir res=0 +== RENAME FILE == +disk_ioctl(0, 6) +disk_write(0, 2, 1, 0xcdb1e73c) +disk_ioctl(0, 0) +unlink res=0 +== UNLINK FILE == +disk_ioctl(0, 6) +disk_write(0, 2, 1, 0x12c8992d) +disk_read(0, 1, 1) +disk_write(0, 1, 1, 0xd19f436a) +disk_ioctl(0, 0) +unlink res=0 +== RENAME DIR == +disk_ioctl(0, 6) +disk_read(0, 2, 1) +disk_write(0, 2, 1, 0x2b759c33) +disk_ioctl(0, 0) +unlink res=0 +== UNLINK DIR == +disk_ioctl(0, 6) +disk_read(0, 37, 1) +disk_read(0, 2, 1) +disk_write(0, 2, 1, 0x09922d72) +disk_read(0, 1, 1) +disk_write(0, 1, 1, 0x61648e45) +disk_ioctl(0, 0) +unlink res=0 +== FREE SPACE == +disk_ioctl(0, 6) +getfree res=0 nclst=92 diff --git a/tests/fatfs1_conf.h b/tests/fatfs1_conf.h new file mode 100644 index 0000000..5c1ccc2 --- /dev/null +++ b/tests/fatfs1_conf.h @@ -0,0 +1,35 @@ +#define _FFCONF 88100 +#define _FS_READONLY 0 +#define _FS_MINIMIZE 0 +#define _USE_STRFUNC 0 +#define _USE_FIND 0 +#define _USE_MKFS 1 +#define _USE_FASTSEEK 0 +#define _USE_EXPAND 0 +#define _USE_CHMOD 1 +#define _USE_LABEL 1 +#define _USE_FORWARD 0 +#define _CODE_PAGE 437 +#define _USE_LFN 1 +#define _MAX_LFN 255 +#define _LFN_UNICODE 0 +#define _STRF_ENCODE 3 +#define _FS_RPATH 0 +#define _VOLUMES 1 +#define _STR_VOLUME_ID 0 +#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3" +#define _MULTI_PARTITION 0 +#define _MIN_SS 512 +#define _MAX_SS 512 +#define _USE_TRIM 0 +#define _FS_NOFSINFO 0 +#define _FS_TINY 0 +#define _FS_EXFAT 1 +#define _FS_NORTC 0 +#define _NORTC_MON 1 +#define _NORTC_MDAY 1 +#define _NORTC_YEAR 2015 +#define _FS_LOCK 0 +#define _FS_REENTRANT 0 +#define _FS_TIMEOUT 1000 +#define _SYNC_t HANDLE diff --git a/tests/util.c b/tests/util.c new file mode 100644 index 0000000..c90db10 --- /dev/null +++ b/tests/util.c @@ -0,0 +1,50 @@ +#include +#include + +#include "util.h" + +void hexdump(const uint8_t *buf, size_t len, size_t width) { + for (size_t i = 0; i < len; i += width) { + printf("%04x ", i); + size_t j; + for (j = i; j < len && j < i + width; ++j) { + printf("%02x ", buf[j]); + } + for (; j < i + width; ++j) { + printf(" "); + } + for (j = i; j < len && j < i + width; ++j) { + int c = buf[j]; + if (c < 32 || c > 126) { + c = '.'; + } + printf("%c", c); + } + printf("\n"); + } +} + +uint32_t hash_djb2(const uint8_t *data, size_t len) { + // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html + uint32_t hash = 5381; + for (const uint8_t *top = data + len; data < top; data++) { + hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data + } + return hash; +} + +void hashdump(const uint8_t *data, size_t len, size_t block_size, size_t width) { + const uint8_t *top = data + len; + for (size_t i = 0; data < top;) { + size_t n = top - data; + if (n > block_size) { + n = block_size; + } + printf("%08x ", hash_djb2(data, n)); + i += 1; + data += n; + if (i % width == 0 || data >= top) { + printf("\n"); + } + } +} diff --git a/tests/util.h b/tests/util.h new file mode 100644 index 0000000..5226bfc --- /dev/null +++ b/tests/util.h @@ -0,0 +1,5 @@ +#pragma once + +void hexdump(const uint8_t *buf, size_t len, size_t width); +uint32_t hash_djb2(const uint8_t *data, size_t len); +void hashdump(const uint8_t *data, size_t len, size_t block_size, size_t width);