1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2022 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#define _GNU_SOURCE 1 33#include "lfs_adapter.h" 34#include "los_config.h" 35#include "vfs_files.h" 36#include "vfs_operations.h" 37#include "vfs_partition.h" 38#include "vfs_maps.h" 39#include "vfs_mount.h" 40#include "securec.h" 41#include "los_fs.h" 42 43static struct PartitionCfg g_partitionCfg; 44static struct DeviceDesc *g_lfsDevice = NULL; 45 46static uint32_t LfsGetStartAddr(int partition) 47{ 48 if (g_lfsDevice == NULL) { 49 struct DeviceDesc *device = NULL; 50 for (device = getDeviceList(); device != NULL; device = device->dNext) { 51 if (strcmp(device->dFsType, "littlefs") == 0) { 52 g_lfsDevice = device; 53 break; 54 } 55 } 56 } 57 58 if ((g_lfsDevice == NULL) || (partition >= g_lfsDevice->dPartNum)) { 59 return INVALID_DEVICE_ADDR; 60 } 61 62 return (uint32_t)g_lfsDevice->dAddrArray[partition]; 63} 64 65WEAK int littlefs_block_read(const struct lfs_config *c, lfs_block_t block, 66 lfs_off_t off, void *dst, lfs_size_t size) 67{ 68 UINT32 addr = c->block_size * block + off; 69 UINT32 startaddr = LfsGetStartAddr((int)c->context); 70 if (startaddr == INVALID_DEVICE_ADDR) { 71 return -1; 72 } 73 addr += startaddr; 74 75 return (g_partitionCfg.readFunc)((int)c->context, &addr, dst, size); 76} 77 78WEAK int littlefs_block_write(const struct lfs_config *c, lfs_block_t block, 79 lfs_off_t off, const void *dst, lfs_size_t size) 80{ 81 UINT32 addr = c->block_size * block + off; 82 UINT32 startaddr = LfsGetStartAddr((int)c->context); 83 if (startaddr == INVALID_DEVICE_ADDR) { 84 return -1; 85 } 86 87 addr += startaddr; 88 89 return (g_partitionCfg.writeFunc)((int)c->context, &addr, dst, size); 90} 91 92WEAK int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block) 93{ 94 UINT32 addr = c->block_size * block; 95 UINT32 startaddr = LfsGetStartAddr((int)c->context); 96 if (startaddr == INVALID_DEVICE_ADDR) { 97 return -1; 98 } 99 100 addr += startaddr; 101 102 return (g_partitionCfg.eraseFunc)((int)c->context, addr, c->block_size); 103} 104 105WEAK int littlefs_block_sync(const struct lfs_config *c) 106{ 107 (void)c; 108 return 0; 109} 110 111static int ConvertFlagToLfsOpenFlag (int oflags) 112{ 113 int lfsOpenFlag = 0; 114 115 if (oflags & O_CREAT) { 116 lfsOpenFlag |= LFS_O_CREAT; 117 } 118 119 if (oflags & O_EXCL) { 120 lfsOpenFlag |= LFS_O_EXCL; 121 } 122 123 if (oflags & O_TRUNC) { 124 lfsOpenFlag |= LFS_O_TRUNC; 125 } 126 127 if (oflags & O_APPEND) { 128 lfsOpenFlag |= LFS_O_APPEND; 129 } 130 131 if (oflags & O_RDWR) { 132 lfsOpenFlag |= LFS_O_RDWR; 133 } 134 135 if (oflags & O_WRONLY) { 136 lfsOpenFlag |= LFS_O_WRONLY; 137 } 138 139 if (oflags == O_RDONLY) { 140 lfsOpenFlag |= LFS_O_RDONLY; 141 } 142 143 return lfsOpenFlag; 144} 145 146static int LittlefsErrno(int result) 147{ 148 return (result < 0) ? -result : result; 149} 150 151void LfsConfigAdapter(struct PartitionCfg *pCfg, struct lfs_config *lfsCfg) 152{ 153 lfsCfg->context = (void *)pCfg->partNo; 154 155 lfsCfg->read_size = pCfg->readSize; 156 lfsCfg->prog_size = pCfg->writeSize; 157 lfsCfg->cache_size = pCfg->cacheSize; 158 lfsCfg->block_cycles = pCfg->blockCycles; 159 lfsCfg->lookahead_size = pCfg->lookaheadSize; 160 lfsCfg->block_size = pCfg->blockSize; 161 lfsCfg->block_count = pCfg->blockCount; 162 163 lfsCfg->read = littlefs_block_read; 164 lfsCfg->prog = littlefs_block_write; 165 lfsCfg->erase = littlefs_block_erase; 166 lfsCfg->sync = littlefs_block_sync; 167 168 g_partitionCfg.readFunc = pCfg->readFunc; 169 g_partitionCfg.writeFunc = pCfg->writeFunc; 170 g_partitionCfg.eraseFunc = pCfg->eraseFunc; 171} 172 173int LfsMount(struct MountPoint *mp, unsigned long mountflags, const void *data) 174{ 175 int ret; 176 lfs_t *mountHdl = NULL; 177 struct lfs_config *cfg = NULL; 178 179 if ((mp == NULL) || (mp->mPath == NULL) || (data == NULL)) { 180 errno = EFAULT; 181 ret = (int)LOS_NOK; 182 goto errout; 183 } 184 185 if (mountflags & MS_REMOUNT) { 186 errno = ENOSYS; 187 ret = (int)LOS_NOK; 188 goto errout; 189 } 190 191 mountHdl = (lfs_t *)LOSCFG_FS_MALLOC_HOOK(sizeof(lfs_t) + sizeof(struct lfs_config)); 192 if (mountHdl == NULL) { 193 errno = ENODEV; 194 ret = (int)LOS_NOK; 195 goto errout; 196 } 197 (void)memset_s(mountHdl, sizeof(lfs_t) + sizeof(struct lfs_config), 0, sizeof(lfs_t) + sizeof(struct lfs_config)); 198 mp->mData = (void *)mountHdl; 199 cfg = (void *)((UINTPTR)mountHdl + sizeof(lfs_t)); 200 201 LfsConfigAdapter((struct PartitionCfg *)data, cfg); 202 203 ret = lfs_mount((lfs_t *)mp->mData, cfg); 204 if (ret != 0) { 205 ret = lfs_format((lfs_t *)mp->mData, cfg); 206 if (ret == 0) { 207 ret = lfs_mount((lfs_t *)mp->mData, cfg); 208 } 209 } 210 if (ret != 0) { 211 LOSCFG_FS_FREE_HOOK(mountHdl); 212 errno = LittlefsErrno(ret); 213 ret = (int)LOS_NOK; 214 } 215 216errout: 217 return ret; 218} 219 220int LfsUmount(struct MountPoint *mp) 221{ 222 int ret; 223 224 if (mp == NULL) { 225 errno = EFAULT; 226 return (int)LOS_NOK; 227 } 228 229 if (mp->mData == NULL) { 230 errno = ENOENT; 231 return (int)LOS_NOK; 232 } 233 234 ret = lfs_unmount((lfs_t *)mp->mData); 235 if (ret != 0) { 236 errno = LittlefsErrno(ret); 237 ret = (int)LOS_NOK; 238 } 239 240 LOSCFG_FS_FREE_HOOK(mp->mData); 241 mp->mData = NULL; 242 return ret; 243} 244 245int LfsUnlink(struct MountPoint *mp, const char *fileName) 246{ 247 int ret; 248 249 if ((mp == NULL) || (fileName == NULL)) { 250 errno = EFAULT; 251 return (int)LOS_NOK; 252 } 253 254 if (mp->mData == NULL) { 255 errno = ENOENT; 256 return (int)LOS_NOK; 257 } 258 259 ret = lfs_remove((lfs_t *)mp->mData, fileName); 260 if (ret != 0) { 261 errno = LittlefsErrno(ret); 262 ret = (int)LOS_NOK; 263 } 264 265 return ret; 266} 267 268int LfsMkdir(struct MountPoint *mp, const char *dirName) 269{ 270 int ret; 271 272 if ((dirName == NULL) || (mp == NULL)) { 273 errno = EFAULT; 274 return (int)LOS_NOK; 275 } 276 277 if (mp->mData == NULL) { 278 errno = ENOENT; 279 return (int)LOS_NOK; 280 } 281 282 lfs_t *lfs = (lfs_t *)mp->mData; 283 284 ret = lfs_mkdir(lfs, dirName); 285 if (ret != 0) { 286 errno = LittlefsErrno(ret); 287 ret = (int)LOS_NOK; 288 } 289 290 return ret; 291} 292 293int LfsRmdir(struct MountPoint *mp, const char *dirName) 294{ 295 int ret; 296 lfs_t *lfs = NULL; 297 298 if (mp == NULL) { 299 errno = EFAULT; 300 return (int)LOS_NOK; 301 } 302 303 if (mp->mData == NULL) { 304 errno = ENOENT; 305 return (int)LOS_NOK; 306 } 307 308 lfs = (lfs_t *)mp->mData; 309 310 if (dirName == NULL) { 311 errno = EFAULT; 312 return (int)LOS_NOK; 313 } 314 315 ret = lfs_remove(lfs, dirName); 316 if (ret != 0) { 317 errno = LittlefsErrno(ret); 318 ret = (int)LOS_NOK; 319 } 320 321 return ret; 322} 323 324int LfsOpendir(struct Dir *dir, const char *dirName) 325{ 326 int ret; 327 328 if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) { 329 errno = EFAULT; 330 return (int)LOS_NOK; 331 } 332 333 lfs_t *lfs = (lfs_t *)dir->dMp->mData; 334 lfs_dir_t *dirInfo = (lfs_dir_t *)LOSCFG_FS_MALLOC_HOOK(sizeof(lfs_dir_t)); 335 if (dirInfo == NULL) { 336 errno = ENOMEM; 337 return (int)LOS_NOK; 338 } 339 340 (void)memset_s(dirInfo, sizeof(lfs_dir_t), 0, sizeof(lfs_dir_t)); 341 ret = lfs_dir_open(lfs, dirInfo, dirName); 342 if (ret != 0) { 343 LOSCFG_FS_FREE_HOOK(dirInfo); 344 errno = LittlefsErrno(ret); 345 goto errout; 346 } 347 348 dir->dData = dirInfo; 349 dir->dOffset = 0; 350 351 return LOS_OK; 352 353errout: 354 return (int)LOS_NOK; 355} 356 357int LfsReaddir(struct Dir *dir, struct dirent *dent) 358{ 359 int ret; 360 struct lfs_info lfsInfo; 361 362 if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL) || 363 (dent == NULL)) { 364 errno = EFAULT; 365 return (int)LOS_NOK; 366 } 367 368 if (dir->dData == NULL) { 369 errno = EBADF; 370 return (int)LOS_NOK; 371 } 372 373 lfs_t *lfs = (lfs_t *)dir->dMp->mData; 374 lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData; 375 376 ret = lfs_dir_read(lfs, dirInfo, &lfsInfo); 377 if (ret == TRUE) { 378 (void)strncpy_s(dent->d_name, sizeof(dent->d_name), lfsInfo.name, strlen(lfsInfo.name) + 1); 379 if (lfsInfo.type == LFS_TYPE_DIR) { 380 dent->d_type = DT_DIR; 381 } else if (lfsInfo.type == LFS_TYPE_REG) { 382 dent->d_type = DT_REG; 383 } 384 385 dent->d_reclen = lfsInfo.size; 386 387 return LOS_OK; 388 } 389 390 if (ret != 0) { 391 errno = LittlefsErrno(ret); 392 } 393 394 return (int)LOS_NOK; 395} 396 397int LfsClosedir(struct Dir *dir) 398{ 399 int ret; 400 401 if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) { 402 errno = EFAULT; 403 return (int)LOS_NOK; 404 } 405 406 if (dir->dData == NULL) { 407 errno = EBADF; 408 return (int)LOS_NOK; 409 } 410 411 lfs_t *lfs = (lfs_t *)dir->dMp->mData; 412 lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData; 413 414 ret = lfs_dir_close(lfs, dirInfo); 415 if (ret != 0) { 416 errno = LittlefsErrno(ret); 417 ret = (int)LOS_NOK; 418 } 419 420 LOSCFG_FS_FREE_HOOK(dirInfo); 421 dir->dData = NULL; 422 423 return ret; 424} 425 426int LfsOpen(struct File *file, const char *pathName, int openFlag) 427{ 428 int ret; 429 lfs_file_t *lfsHandle = NULL; 430 431 if ((pathName == NULL) || (file == NULL) || (file->fMp == NULL) || 432 (file->fMp->mData == NULL)) { 433 errno = EFAULT; 434 return (int)LOS_NOK; 435 } 436 437 lfsHandle = (lfs_file_t *)LOSCFG_FS_MALLOC_HOOK(sizeof(lfs_file_t)); 438 if (lfsHandle == NULL) { 439 errno = ENOMEM; 440 return (int)LOS_NOK; 441 } 442 443 int lfsOpenFlag = ConvertFlagToLfsOpenFlag(openFlag); 444 ret = lfs_file_open((lfs_t *)file->fMp->mData, lfsHandle, pathName, lfsOpenFlag); 445 if (ret != 0) { 446 LOSCFG_FS_FREE_HOOK(lfsHandle); 447 errno = LittlefsErrno(ret); 448 goto errout; 449 } 450 451 file->fData = (void *)lfsHandle; 452 return ret; 453 454errout: 455 return INVALID_FD; 456} 457 458int LfsRead(struct File *file, char *buf, size_t len) 459{ 460 int ret; 461 struct MountPoint *mp = NULL; 462 lfs_file_t *lfsHandle = NULL; 463 464 if (buf == NULL) { 465 errno = EFAULT; 466 return (int)LOS_NOK; 467 } 468 469 if ((file == NULL) || (file->fData == NULL)) { 470 errno = EBADF; 471 return (int)LOS_NOK; 472 } 473 474 lfsHandle = (lfs_file_t *)file->fData; 475 mp = file->fMp; 476 if ((mp == NULL) || (mp->mData == NULL)) { 477 errno = EFAULT; 478 return (int)LOS_NOK; 479 } 480 481 ret = lfs_file_read((lfs_t *)mp->mData, lfsHandle, buf, len); 482 if (ret < 0) { 483 errno = LittlefsErrno(ret); 484 ret = (int)LOS_NOK; 485 } 486 return ret; 487} 488 489int LfsWrite(struct File *file, const char *buf, size_t len) 490{ 491 int ret; 492 struct MountPoint *mp = NULL; 493 lfs_file_t *lfsHandle = NULL; 494 495 if (buf == NULL) { 496 errno = EFAULT; 497 return (int)LOS_NOK; 498 } 499 500 if ((file == NULL) || (file->fData == NULL)) { 501 errno = EBADF; 502 return (int)LOS_NOK; 503 } 504 505 lfsHandle = (lfs_file_t *)file->fData; 506 mp = file->fMp; 507 if ((mp == NULL) || (mp->mData == NULL)) { 508 errno = EFAULT; 509 return (int)LOS_NOK; 510 } 511 512 ret = lfs_file_write((lfs_t *)mp->mData, lfsHandle, buf, len); 513 if (ret < 0) { 514 errno = LittlefsErrno(ret); 515 ret = (int)LOS_NOK; 516 } 517 return ret; 518} 519 520off_t LfsSeek(struct File *file, off_t offset, int whence) 521{ 522 off_t ret; 523 struct MountPoint *mp = NULL; 524 lfs_file_t *lfsHandle = NULL; 525 526 if ((file == NULL) || (file->fData == NULL)) { 527 errno = EBADF; 528 return (off_t)LOS_NOK; 529 } 530 531 lfsHandle = (lfs_file_t *)file->fData; 532 mp = file->fMp; 533 if ((mp == NULL) || (mp->mData == NULL)) { 534 errno = EFAULT; 535 return (off_t)LOS_NOK; 536 } 537 538 ret = (off_t)lfs_file_seek((lfs_t *)mp->mData, lfsHandle, offset, whence); 539 if (ret < 0) { 540 errno = LittlefsErrno(ret); 541 ret = (off_t)LOS_NOK; 542 } 543 544 return ret; 545} 546 547int LfsClose(struct File *file) 548{ 549 int ret; 550 struct MountPoint *mp = NULL; 551 lfs_file_t *lfsHandle = NULL; 552 553 if ((file == NULL) || (file->fData == NULL)) { 554 errno = EBADF; 555 return (int)LOS_NOK; 556 } 557 558 lfsHandle = (lfs_file_t *)file->fData; 559 mp = file->fMp; 560 if ((mp == NULL) || (mp->mData == NULL)) { 561 errno = EFAULT; 562 return (int)LOS_NOK; 563 } 564 565 ret = lfs_file_close((lfs_t *)mp->mData, lfsHandle); 566 if (ret != 0) { 567 errno = LittlefsErrno(ret); 568 ret = (int)LOS_NOK; 569 } 570 571 LOSCFG_FS_FREE_HOOK(file->fData); 572 file->fData = NULL; 573 return ret; 574} 575 576int LfsRename(struct MountPoint *mp, const char *oldName, const char *newName) 577{ 578 int ret; 579 580 if ((mp == NULL) || (oldName == NULL) || (newName == NULL)) { 581 errno = EFAULT; 582 return (int)LOS_NOK; 583 } 584 585 if (mp->mData == NULL) { 586 errno = ENOENT; 587 return (int)LOS_NOK; 588 } 589 590 ret = lfs_rename((lfs_t *)mp->mData, oldName, newName); 591 if (ret != 0) { 592 errno = LittlefsErrno(ret); 593 ret = (int)LOS_NOK; 594 } 595 596 return ret; 597} 598 599int LfsStat(struct MountPoint *mp, const char *path, struct stat *buf) 600{ 601 int ret; 602 struct lfs_info info; 603 604 if ((mp == NULL) || (path == NULL) || (buf == NULL)) { 605 errno = EFAULT; 606 return (int)LOS_NOK; 607 } 608 609 if (mp->mData == NULL) { 610 errno = ENOENT; 611 return (int)LOS_NOK; 612 } 613 614 ret = lfs_stat((lfs_t *)mp->mData, path, &info); 615 if (ret == 0) { 616 buf->st_size = info.size; 617 if (info.type == LFS_TYPE_REG) { 618 buf->st_mode = S_IFREG; 619 } else { 620 buf->st_mode = S_IFDIR; 621 } 622 } else { 623 errno = LittlefsErrno(ret); 624 ret = (int)LOS_NOK; 625 } 626 627 return ret; 628} 629 630int LfsSync(struct File *file) 631{ 632 int ret; 633 struct MountPoint *mp = NULL; 634 635 if ((file == NULL) || (file->fData == NULL)) { 636 errno = EBADF; 637 return (int)LOS_NOK; 638 } 639 640 if ((file->fMp == NULL) || (file->fMp->mData == NULL)) { 641 errno = EFAULT; 642 return (int)LOS_NOK; 643 } 644 645 mp = file->fMp; 646 ret = lfs_file_sync((lfs_t *)mp->mData, (lfs_file_t *)file->fData); 647 if (ret != 0) { 648 errno = LittlefsErrno(ret); 649 ret = (int)LOS_NOK; 650 } 651 return ret; 652} 653 654int LfsFormat(const char *partName, void *privData) 655{ 656 int ret; 657 lfs_t lfs = {0}; 658 struct lfs_config cfg = {0}; 659 660 (void)partName; 661 662 LfsConfigAdapter((struct PartitionCfg *)privData, &cfg); 663 664 ret = lfs_format(&lfs, &cfg); 665 if (ret != 0) { 666 errno = LittlefsErrno(ret); 667 ret = (int)LOS_NOK; 668 } 669 return ret; 670} 671 672static struct MountOps g_lfsMnt = { 673 .mount = LfsMount, 674 .umount = LfsUmount, 675 .umount2 = NULL, 676 .statfs = NULL, 677}; 678 679static struct FileOps g_lfsFops = { 680 .open = LfsOpen, 681 .close = LfsClose, 682 .read = LfsRead, 683 .write = LfsWrite, 684 .lseek = LfsSeek, 685 .stat = LfsStat, 686 .truncate = NULL, 687 .unlink = LfsUnlink, 688 .rename = LfsRename, 689 .ioctl = NULL, /* not support */ 690 .sync = LfsSync, 691 .rmdir = LfsRmdir, 692 .opendir = LfsOpendir, 693 .readdir = LfsReaddir, 694 .closedir = LfsClosedir, 695 .mkdir = LfsMkdir, 696}; 697 698static struct FsManagement g_lfsMgt = { 699 .fdisk = NULL, 700 .format = LfsFormat, 701}; 702 703void LfsInit(void) 704{ 705 (void)OsFsRegister("littlefs", &g_lfsMnt, &g_lfsFops, &g_lfsMgt); 706} 707