37#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
41#error Static LFN work area cannot be used at thread-safe configuration
43#define ENTER_FF(fs) do { if (!lock_fs(fs)) return FR_TIMEOUT; } while (0)
44#define LEAVE_FF(fs, res) do { unlock_fs(fs, res); return res; } while (0)
47#define LEAVE_FF(fs, res) return (res)
50extern FATFS *
FatFs[FF_VOLUMES];
66 TCHAR keyword[FF_MAX_LFN + 1] = {0};
71 (
void)memset_s(keyword,
sizeof(keyword), 0,
sizeof(keyword));
73 for (len = 0; *path !=
'/' && *path !=
'\\' && *path !=
'\0' && len < FF_MAX_LFN; path++, len++) {
77 if (len == 0 || len > _MAX_ENTRYLENGTH) {
85 for (i = 0; i < fs->vir_amount; i++) {
86 if (!CHILDFS(fs, i)) {
89 if (
memcmp((CHILDFS(fs, i))->namelabel, keyword, _MAX_ENTRYLENGTH + 1) == 0) {
90 obj->fs = CHILDFS(fs, i);
103 TCHAR *label = (TCHAR *)path;
106 (
void)memset_s(&fs,
sizeof(fs), 0,
sizeof(fs));
109 res = create_name(&dj, &path);
111 if (res == FR_OK && dj.fn[11] == 0x20) {
112 res = FR_INVALID_NAME;
118 for (; *label !=
'\0'; label++) {
119 if (label - path > _MAX_ENTRYLENGTH) {
120 res = FR_INVALID_NAME;
123 if (*label ==
'/' || *label ==
'\\') {
124 res = FR_INVALID_NAME;
134 if (vol < 0 || vol >= FF_VOLUMES) {
144 if (fs->st_clst <= 2 || (fs->st_clst + fs->ct_clst) > fs->n_fatent) {
147 if (clust < 2 || clust > fs->n_fatent) {
150 if (clust >= (fs->st_clst + fs->ct_clst) || clust < fs->st_clst) {
173 if (fs->fs_type != FS_FAT32) {
174 return FR_INVAILD_FATFS;
183 clust = get_fat(&obj, clust);
184 if (clust == 0xFFFFFFFF) {
185 LEAVE_FF(fs, FR_DISK_ERR);
187 if (clust == 0x0FFFFFFF) {
190 if (clust < 2 || clust >= fs->n_fatent) {
191 LEAVE_FF(fs, FR_INT_ERR);
193 if (clust >= (fs->st_clst + fs->ct_clst) || clust < fs->st_clst) {
194 LEAVE_FF(fs, FR_CHAIN_ERR);
211 return FR_INVAILD_FATFS;
214 if (fs->vir_amount > _MAX_VIRVOLUMES) {
228 if (fs == NULL || ISCHILD(fs)) {
229 return FR_INVAILD_FATFS;
232 fs->vir_avail = FS_VIRDISABLE;
234 if (fs->child_fs != NULL) {
236 for (i = 0; i < fs->vir_amount; i++) {
237 if (CHILDFS(fs, i) != NULL) {
238 ff_memfree(CHILDFS(fs, i));
242 ff_memfree(fs->child_fs);
244 fs->vir_amount = 0xFFFFFFFF;
252 pfs->fs_type = fs->fs_type;
253 pfs->pdrv = fs->pdrv;
254 pfs->n_fats = fs->n_fats;
256 pfs->n_rootdir = fs->n_rootdir;
257 pfs->csize = fs->csize;
258#if FF_MAX_SS != FF_MIN_SS
259 pfs->ssize = fs->ssize;
261 pfs->sobj = fs->sobj;
266 pfs->n_fatent = fs->n_fatent;
267 pfs->fsize = fs->fsize;
268 pfs->volbase = fs->volbase;
269 pfs->fatbase = fs->fatbase;
270 pfs->dirbase = fs->dirbase;
271 pfs->database = fs->database;
272 pfs->last_clst = 0xFFFFFFFF;
273 pfs->free_clst = 0xFFFFFFFF;
274 pfs->st_clst = 0xFFFFFFFF;
275 pfs->ct_clst = 0xFFFFFFFF;
276 pfs->vir_flag = FS_CHILD;
277 pfs->vir_avail = FS_VIRENABLE;
278 pfs->parent_fs = (
void *)fs;
279 pfs->child_fs = (
void *)NULL;
301 if (fs == NULL || ISCHILD(fs)) {
302 return FR_INVAILD_FATFS;
305 if (fs->vir_amount > _MAX_VIRVOLUMES) {
309 fs->parent_fs = (
void *)fs;
311 fs->st_clst = 0xFFFFFFFF;
312 fs->ct_clst = 0xFFFFFFFF;
314 fs->child_fs = (
void **)ff_memalloc(fs->vir_amount *
sizeof(
void *));
315 if (fs->child_fs == NULL) {
316 return FR_NOT_ENOUGH_CORE;
318 fs->vir_avail = FS_VIRENABLE;
321 for (i = 0; i < fs->vir_amount; i++) {
322 pfs = ff_memalloc(
sizeof(FATFS));
327 *(fs->child_fs + i) = (
void *)pfs;
334 ff_memfree(*(fs->child_fs + i));
336 ff_memfree(fs->child_fs);
339 return FR_NOT_ENOUGH_CORE;
345 return FR_INVAILD_FATFS;
352 if (fs->fs_type != FS_FAT32 || ISPARENT(fs)) {
353 return FR_INVAILD_FATFS;
356 if (fs->st_clst < 3 || fs->st_clst >= fs->n_fatent) {
357 return FR_INVAILD_FATFS;
360 if (fs->ct_clst == 0 || fs->ct_clst > (fs->n_fatent - 3)) {
361 return FR_INVAILD_FATFS;
364 if ((fs->st_clst + fs->ct_clst) > fs->n_fatent || (fs->st_clst + fs->ct_clst) < 3) {
365 return FR_INVAILD_FATFS;
399 fs->free_clst = fs->ct_clst;
400 for (clst = fs->st_clst; clst < fs->st_clst + fs->ct_clst; clst++) {
401 link = get_fat(&obj, clst);
402 if (link == 0xFFFFFFFF) {
403 LEAVE_FF(fs, FR_DISK_ERR);
410 fs->last_clst = fs->st_clst - 1;
417 DWORD startBaseSect, countBaseSect;
419 countBaseSect = LD2PC(vol);
420 startBaseSect = LD2PS(vol);
423 if (ld_dword(work + VR_VertifyString) != 0x4C495445) {
427 if (work[VR_PartitionFSType] != fs->fs_type) {
431 if (ld_dword(work + VR_PartitionStSec) != startBaseSect) {
435 if (ld_dword(work + VR_PartitionCtSec) != countBaseSect) {
439 if (ld_word(work + VR_PartitionClstSz) != fs->csize) {
443 if (ld_dword(work + VR_PartitionCtClst) != fs->n_fatent) {
447 if (work[VR_PartitionCnt] > _MAX_VIRVOLUMES) {
456 if ((CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst < fs->n_fatent) {
457 fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
458 fs->ct_clst = fs->n_fatent - ((CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst);
459 }
else if ((CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst == fs->n_fatent) {
460 fs->st_clst = 0xFFFFFFFF;
461 fs->ct_clst = 0xFFFFFFFF;
474 if ((CHILDFS(fs, i))->st_clst != 3) {
480 if ((CHILDFS(fs, i))->st_clst != (CHILDFS(fs, (i - 1))->st_clst + CHILDFS(fs, (i - 1))->ct_clst)) {
491 (CHILDFS(fs, i))->st_clst = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_StartClust);
492 (CHILDFS(fs, i))->ct_clst = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_CountClust);
520 CHAR label[_MAX_ENTRYLENGTH + 1];
521 DWORD *labelTmp = NULL;
523 if (fs == NULL || (disk_status(fs->pdrv) & STA_NOINIT)) {
524 return FR_INVAILD_FATFS;
528 res = mount_volume(&path, &fs, FA_WRITE);
534 LEAVE_FF(fs, FR_INT_ERR);
537 virSect = fs->fatbase - 1;
541 work = (BYTE *)ff_memalloc(SS(fs));
543 LEAVE_FF(fs, FR_NOT_ENOUGH_CORE);
546 if (disk_read(pdrv, work, virSect, 1) != RES_OK) {
556 fs->vir_amount = work[VR_PartitionCnt];
562 for (i = 0; i < _MAX_VIRVOLUMES; i++) {
563 if (i < work[VR_PartitionCnt]) {
564 if (work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] != 0x80) {
570 if (work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] != 0x00) {
578 (
void)memset_s(label,
sizeof(label), 0,
sizeof(label));
580 tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 0);
581 labelTmp = (DWORD *)label;
583 tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 4);
584 *((DWORD * )(label + 4)) = tmp;
585 tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 8);
586 *((DWORD * )(label + 8)) = tmp;
587 tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 12);
588 *((DWORD * )(label + 12)) = tmp;
595 (
void)memcpy_s((CHILDFS(fs, i))->namelabel, _MAX_ENTRYLENGTH + 1, label, _MAX_ENTRYLENGTH + 1);
600 if ((QWORD)(CHILDFS(fs, i))->st_clst + (QWORD)((CHILDFS(fs, i))->ct_clst) > (QWORD)fs->n_fatent) {
610 if (i == (work[VR_PartitionCnt] - 1)) {
629 (CHILDFS(fs, i))->st_clst = 3;
630 (CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
633 fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
634 fs->ct_clst = fs->n_fatent - fs->st_clst;
635 }
else if (i != (fs->vir_amount - 1)) {
636 (CHILDFS(fs, i))->st_clst = (CHILDFS(fs, (i - 1)))->st_clst + (CHILDFS(fs, (i - 1)))->ct_clst;
637 (CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
640 (CHILDFS(fs, i))->st_clst = (CHILDFS(fs, (i - 1)))->st_clst + (CHILDFS(fs, (i - 1)))->ct_clst;
641 if (virpartper <= (1 + _FLOAT_ACC) && virpartper >= (1 - _FLOAT_ACC)) {
642 (CHILDFS(fs, i))->ct_clst = fs->n_fatent - (CHILDFS(fs, i))->st_clst;
643 fs->st_clst = 0xFFFFFFFF;
644 fs->ct_clst = 0xFFFFFFFF;
646 (CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
648 fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
649 fs->ct_clst = fs->n_fatent - fs->st_clst;
672 DWORD startBaseSect, countBaseSect;
674 CHAR label[_MAX_ENTRYLENGTH + 1];
675 DWORD *labelTmp = NULL;
681 if (fs == NULL || (disk_status(fs->pdrv) & STA_NOINIT)) {
682 return FR_INVAILD_FATFS;
686 res = mount_volume(&path, &fs, FA_WRITE);
693 LEAVE_FF(fs, FR_INVAILD_FATFS);
696 virSect = fs->fatbase - 1;
699 countBaseSect = LD2PC(vol);
700 startBaseSect = LD2PS(vol);
708 work = (BYTE *)ff_memalloc(SS(fs));
710 LEAVE_FF(fs, FR_NOT_ENOUGH_CORE);
715 (
void)memset_s(work, SS(fs), 0, SS(fs));
717 for (i = 0; i < fs->vir_amount; i++) {
719 (
void)memset_s(label,
sizeof(label), 0,
sizeof(label));
720 (
void)memcpy_s(label, _MAX_ENTRYLENGTH + 1,
g_fatVirPart.virtualinfo.virpartname[i], _MAX_ENTRYLENGTH + 1);
721 labelTmp = (DWORD *)label;
723 st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 0, tmp);
724 tmp = *((DWORD * )(label + 4));
725 st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 4, tmp);
726 tmp = *((DWORD * )(label + 8));
727 st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 8, tmp);
728 tmp = *((DWORD * )(label + 12));
729 st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 12, tmp);
731 virpartper +=
g_fatVirPart.virtualinfo.virpartpercent[i];
733 (
void)memcpy_s((CHILDFS(fs, i))->namelabel, _MAX_ENTRYLENGTH + 1,
g_fatVirPart.virtualinfo.virpartname[i],
734 _MAX_ENTRYLENGTH + 1);
736 (CHILDFS(fs, i))->last_clst = (CHILDFS(fs, i))->st_clst - 1;
737 work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] = 0x80;
741 work[VR_PartitionCnt] = fs->vir_amount;
742 work[VR_PartitionFSType] = fs->fs_type;
743 st_dword(work + VR_PartitionStSec, startBaseSect);
744 st_dword(work + VR_PartitionCtSec, countBaseSect);
745 st_word(work + VR_PartitionClstSz, fs->csize);
746 st_dword(work + VR_PartitionCtClst, fs->n_fatent);
747 for (i = 0; i < fs->vir_amount; i++) {
748 st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_StartClust,
749 (CHILDFS(fs, i))->st_clst);
750 st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_CountClust,
751 (CHILDFS(fs, i))->ct_clst);
755 st_dword(work + VR_VertifyString, 0x4C495445);
758 if (disk_write(pdrv, work, virSect, 1) != RES_OK) {
777 res = mount_volume(&path, &fs, 0);
787 if (res == FR_INT_ERR) {
795 LEAVE_FF(fs, FR_DENIED);
801 if (fs->free_clst > fs->ct_clst) {
803 fs->free_clst = fs->ct_clst;
804 for (clst = fs->st_clst; clst < fs->st_clst + fs->ct_clst; clst++) {
805 link = get_fat(&dj.obj, clst);
812 *nclst = fs->free_clst;
813 *cclst = fs->ct_clst;
817 if (fs->ct_clst == 0xFFFFFFFF) {
818 LEAVE_FF(fs, FR_DENIED);
820 for (i = 0; i < fs->vir_amount; i++) {
821 if (CHILDFS(fs, i)->free_clst > CHILDFS(fs, i)->ct_clst) {
822 dj.obj.fs = CHILDFS(fs, i);
823 CHILDFS(fs, i)->free_clst = CHILDFS(fs, i)->ct_clst;
824 for (clst = CHILDFS(fs, i)->st_clst; clst < CHILDFS(fs, i)->st_clst + CHILDFS(fs, i)->ct_clst; clst++) {
825 link = get_fat(&dj.obj, clst);
829 CHILDFS(fs, i)->free_clst--;
832 nfree += CHILDFS(fs, i)->free_clst;
834 *nclst = fs->free_clst - nfree;
835 *cclst = fs->ct_clst;
int memcmp(const void *str1, const void *str2, size_t n)
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
FRESULT f_checkvirpart(FATFS *fs, const TCHAR *path, BYTE vol)
FATFS * FatFs[FF_VOLUMES]
FRESULT f_checkname(const TCHAR *path)
static FRESULT FatfsCheckPercent(FATFS *fs, WORD i)
static void FatfsSetParentFs(FATFS *pfs, FATFS *fs)
FRESULT follow_virentry(FFOBJID *obj, const TCHAR *path)
static FRESULT FatfsCheckBoundParam(FATFS *fs, DWORD clust)
FATFS * f_getfatfs(int vol)
static void FatfsClacPartInfo(FATFS *fs, DOUBLE virpartper, UINT i)
FRESULT f_unregvirfs(FATFS *fs)
FRESULT f_getvirfree(const TCHAR *path, DWORD *nclst, DWORD *cclst)
static FRESULT FatfsCheckStart(BYTE *work, FATFS *fs, BYTE vol)
static FRESULT FatfsCheckScanFatParam(FATFS *fs)
FRESULT f_makevirpart(FATFS *fs, const TCHAR *path, BYTE vol)
static FRESULT FatfsCheckPartClst(FATFS *fs, WORD i)
static void FatfsSetChildClst(BYTE *work, FATFS *fs, WORD i)
FRESULT f_scanfat(FATFS *fs)
FRESULT f_regvirfs(FATFS *fs)
FRESULT f_disvirfs(FATFS *fs)
FRESULT f_boundary(FATFS *fs, DWORD clust)
FAT_VIR_PART g_fatVirPart