1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-09-21
13 * Description: littlefs适配层代码
14 */
15 #define _GNU_SOURCE 1
16 #include "lfs_adapter.h"
17 #include "prt_fs.h"
18 #include "vfs_files.h"
19 #include "vfs_operations.h"
20 #include "vfs_partition.h"
21 #include "vfs_maps.h"
22 #include "vfs_mount.h"
23 #include "securec.h"
24
25 static pthread_mutex_t g_fsLocalMutex = PTHREAD_MUTEX_INITIALIZER;
26
27 static struct PartitionCfg g_partitionCfg;
28 static struct TagDeviceDesc *g_lfsDevice;
29
OsLfsGetStartAddr(S32 partition)30 static uintptr_t OsLfsGetStartAddr(S32 partition)
31 {
32 if (g_lfsDevice == NULL) {
33 struct TagDeviceDesc *device = NULL;
34 for (device = OsGetDeviceList(); device != NULL; device = device->dNext) {
35 if (strcmp(device->dFsType, "littlefs") == 0) {
36 g_lfsDevice = device;
37 break;
38 }
39 }
40 }
41
42 if ((g_lfsDevice == NULL) || (partition >= g_lfsDevice->dPartNum)) {
43 return INVALID_DEVICE_ADDR;
44 }
45
46 return g_lfsDevice->dAddrArray[partition];
47 }
48
OsLfsBlockRead(const struct lfs_config * c,lfs_block_t block,lfs_off_t off,void * dst,lfs_size_t size)49 static S32 OsLfsBlockRead(const struct lfs_config *c, lfs_block_t block,
50 lfs_off_t off, void *dst, lfs_size_t size)
51 {
52 uintptr_t startAddr = OsLfsGetStartAddr((S32)c->context);
53 if (startAddr == INVALID_DEVICE_ADDR) {
54 return -1;
55 }
56 startAddr += (c->block_size * block + off);
57 return (g_partitionCfg.readFunc)((S32)c->context, startAddr, dst, size);
58 }
59
OsLfsBlockWrite(const struct lfs_config * c,lfs_block_t block,lfs_off_t off,const void * dst,lfs_size_t size)60 static S32 OsLfsBlockWrite(const struct lfs_config *c, lfs_block_t block,
61 lfs_off_t off, const void *dst, lfs_size_t size)
62 {
63 uintptr_t startAddr = OsLfsGetStartAddr((S32)c->context);
64 if (startAddr == INVALID_DEVICE_ADDR) {
65 return -1;
66 }
67
68 startAddr += (c->block_size * block + off);
69 return (g_partitionCfg.writeFunc)((S32)c->context, startAddr, dst, size);
70 }
71
OsLfsBlockErase(const struct lfs_config * c,lfs_block_t block)72 static S32 OsLfsBlockErase(const struct lfs_config *c, lfs_block_t block)
73 {
74 uintptr_t startAddr = OsLfsGetStartAddr((S32)c->context);
75 if (startAddr == INVALID_DEVICE_ADDR) {
76 return -1;
77 }
78
79 startAddr += (c->block_size * block);
80 return (g_partitionCfg.eraseFunc)((S32)c->context, startAddr, c->block_size);
81 }
82
OsLfsBlockSync(const struct lfs_config * c)83 static S32 OsLfsBlockSync(const struct lfs_config *c)
84 {
85 (void)c;
86 return 0;
87 }
88
OsConvertFlagToLfsOpenFlag(S32 oflags)89 static S32 OsConvertFlagToLfsOpenFlag(S32 oflags)
90 {
91 S32 lfsOpenFlag = 0;
92
93 if (oflags & O_CREAT) {
94 lfsOpenFlag |= LFS_O_CREAT;
95 }
96
97 if (oflags & O_EXCL) {
98 lfsOpenFlag |= LFS_O_EXCL;
99 }
100
101 if (oflags & O_TRUNC) {
102 lfsOpenFlag |= LFS_O_TRUNC;
103 }
104
105 if (oflags & O_APPEND) {
106 lfsOpenFlag |= LFS_O_APPEND;
107 }
108
109 if (oflags & O_RDWR) {
110 lfsOpenFlag |= LFS_O_RDWR;
111 }
112
113 if (oflags & O_WRONLY) {
114 lfsOpenFlag |= LFS_O_WRONLY;
115 }
116
117 if (oflags == O_RDONLY) {
118 lfsOpenFlag |= LFS_O_RDONLY;
119 }
120
121 return lfsOpenFlag;
122 }
123
OsLfsErrno(S32 result)124 static S32 OsLfsErrno(S32 result)
125 {
126 return (result < 0) ? -result : result;
127 }
128
OsLfsConfigAdapter(struct PartitionCfg * pCfg,struct lfs_config * lfsCfg)129 static void OsLfsConfigAdapter(struct PartitionCfg *pCfg, struct lfs_config *lfsCfg)
130 {
131 lfsCfg->context = (void *)pCfg->partNo;
132
133 lfsCfg->read_size = pCfg->readSize;
134 lfsCfg->prog_size = pCfg->writeSize;
135 lfsCfg->cache_size = pCfg->cacheSize;
136 lfsCfg->block_cycles = pCfg->blockCycles;
137 lfsCfg->lookahead_size = pCfg->lookaheadSize;
138 lfsCfg->block_size = pCfg->blockSize;
139 lfsCfg->block_count = pCfg->blockCount;
140
141 lfsCfg->read = OsLfsBlockRead;
142 lfsCfg->prog = OsLfsBlockWrite;
143 lfsCfg->erase = OsLfsBlockErase;
144 lfsCfg->sync = OsLfsBlockSync;
145
146 g_partitionCfg.readFunc = pCfg->readFunc;
147 g_partitionCfg.writeFunc = pCfg->writeFunc;
148 g_partitionCfg.eraseFunc = pCfg->eraseFunc;
149 }
150
OsLfsMount(struct TagMountPoint * mp,uintptr_t mountflags,const void * data)151 static S32 OsLfsMount(struct TagMountPoint *mp, uintptr_t mountflags, const void *data)
152 {
153 S32 ret;
154 S32 size;
155 lfs_t *mountHdl = NULL;
156 struct lfs_config *cfg = NULL;
157
158 if ((mp == NULL) || (mp->mPath == NULL) || (data == NULL)) {
159 errno = EFAULT;
160 return FS_NOK;
161 }
162
163 size = sizeof(lfs_t) + sizeof(struct lfs_config);
164 mountHdl = (lfs_t *)malloc(size);
165 if (mountHdl == NULL) {
166 errno = ENODEV;
167 return FS_NOK;
168 }
169 if (memset_s(mountHdl, size, 0, size) != EOK) {
170 free(mountHdl);
171 errno = EBADF;
172 return FS_NOK;
173 }
174 mp->mData = (void *)mountHdl;
175 cfg = (struct lfs_config *)((uintptr_t)mountHdl + sizeof(lfs_t));
176
177 OsLfsConfigAdapter((struct PartitionCfg *)data, cfg);
178
179 ret = lfs_mount((lfs_t *)mp->mData, cfg);
180 if (ret != 0) {
181 ret = lfs_format((lfs_t *)mp->mData, cfg);
182 if (ret == 0) {
183 ret = lfs_mount((lfs_t *)mp->mData, cfg);
184 }
185 }
186 if (ret != 0) {
187 free(mountHdl);
188 errno = OsLfsErrno(ret);
189 return FS_NOK;
190 }
191 return ret;
192 }
193
OsLfsUmount(struct TagMountPoint * mp)194 static S32 OsLfsUmount(struct TagMountPoint *mp)
195 {
196 S32 ret;
197
198 if (mp == NULL) {
199 errno = EFAULT;
200 return FS_NOK;
201 }
202
203 if (mp->mData == NULL) {
204 errno = ENOENT;
205 return FS_NOK;
206 }
207
208 ret = lfs_unmount((lfs_t *)mp->mData);
209 if (ret != 0) {
210 errno = OsLfsErrno(ret);
211 ret = FS_NOK;
212 }
213
214 free(mp->mData);
215 mp->mData = NULL;
216 return ret;
217 }
218
OsLfsUnlink(struct TagMountPoint * mp,const char * fileName)219 static S32 OsLfsUnlink(struct TagMountPoint *mp, const char *fileName)
220 {
221 S32 ret;
222
223 if ((mp == NULL) || (fileName == NULL)) {
224 errno = EFAULT;
225 return FS_NOK;
226 }
227
228 if (mp->mData == NULL) {
229 errno = ENOENT;
230 return FS_NOK;
231 }
232
233 ret = lfs_remove((lfs_t *)mp->mData, fileName);
234 if (ret != 0) {
235 errno = OsLfsErrno(ret);
236 ret = FS_NOK;
237 }
238
239 return ret;
240 }
241
OsLfsMkdir(struct TagMountPoint * mp,const char * dirName)242 static S32 OsLfsMkdir(struct TagMountPoint *mp, const char *dirName)
243 {
244 S32 ret;
245
246 if ((dirName == NULL) || (mp == NULL)) {
247 errno = EFAULT;
248 return FS_NOK;
249 }
250
251 if (mp->mData == NULL) {
252 errno = ENOENT;
253 return FS_NOK;
254 }
255
256 lfs_t *lfs = (lfs_t *)mp->mData;
257
258 ret = lfs_mkdir(lfs, dirName);
259 if (ret != 0) {
260 errno = OsLfsErrno(ret);
261 ret = FS_NOK;
262 }
263
264 return ret;
265 }
266
OsLfsRmdir(struct TagMountPoint * mp,const char * dirName)267 static S32 OsLfsRmdir(struct TagMountPoint *mp, const char *dirName)
268 {
269 S32 ret;
270 lfs_t *lfs = NULL;
271
272 if (mp == NULL) {
273 errno = EFAULT;
274 return FS_NOK;
275 }
276
277 if (mp->mData == NULL) {
278 errno = ENOENT;
279 return FS_NOK;
280 }
281
282 if (dirName == NULL) {
283 errno = EFAULT;
284 return FS_NOK;
285 }
286
287 lfs = (lfs_t *)mp->mData;
288 ret = lfs_remove(lfs, dirName);
289 if (ret != 0) {
290 errno = OsLfsErrno(ret);
291 ret = FS_NOK;
292 }
293 return ret;
294 }
295
OsLfsOpendir(struct TagDir * dir,const char * dirName)296 static S32 OsLfsOpendir(struct TagDir *dir, const char *dirName)
297 {
298 S32 ret;
299
300 if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) {
301 errno = EFAULT;
302 return FS_NOK;
303 }
304
305 lfs_t *lfs = (lfs_t *)dir->dMp->mData;
306 lfs_dir_t *dirInfo = (lfs_dir_t *)malloc(sizeof(lfs_dir_t));
307 if (dirInfo == NULL) {
308 errno = ENOMEM;
309 return FS_NOK;
310 }
311 if (memset_s(dirInfo, sizeof(lfs_dir_t), 0, sizeof(lfs_dir_t)) != EOK) {
312 free(dirInfo);
313 errno = EBADF;
314 return FS_NOK;
315 }
316
317 ret = lfs_dir_open(lfs, dirInfo, dirName);
318 if (ret != 0) {
319 free(dirInfo);
320 errno = OsLfsErrno(ret);
321 return FS_NOK;
322 }
323
324 dir->dData = dirInfo;
325 dir->dOffset = 0;
326 return FS_OK;
327 }
328
OsLfsReaddir(struct TagDir * dir,struct dirent * dent)329 static S32 OsLfsReaddir(struct TagDir *dir, struct dirent *dent)
330 {
331 S32 ret;
332 struct lfs_info lfsInfo;
333
334 if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL) ||
335 (dent == NULL)) {
336 errno = EFAULT;
337 return FS_NOK;
338 }
339
340 if (dir->dData == NULL) {
341 errno = EBADF;
342 return FS_NOK;
343 }
344
345 lfs_t *lfs = (lfs_t *)dir->dMp->mData;
346 lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData;
347
348 ret = lfs_dir_read(lfs, dirInfo, &lfsInfo);
349 if (ret == TRUE) {
350 pthread_mutex_lock(&g_fsLocalMutex);
351 (void)strncpy_s(dent->d_name, sizeof(dent->d_name), lfsInfo.name, strlen(lfsInfo.name) + 1);
352 if (lfsInfo.type == LFS_TYPE_DIR) {
353 dent->d_type = DT_DIR;
354 } else if (lfsInfo.type == LFS_TYPE_REG) {
355 dent->d_type = DT_REG;
356 }
357
358 dent->d_reclen = lfsInfo.size;
359 pthread_mutex_unlock(&g_fsLocalMutex);
360
361 return FS_OK;
362 }
363
364 if (ret != 0) {
365 errno = OsLfsErrno(ret);
366 }
367
368 return FS_NOK;
369 }
370
OsLfsClosedir(struct TagDir * dir)371 static S32 OsLfsClosedir(struct TagDir *dir)
372 {
373 S32 ret;
374
375 if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) {
376 errno = EFAULT;
377 return FS_NOK;
378 }
379
380 if (dir->dData == NULL) {
381 errno = EBADF;
382 return FS_NOK;
383 }
384
385 lfs_t *lfs = (lfs_t *)dir->dMp->mData;
386 lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData;
387
388 ret = lfs_dir_close(lfs, dirInfo);
389 if (ret != 0) {
390 errno = OsLfsErrno(ret);
391 ret = FS_NOK;
392 }
393
394 free(dirInfo);
395 dir->dData = NULL;
396
397 return ret;
398 }
399
OsLfsOpen(struct TagFile * file,const char * pathName,S32 openFlag)400 static S32 OsLfsOpen(struct TagFile *file, const char *pathName, S32 openFlag)
401 {
402 S32 ret;
403 lfs_file_t *lfsHandle = NULL;
404
405 if ((pathName == NULL) || (file == NULL) || (file->fMp == NULL) ||
406 (file->fMp->mData == NULL)) {
407 errno = EFAULT;
408 return FS_NOK;
409 }
410
411 lfsHandle = (lfs_file_t *)malloc(sizeof(lfs_file_t));
412 if (lfsHandle == NULL) {
413 errno = ENOMEM;
414 return FS_NOK;
415 }
416
417 S32 lfsOpenFlag = OsConvertFlagToLfsOpenFlag(openFlag);
418 ret = lfs_file_open((lfs_t *)file->fMp->mData, lfsHandle, pathName, lfsOpenFlag);
419 if (ret != 0) {
420 free(lfsHandle);
421 errno = OsLfsErrno(ret);
422 return INVALID_FD;
423 }
424
425 file->fData = (void *)lfsHandle;
426 return ret;
427 }
428
OsLfsRead(struct TagFile * file,char * buf,size_t len)429 static S32 OsLfsRead(struct TagFile *file, char *buf, size_t len)
430 {
431 S32 ret;
432 struct TagMountPoint *mp = NULL;
433 lfs_file_t *lfsHandle = NULL;
434
435 if (buf == NULL) {
436 errno = EFAULT;
437 return FS_NOK;
438 }
439
440 if ((file == NULL) || (file->fData == NULL)) {
441 errno = EBADF;
442 return FS_NOK;
443 }
444
445 lfsHandle = (lfs_file_t *)file->fData;
446 mp = file->fMp;
447 if ((mp == NULL) || (mp->mData == NULL)) {
448 errno = EFAULT;
449 return FS_NOK;
450 }
451
452 ret = lfs_file_read((lfs_t *)mp->mData, lfsHandle, buf, len);
453 if (ret < 0) {
454 errno = OsLfsErrno(ret);
455 ret = FS_NOK;
456 }
457 return ret;
458 }
459
OsLfsWrite(struct TagFile * file,const char * buf,size_t len)460 static S32 OsLfsWrite(struct TagFile *file, const char *buf, size_t len)
461 {
462 S32 ret;
463 struct TagMountPoint *mp = NULL;
464 lfs_file_t *lfsHandle = NULL;
465
466 if (buf == NULL) {
467 errno = EFAULT;
468 return FS_NOK;
469 }
470
471 if ((file == NULL) || (file->fData == NULL)) {
472 errno = EBADF;
473 return FS_NOK;
474 }
475
476 lfsHandle = (lfs_file_t *)file->fData;
477 mp = file->fMp;
478 if ((mp == NULL) || (mp->mData == NULL)) {
479 errno = EFAULT;
480 return FS_NOK;
481 }
482
483 ret = lfs_file_write((lfs_t *)mp->mData, lfsHandle, buf, len);
484 if (ret < 0) {
485 errno = OsLfsErrno(ret);
486 ret = FS_NOK;
487 }
488 return ret;
489 }
490
OsLfsSeek(struct TagFile * file,off_t offset,S32 whence)491 static off_t OsLfsSeek(struct TagFile *file, off_t offset, S32 whence)
492 {
493 off_t ret;
494 struct TagMountPoint *mp = NULL;
495 lfs_file_t *lfsHandle = NULL;
496
497 if ((file == NULL) || (file->fData == NULL)) {
498 errno = EBADF;
499 return (off_t)FS_NOK;
500 }
501
502 lfsHandle = (lfs_file_t *)file->fData;
503 mp = file->fMp;
504 if ((mp == NULL) || (mp->mData == NULL)) {
505 errno = EFAULT;
506 return (off_t)FS_NOK;
507 }
508
509 ret = (off_t)lfs_file_seek((lfs_t *)mp->mData, lfsHandle, offset, whence);
510 if (ret < 0) {
511 errno = OsLfsErrno(ret);
512 ret = (off_t)FS_NOK;
513 }
514
515 return ret;
516 }
517
OsLfsClose(struct TagFile * file)518 static S32 OsLfsClose(struct TagFile *file)
519 {
520 S32 ret;
521 struct TagMountPoint *mp = NULL;
522 lfs_file_t *lfsHandle = NULL;
523
524 if ((file == NULL) || (file->fData == NULL)) {
525 errno = EBADF;
526 return FS_NOK;
527 }
528
529 lfsHandle = (lfs_file_t *)file->fData;
530 mp = file->fMp;
531 if ((mp == NULL) || (mp->mData == NULL)) {
532 errno = EFAULT;
533 return FS_NOK;
534 }
535
536 pthread_mutex_lock(&g_fsLocalMutex);
537 ret = lfs_file_close((lfs_t *)mp->mData, lfsHandle);
538 pthread_mutex_unlock(&g_fsLocalMutex);
539
540 if (ret != 0) {
541 errno = OsLfsErrno(ret);
542 ret = FS_NOK;
543 }
544
545 free(file->fData);
546 file->fData = NULL;
547 return ret;
548 }
549
OsLfsRename(struct TagMountPoint * mp,const char * oldName,const char * newName)550 static S32 OsLfsRename(struct TagMountPoint *mp, const char *oldName, const char *newName)
551 {
552 S32 ret;
553
554 if ((mp == NULL) || (oldName == NULL) || (newName == NULL)) {
555 errno = EFAULT;
556 return FS_NOK;
557 }
558
559 if (mp->mData == NULL) {
560 errno = ENOENT;
561 return FS_NOK;
562 }
563
564 ret = lfs_rename((lfs_t *)mp->mData, oldName, newName);
565 if (ret != 0) {
566 errno = OsLfsErrno(ret);
567 ret = FS_NOK;
568 }
569
570 return ret;
571 }
572
OsLfsStat(struct TagMountPoint * mp,const char * path,struct stat * buf)573 static S32 OsLfsStat(struct TagMountPoint *mp, const char *path, struct stat *buf)
574 {
575 S32 ret;
576 struct lfs_info info;
577
578 if ((mp == NULL) || (path == NULL) || (buf == NULL)) {
579 errno = EFAULT;
580 return FS_NOK;
581 }
582
583 if (mp->mData == NULL) {
584 errno = ENOENT;
585 return FS_NOK;
586 }
587
588 ret = lfs_stat((lfs_t *)mp->mData, path, &info);
589 if (ret == 0) {
590 buf->st_size = info.size;
591 if (info.type == LFS_TYPE_REG) {
592 buf->st_mode = S_IFREG;
593 } else {
594 buf->st_mode = S_IFDIR;
595 }
596 } else {
597 errno = OsLfsErrno(ret);
598 ret = FS_NOK;
599 }
600
601 return ret;
602 }
603
OsLfsSync(struct TagFile * file)604 static S32 OsLfsSync(struct TagFile *file)
605 {
606 S32 ret;
607 struct TagMountPoint *mp = NULL;
608
609 if ((file == NULL) || (file->fData == NULL)) {
610 errno = EBADF;
611 return FS_NOK;
612 }
613
614 if ((file->fMp == NULL) || (file->fMp->mData == NULL)) {
615 errno = EFAULT;
616 return FS_NOK;
617 }
618
619 mp = file->fMp;
620 ret = lfs_file_sync((lfs_t *)mp->mData, (lfs_file_t *)file->fData);
621 if (ret != 0) {
622 errno = OsLfsErrno(ret);
623 ret = FS_NOK;
624 }
625 return ret;
626 }
627
OsLfsFormat(const char * partName,void * privData)628 static S32 OsLfsFormat(const char *partName, void *privData)
629 {
630 S32 ret;
631 lfs_t lfs = {0};
632 struct lfs_config cfg = {0};
633
634 (void)partName;
635
636 OsLfsConfigAdapter((struct PartitionCfg *)privData, &cfg);
637
638 ret = lfs_format(&lfs, &cfg);
639 if (ret != 0) {
640 errno = OsLfsErrno(ret);
641 ret = FS_NOK;
642 }
643 return ret;
644 }
645
646 static struct TagMountOps g_lfsMnt = {
647 .mount = OsLfsMount,
648 .umount = OsLfsUmount,
649 .umount2 = NULL,
650 .statfs = NULL,
651 };
652
653 static struct TagFileOps g_lfsFops = {
654 .open = OsLfsOpen,
655 .close = OsLfsClose,
656 .read = OsLfsRead,
657 .write = OsLfsWrite,
658 .lseek = OsLfsSeek,
659 .stat = OsLfsStat,
660 .truncate = NULL,
661 .unlink = OsLfsUnlink,
662 .rename = OsLfsRename,
663 .ioctl = NULL, /* 不支持 */
664 .sync = OsLfsSync,
665 .rmdir = OsLfsRmdir,
666 .opendir = OsLfsOpendir,
667 .readdir = OsLfsReaddir,
668 .closedir = OsLfsClosedir,
669 .mkdir = OsLfsMkdir,
670 };
671
672 static struct TagFsManagement g_lfsMgt = {
673 .fdisk = NULL,
674 .format = OsLfsFormat,
675 };
676
OsLfsInit(void)677 void OsLfsInit(void)
678 {
679 (void)OsFsRegister("littlefs", &g_lfsMnt, &g_lfsFops, &g_lfsMgt);
680 }
681