更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
virpartff.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "ffconf.h"
33#include "virpartff.h"
34#include "string.h"
35#include "diskio.h"
36
37#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
38
39#if FF_FS_REENTRANT
40#if FF_USE_LFN == 1
41#error Static LFN work area cannot be used at thread-safe configuration
42#endif
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)
45#else
46#define ENTER_FF(fs)
47#define LEAVE_FF(fs, res) return (res)
48#endif
49
50extern FATFS *FatFs[FF_VOLUMES];
51
52/*
53* follow_virentry:
54* Compare the top segment with the virtual partition entry and replace it to its CHILD FATFS
55*
56* Acceptable return vaule:
57* - FR_OK : The top segment matches one of the virtual partition entries, and the FATFS
58* has been replaced to the corresponding FATFS.
59* - FR_DENIED : The top segment does not matched any of the virtual partition entries, and
60* the FATFS has kept as it is. Or the virtual partition feature has been
61* switched down by any reason.
62* - FR_INT_ERR : Assertion error
63*/
64FRESULT follow_virentry(FFOBJID *obj, const TCHAR *path)
65{
66 TCHAR keyword[FF_MAX_LFN + 1] = {0};
67 FATFS *fs = obj->fs;
68 INT len;
69 UINT i;
70
71 (void)memset_s(keyword, sizeof(keyword), 0, sizeof(keyword));
72 /* Search and copy the first segment in path */
73 for (len = 0; *path != '/' && *path != '\\' && *path != '\0' && len < FF_MAX_LFN; path++, len++) {
74 keyword[len] = *path;
75 }
76
77 if (len == 0 || len > _MAX_ENTRYLENGTH) {
78 return FR_DENIED;
79 }
80
81 /*
82 * Compare the segment does match one for virtual partitions' entry or not,
83 * replace the FATFS if the result is positive
84 */
85 for (i = 0; i < fs->vir_amount; i++) {
86 if (!CHILDFS(fs, i)) {
87 return FR_INT_ERR;
88 }
89 if (memcmp((CHILDFS(fs, i))->namelabel, keyword, _MAX_ENTRYLENGTH + 1) == 0) {
90 obj->fs = CHILDFS(fs, i);
91 return FR_OK;
92 }
93 }
94
95 return FR_DENIED;
96}
97
98FRESULT f_checkname(const TCHAR *path)
99{
100 FRESULT res;
101 DIR dj;
102 FATFS fs;
103 TCHAR *label = (TCHAR *)path;
104 DEF_NAMBUF
105
106 (void)memset_s(&fs, sizeof(fs), 0, sizeof(fs));
107 dj.obj.fs = &fs;
108 INIT_NAMBUF(&fs);
109 res = create_name(&dj, &path);
110 /* the last byte of file name can't be a space */
111 if (res == FR_OK && dj.fn[11] == 0x20) {
112 res = FR_INVALID_NAME;
113 return res;
114 }
115
116 FREE_NAMBUF();
117
118 for (; *label != '\0'; label++) {
119 if (label - path > _MAX_ENTRYLENGTH) {
120 res = FR_INVALID_NAME;
121 return res;
122 }
123 if (*label == '/' || *label == '\\') {
124 res = FR_INVALID_NAME;
125 return res;
126 }
127 }
128 return res;
129}
130
131FATFS *f_getfatfs(int vol)
132{
133 FATFS *fs = NULL;
134 if (vol < 0 || vol >= FF_VOLUMES) {
135 fs = NULL;
136 } else {
137 fs = FatFs[vol];
138 }
139 return fs;
140}
141
142static FRESULT FatfsCheckBoundParam(FATFS *fs, DWORD clust)
143{
144 if (fs->st_clst <= 2 || (fs->st_clst + fs->ct_clst) > fs->n_fatent) {
145 return FR_INT_ERR;
146 }
147 if (clust < 2 || clust > fs->n_fatent) {
148 return FR_INT_ERR;
149 }
150 if (clust >= (fs->st_clst + fs->ct_clst) || clust < fs->st_clst) {
151 return FR_CHAIN_ERR;
152 }
153
154 return FR_OK;
155}
156
157/*
158* check_boundary:
159* Check the chain occupied more than one virtual partition or not start at the var 'clust'
160*
161* Acceptable Return Value:
162* - FR_OK : The chain occupied only one virtual parition
163* - FR_CHAIN_ERR : The chain occupied more than one virtual parition
164*/
165FRESULT f_boundary(FATFS *fs, DWORD clust)
166{
167 FFOBJID obj;
168 FRESULT res;
169 obj.fs = fs;
170 if (fs == NULL) {
171 return FR_INT_ERR;
172 }
173 if (fs->fs_type != FS_FAT32) {
174 return FR_INVAILD_FATFS;
175 }
176 ENTER_FF(fs);
177
178 res = FatfsCheckBoundParam(fs, clust);
179 if (res != FR_OK) {
180 LEAVE_FF(fs, res);
181 }
182 for (;;) {
183 clust = get_fat(&obj, clust);
184 if (clust == 0xFFFFFFFF) {
185 LEAVE_FF(fs, FR_DISK_ERR);
186 }
187 if (clust == 0x0FFFFFFF) {
188 break;
189 }
190 if (clust < 2 || clust >= fs->n_fatent) {
191 LEAVE_FF(fs, FR_INT_ERR);
192 }
193 if (clust >= (fs->st_clst + fs->ct_clst) || clust < fs->st_clst) {
194 LEAVE_FF(fs, FR_CHAIN_ERR);
195 }
196 }
197
198 LEAVE_FF(fs, FR_OK);
199}
200
201/*
202* f_unregvirfs:
203* Uninitialized the CHILD FATFS object
204*
205* Acceptable Return Value:
206* - FR_OK : Successfully initialized the CHILD FATFS object.
207*/
208FRESULT f_disvirfs(FATFS *fs)
209{
210 if (ISCHILD(fs)) {
211 return FR_INVAILD_FATFS;
212 }
213
214 if (fs->vir_amount > _MAX_VIRVOLUMES) {
215 return FR_INT_ERR;
216 }
217
218 ENTER_FF(fs);
219
220 (void)f_unregvirfs(fs);
221 LEAVE_FF(fs, FR_OK);
222}
223
224FRESULT f_unregvirfs(FATFS *fs)
225{
226 UINT i;
227
228 if (fs == NULL || ISCHILD(fs)) {
229 return FR_INVAILD_FATFS;
230 }
231
232 fs->vir_avail = FS_VIRDISABLE;
233 /* PARENT FATFS has linked to CHILD FATFS already */
234 if (fs->child_fs != NULL) {
235 /* Followed the CHILD FATFS and free the memory */
236 for (i = 0; i < fs->vir_amount; i++) {
237 if (CHILDFS(fs, i) != NULL) {
238 ff_memfree(CHILDFS(fs, i));
239 }
240 }
241 /* Free the 'child_fs' feild */
242 ff_memfree(fs->child_fs);
243 fs->child_fs = NULL;
244 fs->vir_amount = 0xFFFFFFFF;
245 }
246
247 return FR_OK;
248}
249
250static void FatfsSetParentFs(FATFS *pfs, FATFS *fs)
251{
252 pfs->fs_type = fs->fs_type; /* Copy the feild info from PARENT FATFS object */
253 pfs->pdrv = fs->pdrv;
254 pfs->n_fats = fs->n_fats;
255 pfs->id = fs->id;
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;
260#endif
261 pfs->sobj = fs->sobj;
262
263#if FF_FS_RPATH != 0
264 pfs->cdir = 0;
265#endif
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; /* Mark the 'last_clst' and 'free_clst' in CHILD FATFS is not been updated for now */
273 pfs->free_clst = 0xFFFFFFFF;
274 pfs->st_clst = 0xFFFFFFFF; /* Mark the 'st_clst' and 'ct_clst' in CHILD FATFS is not been update for now. */
275 pfs->ct_clst = 0xFFFFFFFF;
276 pfs->vir_flag = FS_CHILD; /* Mark the FATFS object is a CHILD */
277 pfs->vir_avail = FS_VIRENABLE; /* Mark the CHILD object is enable for now */
278 pfs->parent_fs = (void *)fs; /* Link to the PARENT object */
279 pfs->child_fs = (void *)NULL; /* Link the unrelated feild to NULL */
280}
281
282/*
283* f_regvirfs:
284* Initialized the CHILD FATFS object
285*
286* Acceptable Return Value:
287* - FR_OK : Successfully initialized the CHILD FATFS object.
288*
289* Others Return Value:
290* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
291* - FR_DENIED : The virtual partition feature has been shut down by switcher
292* - FR_DISK_ERR : A disk error happened
293* - FR_NOT_ENOUGH_CORE : Not enough memory for allocate space for CHILD FATFS
294* - FR_INVALID_PARAMETER : There is a invaild value in current setting
295*/
296FRESULT f_regvirfs(FATFS *fs)
297{
298 UINT i;
299 FATFS *pfs = NULL;
300
301 if (fs == NULL || ISCHILD(fs)) {
302 return FR_INVAILD_FATFS;
303 }
304
305 if (fs->vir_amount > _MAX_VIRVOLUMES) {
306 return FR_INT_ERR;
307 }
308
309 fs->parent_fs = (void *)fs; /* Relink to itself */
310 /* Mark the FATFS object is PARENT */
311 fs->st_clst = 0xFFFFFFFF;
312 fs->ct_clst = 0xFFFFFFFF;
313 /* Allocate a space for linking to the child FATFS */
314 fs->child_fs = (void **)ff_memalloc(fs->vir_amount * sizeof(void *));
315 if (fs->child_fs == NULL) {
316 return FR_NOT_ENOUGH_CORE;
317 }
318 fs->vir_avail = FS_VIRENABLE; /* Mark the PARENT object is enable for now */
319
320 /* Set the CHILD object field */
321 for (i = 0; i < fs->vir_amount; i++) {
322 pfs = ff_memalloc(sizeof(FATFS)); /* Allocate a memeory for current child FATFS object */
323 if (pfs == NULL) { /* If allocate failed, must call 'f_unregvirfs' to free the previous FATFS object memory */
324 goto ERROUT;
325 }
326 FatfsSetParentFs(pfs, fs);
327 *(fs->child_fs + i) = (void *)pfs;
328 }
329
330 return FR_OK;
331ERROUT:
332 while (i > 0) {
333 --i;
334 ff_memfree(*(fs->child_fs + i));
335 }
336 ff_memfree(fs->child_fs);
337 fs->child_fs = NULL;
338
339 return FR_NOT_ENOUGH_CORE;
340}
341
342static FRESULT FatfsCheckScanFatParam(FATFS *fs)
343{
344 if (fs == NULL) {
345 return FR_INVAILD_FATFS;
346 }
347
348 if (ISNORMAL(fs)) {
349 return FR_DENIED;
350 }
351
352 if (fs->fs_type != FS_FAT32 || ISPARENT(fs)) {
353 return FR_INVAILD_FATFS;
354 }
355
356 if (fs->st_clst < 3 || fs->st_clst >= fs->n_fatent) {
357 return FR_INVAILD_FATFS;
358 }
359
360 if (fs->ct_clst == 0 || fs->ct_clst > (fs->n_fatent - 3)) {
361 return FR_INVAILD_FATFS;
362 }
363
364 if ((fs->st_clst + fs->ct_clst) > fs->n_fatent || (fs->st_clst + fs->ct_clst) < 3) {
365 return FR_INVAILD_FATFS;
366 }
367
368 return FR_OK;
369}
370
371/*
372* f_scanfat:
373* Scan the FAT inside the boundary of CHILD FATFS limit, and update the free cluster and last cluster
374*
375* Acceptable Return Value:
376* - FR_OK : Successfully scaned the FAT and update field.
377*
378* Others Return Value:
379* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
380* - FR_DENIED : The virtual partition feature has been shut down by switcher
381* - FR_DISK_ERR : A disk error happened
382*/
383FRESULT f_scanfat(FATFS *fs)
384{
385 FRESULT res;
386 DWORD clst;
387 DWORD link;
388 FFOBJID obj;
389
390 res = FatfsCheckScanFatParam(fs);
391 if (res != FR_OK) {
392 return res;
393 }
394
395 ENTER_FF(fs);
396 res = FR_OK;
397 obj.fs = fs;
398
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);
404 }
405 if (link == 0) {
406 continue;
407 }
408 fs->free_clst--;
409 }
410 fs->last_clst = fs->st_clst - 1;
411
412 LEAVE_FF(fs, res);
413}
414
415static FRESULT FatfsCheckStart(BYTE *work, FATFS *fs, BYTE vol)
416{
417 DWORD startBaseSect, countBaseSect;
418
419 countBaseSect = LD2PC(vol); /* Volume Base Sectors Count */
420 startBaseSect = LD2PS(vol); /* Volume Base Start Sector */
421
422 /* Check ASCII for Keyword "LITE" */
423 if (ld_dword(work + VR_VertifyString) != 0x4C495445) {
424 return FR_NOVIRPART;
425 }
426 /* Check whether filesystem has been changed or not */
427 if (work[VR_PartitionFSType] != fs->fs_type) {
428 return FR_MODIFIED;
429 }
430 /* Check whether volume base sector has benn changed or not */
431 if (ld_dword(work + VR_PartitionStSec) != startBaseSect) {
432 return FR_MODIFIED;
433 }
434 /* Check whether volume base size hase been changed or not */
435 if (ld_dword(work + VR_PartitionCtSec) != countBaseSect) {
436 return FR_MODIFIED;
437 }
438 /* Check whether volume cluster size has been changed or not */
439 if (ld_word(work + VR_PartitionClstSz) != fs->csize) {
440 return FR_MODIFIED;
441 }
442 /* Check whether volume start cluster is cluster #3 or not */
443 if (ld_dword(work + VR_PartitionCtClst) != fs->n_fatent) {
444 return FR_MODIFIED;
445 }
446 /* Check whether virtual partition overlimit */
447 if (work[VR_PartitionCnt] > _MAX_VIRVOLUMES) {
448 return FR_MODIFIED;
449 }
450
451 return FR_OK;
452}
453
454static FRESULT FatfsCheckPercent(FATFS *fs, WORD i)
455{
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;
462 } else {
463 (void)f_unregvirfs(fs);
464 return FR_MODIFIED;
465 }
466
467 return FR_OK;
468}
469
470static FRESULT FatfsCheckPartClst(FATFS *fs, WORD i)
471{
472 if (i == 0) {
473 /* First virtual partition must start at cluster #3 */
474 if ((CHILDFS(fs, i))->st_clst != 3) {
475 (void)f_unregvirfs(fs);
476 return FR_MODIFIED;
477 }
478 } else {
479 /* Check whether the current virtual partition is closely next to the previous virtual partition */
480 if ((CHILDFS(fs, i))->st_clst != (CHILDFS(fs, (i - 1))->st_clst + CHILDFS(fs, (i - 1))->ct_clst)) {
481 (void)f_unregvirfs(fs);
482 return FR_MODIFIED;
483 }
484 }
485
486 return FR_OK;
487}
488
489static void FatfsSetChildClst(BYTE *work, FATFS *fs, WORD i)
490{
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);
493}
494
495/*
496* f_ckvtlpt :
497* Check the external SD virtual paritition sectors and read configure from it
498*
499* Acceptable Return Value:
500* - FR_OK : The external SD configure is complete, all info has been set to the
501* each CHILD FATFS
502* - FR_NOT_MATCHED : The virtual partition's configure does not matched as current setting
503* - FR_MODIFIED : The virtual partition's configure has been destoried partly or completely
504* - FR_NOVIRPART : The external SD has not been apllied as virtual partition yet
505*
506* Others Return Value:
507* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
508* - FR_DENIED : The virtual partition feature has been shut down by switcher
509* - FR_INVALID_DRIVE : The drive index is error
510* - FR_DISK_ERR : A Disk error happend
511*/
512FRESULT f_checkvirpart(FATFS *fs, const TCHAR *path, BYTE vol)
513{
514 FRESULT res;
515 WORD i;
516 DWORD virSect;
517 DWORD tmp;
518 BYTE pdrv;
519 BYTE *work = NULL;
520 CHAR label[_MAX_ENTRYLENGTH + 1];
521 DWORD *labelTmp = NULL; /* to clear the compilation warning */
522
523 if (fs == NULL || (disk_status(fs->pdrv) & STA_NOINIT)) {
524 return FR_INVAILD_FATFS; /* The object is invalid */
525 }
526
527 /* Lock the filesystem object */
528 res = mount_volume(&path, &fs, FA_WRITE); /* Update the filesystem info to the parent fs */
529 if (res != FR_OK) {
530 LEAVE_FF(fs, res);
531 }
532
533 if (ISCHILD(fs)) {
534 LEAVE_FF(fs, FR_INT_ERR);
535 }
536 /* Data will be save at the last reserve sector ,which is the front one of the fat base sector */
537 virSect = fs->fatbase - 1;
538
539 pdrv = LD2PD(vol); /* Driver index */
540
541 work = (BYTE *)ff_memalloc(SS(fs));
542 if (work == NULL) {
543 LEAVE_FF(fs, FR_NOT_ENOUGH_CORE);
544 }
545 /* Check and vertify partition information */
546 if (disk_read(pdrv, work, virSect, 1) != RES_OK) {
547 res = FR_DISK_ERR;
548 goto EXIT;
549 } /* Load VBR */
550
551 res = FatfsCheckStart(work, fs, vol);
552 if (res != FR_OK) {
553 goto EXIT;
554 }
555 /* Check the virtual parition amount if matched current setting or not */
556 fs->vir_amount = work[VR_PartitionCnt];
557 res = f_regvirfs(fs);
558 if (res != FR_OK) {
559 goto EXIT;
560 }
561
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) {
565 (void)f_unregvirfs(fs);
566 res = FR_MODIFIED;
567 goto EXIT;
568 }
569 } else {
570 if (work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] != 0x00) {
571 (void)f_unregvirfs(fs);
572 res = FR_MODIFIED;
573 goto EXIT;
574 }
575 break;
576 }
577
578 (void)memset_s(label, sizeof(label), 0, sizeof(label));
579
580 tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 0);
581 labelTmp = (DWORD *)label;
582 *labelTmp = tmp;
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;
589
590 if (f_checkname(label) != FR_OK) {
591 (void)f_unregvirfs(fs);
592 res = FR_MODIFIED;
593 goto EXIT;
594 }
595 (void)memcpy_s((CHILDFS(fs, i))->namelabel, _MAX_ENTRYLENGTH + 1, label, _MAX_ENTRYLENGTH + 1);
596
597 FatfsSetChildClst(work, fs, i);
598
599 /* External SD setting has overlimit the whole partition cluster amount */
600 if ((QWORD)(CHILDFS(fs, i))->st_clst + (QWORD)((CHILDFS(fs, i))->ct_clst) > (QWORD)fs->n_fatent) {
601 (void)f_unregvirfs(fs);
602 res = FR_MODIFIED;
603 goto EXIT;
604 }
605
606 res = FatfsCheckPartClst(fs, i);
607 if (res != FR_OK) {
608 goto EXIT;
609 }
610 if (i == (work[VR_PartitionCnt] - 1)) {
611 /*
612 * If the external SD virtual partition percent exceeds the error tolerance based on current virtual
613 * partition percent setting
614 */
615 res = FatfsCheckPercent(fs, i);
616 if (res != FR_OK) {
617 goto EXIT;
618 }
619 }
620 }
621EXIT:
622 ff_memfree(work);
623 LEAVE_FF(fs, res);
624}
625
626static void FatfsClacPartInfo(FATFS *fs, DOUBLE virpartper, UINT i)
627{
628 if (i == 0) {
629 (CHILDFS(fs, i))->st_clst = 3;
630 (CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
631 g_fatVirPart.virtualinfo.virpartpercent[i]);
632
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) *
638 g_fatVirPart.virtualinfo.virpartpercent[i]);
639 } else {
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;
645 } else {
646 (CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
647 g_fatVirPart.virtualinfo.virpartpercent[i]);
648 fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
649 fs->ct_clst = fs->n_fatent - fs->st_clst;
650 }
651 }
652}
653
654/*
655* f_mkvtlpt:
656* Apply the current virtual partition's setting to external SD card and to the CHILD FATFS
657*
658* Acceptable Return Value:
659* - FR_OK : Successfully applied current setting to external SD card and
660* CHILD FATFS
661*
662* Others Return Value :
663* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
664* - FR_DENIED : The virtual partition feature has been shut down by switcher
665* - FR_INVALID_DRIVE : The drive index is error
666* - FR_DISK_ERR : A Disk error happend
667*/
668FRESULT f_makevirpart(FATFS *fs, const TCHAR *path, BYTE vol)
669{
670 FRESULT res;
671 DWORD virSect;
672 DWORD startBaseSect, countBaseSect;
673 DWORD tmp;
674 CHAR label[_MAX_ENTRYLENGTH + 1];
675 DWORD *labelTmp = NULL; /* to clear the compilation warning */
676 UINT i;
677 BYTE pdrv;
678 BYTE *work = NULL;
679 DOUBLE virpartper = 0.0;
680
681 if (fs == NULL || (disk_status(fs->pdrv) & STA_NOINIT)) {
682 return FR_INVAILD_FATFS; /* The object is invalid */
683 }
684
685 /* Lock the filesystem object */
686 res = mount_volume(&path, &fs, FA_WRITE); /* Update the filesystem info to the parent fs */
687 if (res != FR_OK) {
688 LEAVE_FF(fs, res);
689 }
690
691 /* Only available in FAT32 filesystem */
692 if (ISCHILD(fs)) {
693 LEAVE_FF(fs, FR_INVAILD_FATFS);
694 }
695 /* Data will be save at the last reserve sector,which is the front one of the fat base sector */
696 virSect = fs->fatbase - 1;
697 /* Search the fs index, which same as the volume index */
698 pdrv = LD2PD(vol); /* Driver index */
699 countBaseSect = LD2PC(vol); /* Volume Base Sectors Count */
700 startBaseSect = LD2PS(vol); /* Volume Base Start Sector */
701
702 fs->vir_amount = g_fatVirPart.virtualinfo.virpartnum;
703 res = f_regvirfs(fs);
704 if (res != FR_OK) {
705 LEAVE_FF(fs, res);
706 }
707
708 work = (BYTE *)ff_memalloc(SS(fs));
709 if (work == NULL) {
710 LEAVE_FF(fs, FR_NOT_ENOUGH_CORE);
711 }
712 /* Data Cluster is begin from the Cluster #3 to the last cluster */
713 /* Cluster #0 #1 is for VBR, reserve sectors and fat */
714 /* Cluster #2 is for root directory */
715 (void)memset_s(work, SS(fs), 0, SS(fs));
716
717 for (i = 0; i < fs->vir_amount; i++) {
718 /* Copy the Entry label and write to work sector's buffer */
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;
722 tmp = *labelTmp;
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);
730
731 virpartper += g_fatVirPart.virtualinfo.virpartpercent[i];
732
733 (void)memcpy_s((CHILDFS(fs, i))->namelabel, _MAX_ENTRYLENGTH + 1, g_fatVirPart.virtualinfo.virpartname[i],
734 _MAX_ENTRYLENGTH + 1);
735 FatfsClacPartInfo(fs, virpartper, i);
736 (CHILDFS(fs, i))->last_clst = (CHILDFS(fs, i))->st_clst - 1;
737 work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] = 0x80;
738 }
739
740 /* Set the data to sector */
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);
752 }
753
754 /* ASCII for Keyword "LITE" */
755 st_dword(work + VR_VertifyString, 0x4C495445);
756
757 /* Write into the data area */
758 if (disk_write(pdrv, work, virSect, 1) != RES_OK) {
759 (void)f_unregvirfs(fs);
760 res = FR_DISK_ERR;
761 }
762
763 ff_memfree(work);
764 LEAVE_FF(fs, res);
765}
766
767FRESULT f_getvirfree(const TCHAR *path, DWORD *nclst, DWORD *cclst)
768{
769 FATFS *fs = NULL;
770 FRESULT res;
771 DWORD clst, link;
772 DWORD nfree;
773 UINT i;
774 DIR dj;
775
776 /* Find volume to Update the global FSINFO */
777 res = mount_volume(&path, &fs, 0);
778 if (res != FR_OK) {
779 LEAVE_FF(fs, res);
780 }
781
782 /* Following the entry keyword, decide to replace the PARENT FATFS to CHILD FATFS or not */
783 dj.obj.fs = fs;
784 if (ISVIRPART(fs)) {
785 /* Check the virtual partition top directory, and match the virtual fs */
786 res = follow_virentry(&dj.obj, path);
787 if (res == FR_INT_ERR) {
788 LEAVE_FF(fs, res);
789 }
790 if (res == FR_OK) {
791 fs = dj.obj.fs;
792 }
793 } else {
794 /* Virtual Partition Feature was off, deny this operation */
795 LEAVE_FF(fs, FR_DENIED);
796 }
797
798 /* If current FATFS is a CHILD FATFS */
799 if (ISCHILD(fs)) {
800 /* If CHILD FATFS' free_clst is invaild, the scan the FAT and update it */
801 if (fs->free_clst > fs->ct_clst) {
802 dj.obj.fs = fs;
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);
806 if (link == 0) {
807 continue;
808 }
809 fs->free_clst--;
810 }
811 }
812 *nclst = fs->free_clst;
813 *cclst = fs->ct_clst;
814 LEAVE_FF(fs, FR_OK);
815 } else {
816 nfree = 0;
817 if (fs->ct_clst == 0xFFFFFFFF) {
818 LEAVE_FF(fs, FR_DENIED);
819 }
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);
826 if (link == 0) {
827 continue;
828 }
829 CHILDFS(fs, i)->free_clst--;
830 }
831 }
832 nfree += CHILDFS(fs, i)->free_clst;
833 }
834 *nclst = fs->free_clst - nfree;
835 *cclst = fs->ct_clst;
836 LEAVE_FF(fs, FR_OK);
837 }
838}
839#endif
double DOUBLE
Definition: los_typedef.h:62
char CHAR
Definition: los_typedef.h:63
int memcmp(const void *str1, const void *str2, size_t n)
Definition: memcmp.c:37
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)
Definition: virpartff.c:512
FATFS * FatFs[FF_VOLUMES]
FRESULT f_checkname(const TCHAR *path)
Definition: virpartff.c:98
static FRESULT FatfsCheckPercent(FATFS *fs, WORD i)
Definition: virpartff.c:454
static void FatfsSetParentFs(FATFS *pfs, FATFS *fs)
Definition: virpartff.c:250
FRESULT follow_virentry(FFOBJID *obj, const TCHAR *path)
Definition: virpartff.c:64
static FRESULT FatfsCheckBoundParam(FATFS *fs, DWORD clust)
Definition: virpartff.c:142
FATFS * f_getfatfs(int vol)
Definition: virpartff.c:131
static void FatfsClacPartInfo(FATFS *fs, DOUBLE virpartper, UINT i)
Definition: virpartff.c:626
FRESULT f_unregvirfs(FATFS *fs)
Definition: virpartff.c:224
FRESULT f_getvirfree(const TCHAR *path, DWORD *nclst, DWORD *cclst)
Definition: virpartff.c:767
static FRESULT FatfsCheckStart(BYTE *work, FATFS *fs, BYTE vol)
Definition: virpartff.c:415
static FRESULT FatfsCheckScanFatParam(FATFS *fs)
Definition: virpartff.c:342
FRESULT f_makevirpart(FATFS *fs, const TCHAR *path, BYTE vol)
Definition: virpartff.c:668
static FRESULT FatfsCheckPartClst(FATFS *fs, WORD i)
Definition: virpartff.c:470
static void FatfsSetChildClst(BYTE *work, FATFS *fs, WORD i)
Definition: virpartff.c:489
FRESULT f_scanfat(FATFS *fs)
Definition: virpartff.c:383
FRESULT f_regvirfs(FATFS *fs)
Definition: virpartff.c:296
FRESULT f_disvirfs(FATFS *fs)
Definition: virpartff.c:208
FRESULT f_boundary(FATFS *fs, DWORD clust)
Definition: virpartff.c:165
FAT_VIR_PART g_fatVirPart