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 25static pthread_mutex_t g_fsLocalMutex = PTHREAD_MUTEX_INITIALIZER; 26 27static struct PartitionCfg g_partitionCfg; 28static struct TagDeviceDesc *g_lfsDevice; 29 30static 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 49static 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 60static 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 72static 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 83static S32 OsLfsBlockSync(const struct lfs_config *c) 84{ 85 (void)c; 86 return 0; 87} 88 89static 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 124static S32 OsLfsErrno(S32 result) 125{ 126 return (result < 0) ? -result : result; 127} 128 129static 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 151static 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 194static 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 219static 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 242static 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 267static 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 296static 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 329static 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 371static 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 400static 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 429static 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 460static 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 491static 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 518static 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 550static 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 573static 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 604static 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 628static 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 646static struct TagMountOps g_lfsMnt = { 647 .mount = OsLfsMount, 648 .umount = OsLfsUmount, 649 .umount2 = NULL, 650 .statfs = NULL, 651}; 652 653static 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 672static struct TagFsManagement g_lfsMgt = { 673 .fdisk = NULL, 674 .format = OsLfsFormat, 675}; 676 677void OsLfsInit(void) 678{ 679 (void)OsFsRegister("littlefs", &g_lfsMnt, &g_lfsFops, &g_lfsMgt); 680} 681