| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2017-11-11 parai@foxmail.com base porting
- * 2018-06-02 parai@foxmail.com fix mkfs issues
- * 2020-08-19 lizhirui porting to ls2k
- */
- #include <rtthread.h>
- #include <rtdef.h>
- #include <dfs.h>
- #include <dfs_fs.h>
- #include <dfs_file.h>
- #include <blk_device.h>
- #include "dfs_ext.h"
- #include "ext4.h"
- #include "ext4_mkfs.h"
- #include "ext4_config.h"
- #include "ext4_blockdev.h"
- #include "ext4_errno.h"
- #include "ext4_mbr.h"
- static int blockdev_open(struct ext4_blockdev *bdev);
- static int blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt);
- static int blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf,
- uint64_t blk_id, uint32_t blk_cnt);
- static int blockdev_close(struct ext4_blockdev *bdev);
- static int blockdev_lock(struct ext4_blockdev *bdev);
- static int blockdev_unlock(struct ext4_blockdev *bdev);
- EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev, 4096, 0, blockdev_open,
- blockdev_bread, blockdev_bwrite, blockdev_close,
- blockdev_lock, blockdev_unlock);
- #if RT_DFS_EXT_DRIVES > 1
- EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev1, 4096, 0, blockdev_open,
- blockdev_bread, blockdev_bwrite, blockdev_close,
- blockdev_lock, blockdev_unlock);
- #endif
- #if RT_DFS_EXT_DRIVES > 2
- EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev2, 4096, 0, blockdev_open,
- blockdev_bread, blockdev_bwrite, blockdev_close,
- blockdev_lock, blockdev_unlock);
- #endif
- #if RT_DFS_EXT_DRIVES > 3
- EXT4_BLOCKDEV_STATIC_INSTANCE(ext4_blkdev3, 4096, 0, blockdev_open,
- blockdev_bread, blockdev_bwrite, blockdev_close,
- blockdev_lock, blockdev_unlock);
- #endif
- #if RT_DFS_EXT_DRIVES > 4
- #error dfs_ext by default support only 4 partitions!
- #endif
- static rt_device_t disk[RT_DFS_EXT_DRIVES] = {0};
- static rt_size_t disk_sector_size[RT_DFS_EXT_DRIVES] = {0};
- static struct ext4_blockdev * const ext4_blkdev_list[RT_DFS_EXT_DRIVES] =
- {
- &ext4_blkdev,
- #if RT_DFS_EXT_DRIVES > 1
- &ext4_blkdev1,
- #endif
- #if RT_DFS_EXT_DRIVES > 2
- &ext4_blkdev2,
- #endif
- #if RT_DFS_EXT_DRIVES > 3
- &ext4_blkdev3,
- #endif
- };
- static int get_disk(rt_device_t id)
- {
- int index;
- for (index = 0; index < RT_DFS_EXT_DRIVES; index ++)
- {
- if (disk[index] == id)
- return index;
- }
- return -1;
- }
- static int get_bdev(struct ext4_blockdev * bdev)
- {
- int index;
- for (index = 0; index < RT_DFS_EXT_DRIVES; index ++)
- {
- if (ext4_blkdev_list[index] == bdev)
- return index;
- }
- RT_ASSERT(0);
- return -1;
- }
- static int dfs_ext_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* data)
- {
- int rc;
- int index;
- long partid = (long)data;
- char* mp = fs->path; /*mount point */
- char* img = fs->dev_id->parent.name;
- /* get an empty position */
- index = get_disk(RT_NULL);
- if (index == -1)
- {
- rt_kprintf("dfs_ext_mount: get an empty position.\n");
- return -ENOENT;
- }
- if(partid >= 0 && partid <= 3)
- {
- ext4_blkdev_list[index]->part_offset = ((struct blk_device *)fs->dev_id)->ext4_partition.partitions[partid].part_offset;
- ext4_blkdev_list[index]->part_size = ((struct blk_device *)fs->dev_id)->ext4_partition.partitions[partid].part_size;
- }
- else
- {
- rt_kprintf("dfs_ext_mount: mount partid:%d ,the partid max is 3.\n", partid);
- ext4_blkdev_list[index]->part_offset = -1;
- }
- rc = ext4_device_register(ext4_blkdev_list[index], img);
- if(EOK == rc)
- {
- disk[index] = fs->dev_id;
- rc = ext4_mount(img, fs->path, false);
- if(EOK != rc)
- {
- disk[index] = NULL;
- rc = -rc;
- ext4_device_unregister(img);
- }
- }
- return rc;
- }
- static int dfs_ext_unmount(struct dfs_filesystem* fs)
- {
- int index;
- int rc;
- char* mp = fs->path; /*mount point */
- /* find the device index and then umount it */
- index = get_disk(fs->dev_id);
- if (index == -1) /* not found */
- return -ENOENT;
- rc = ext4_umount(mp);
- return rc;
- }
- static int dfs_ext_mkfs(rt_device_t devid)
- {
- int index;
- int rc;
- static struct ext4_fs fs;
- static struct ext4_mkfs_info info = {
- .block_size = 4096,
- .journal = true,
- };
- char* img = devid->parent.name;
- if (devid == RT_NULL)
- {
- return -EINVAL;
- }
- /* find the device index, already mount */
- index = get_disk(devid);
- if (index != -1)
- return -EBUSY;
- index = get_disk(RT_NULL);
- if (index == -1) /* not found */
- return -ENOSPC;
- rc = ext4_device_register(ext4_blkdev_list[index], img);
- if(EOK == rc)
- {
- disk[index] = devid;
- /* try to open device */
- rt_device_open(devid, RT_DEVICE_OFLAG_RDWR);
- rc = ext4_mkfs(&fs, ext4_blkdev_list[index], &info, F_SET_EXT4);
- /* no matter what, unregister */
- disk[index] = NULL;
- ext4_device_unregister(img);
- /* close device */
- rt_device_close(devid);
- }
- rc = -rc;
- return rc;
- }
- static int dfs_ext_ioctl(struct dfs_fd* file, int cmd, void* args)
- {
- return -RT_EIO;
- }
- static int dfs_ext_read(struct dfs_fd *fd, void *buf, size_t count)
- {
- size_t bytesread = 0;
- int r;
- r = ext4_fread(fd->data, buf, count, &bytesread);
- if (0 != r)
- {
- bytesread = 0;
- }
- return bytesread;
- }
- static int dfs_ext_write(struct dfs_fd *fd, const void *buf, size_t count)
- {
- size_t byteswritten = 0;
- int r;
- r = ext4_fwrite(fd->data, buf, count, &byteswritten);
- if (0 != r)
- {
- byteswritten = 0;
- }
- return byteswritten;
- }
- static int dfs_ext_flush(struct dfs_fd *fd)
- {
- (void)fd;
- return -ENOTSUP;
- }
- static int dfs_ext_lseek(struct dfs_fd* file, rt_off_t offset)
- {
- int r;
- r = ext4_fseek(file->data, offset, SEEK_SET);
- return -r;
- }
- static int dfs_ext_close(struct dfs_fd* file)
- {
- int r;
- if (file->type == FT_DIRECTORY)
- {
- r = ext4_fclose(file->data);
- rt_free(file->data);
- }
- else
- {
- r = ext4_fclose(file->data);
- if(EOK == r)
- {
- rt_free(file->data);
- }
- }
- return -r;
- }
- static int dfs_ext_open(struct dfs_fd* file)
- {
- int r = EOK;
- ext4_dir *dir;
- ext4_file *f;
- if (file->flags & O_DIRECTORY)
- {
- if (file->flags & O_CREAT)
- {
- r = ext4_dir_mk(file->path);
- }
- if(EOK == r)
- {
- dir = rt_malloc(sizeof(ext4_dir));
- r = ext4_dir_open(dir, file->path);
- if(EOK == r)
- {
- file->data = dir;
- }
- else
- {
- rt_free(dir);
- }
- }
- }
- else
- {
- f = rt_malloc(sizeof(ext4_file));
- r = ext4_fopen2(f, file->path, file->flags);
- if(EOK == r)
- {
- file->data = f;
- }
- else
- {
- rt_free(f);
- }
- }
- return -r;
- }
- static int dfs_ext_unlink (struct dfs_filesystem *fs, const char *pathname)
- {
- int r;
- r = ext4_fremove(pathname);
- return -r;
- }
- static int dfs_ext_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
- {
- int r;
- union {
- ext4_dir dir;
- ext4_file f;
- } var;
- r = ext4_dir_open(&(var.dir), path);
- if(0 == r)
- {
- (void) ext4_dir_close(&(var.dir));
- st->st_mode = S_IFDIR;
- st->st_size = 0;
- }
- else
- {
- r = ext4_fopen(&(var.f), path, "rb");
- if( 0 == r)
- {
- st->st_mode = S_IFREG;
- st->st_size = ext4_fsize(&(var.f));
- (void)ext4_fclose(&(var.f));
- }
- }
- return -r;
- }
- static int dfs_ext_getdents(struct dfs_fd* file, struct dirent* dirp, rt_uint32_t count)
- {
- int index;
- struct dirent *d;
- const ext4_direntry * rentry;
- /* make integer count */
- count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
- if (count == 0)
- return -EINVAL;
- index = 0;
- while (1)
- {
- d = dirp + index;
- rentry = ext4_dir_entry_next(file->data);
- if(NULL != rentry)
- {
- strncpy(d->d_name, rentry->name, DFS_PATH_MAX);
- if(EXT4_DE_DIR == rentry->inode_type)
- {
- d->d_type = DT_DIR;
- }
- else
- {
- d->d_type = DT_REG;
- }
- d->d_namlen = (rt_uint8_t)rentry->name_length;
- d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
- index ++;
- if (index * sizeof(struct dirent) >= count)
- break;
- }
- else
- {
- break;
- }
- }
- file->pos += index * sizeof(struct dirent);
- return index * sizeof(struct dirent);
- }
- static int dfs_ext_rename (struct dfs_filesystem *fs, const char *oldpath, const char *newpath)
- {
- int r;
- r = ext4_frename(oldpath, newpath);
- return -r;
- }
- static const struct dfs_file_ops _ext_fops =
- {
- dfs_ext_open,
- dfs_ext_close,
- dfs_ext_ioctl,
- dfs_ext_read,
- dfs_ext_write,
- dfs_ext_flush,
- dfs_ext_lseek,
- dfs_ext_getdents,
- };
- static const struct dfs_filesystem_ops _ext_fs =
- {
- "ext",
- DFS_FS_FLAG_DEFAULT,
- &_ext_fops,
- dfs_ext_mount,
- dfs_ext_unmount,
- dfs_ext_mkfs,
- NULL, /* statfs */
- dfs_ext_unlink,
- dfs_ext_stat,
- dfs_ext_rename
- };
- int dfs_ext_init(void)
- {
- /* register rom file system */
- dfs_register(&_ext_fs);
- return 0;
- }
- INIT_COMPONENT_EXPORT(dfs_ext_init);
- static int blockdev_open(struct ext4_blockdev *bdev)
- {
- int r;
- uint32_t size;
- int index = get_bdev(bdev);
- rt_device_t device = disk[index];
- struct rt_device_blk_geometry geometry;
- RT_ASSERT(index < RT_DFS_EXT_DRIVES);
- RT_ASSERT(device);
- r = rt_device_open(device,RT_DEVICE_OFLAG_RDWR);
- if(r != RT_EOK)
- {
- return r;
- }
- r = rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
- if(RT_EOK == r)
- {
- if(bdev->part_offset == -1)
- {
- bdev->part_offset = 0;
- bdev->part_size = geometry.sector_count*geometry.bytes_per_sector;
- }
- disk_sector_size[index] = geometry.bytes_per_sector;
- bdev->bdif->ph_bcnt = bdev->part_size / bdev->bdif->ph_bsize;
- }
- return r;
- }
- static int blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt)
- {
- int result;
- int index = get_bdev(bdev);
- rt_device_t device = disk[index];
- struct blk_device *blk = (struct blk_device *)device;
- RT_ASSERT(index < RT_DFS_EXT_DRIVES);
- RT_ASSERT(device);
- result = rt_device_read(device, blk_id*(bdev->bdif->ph_bsize/disk_sector_size[index]),
- buf, blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index]));
- if((blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index])) == result)
- {
- result = 0;
- }
- else
- {
- result = -EIO;
- }
- return result;
- }
- static int blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf,
- uint64_t blk_id, uint32_t blk_cnt)
- {
- int result;
- int index = get_bdev(bdev);
- rt_device_t device = disk[index];
- RT_ASSERT(index < RT_DFS_EXT_DRIVES);
- RT_ASSERT(device);
- result = rt_device_write(device, blk_id*(bdev->bdif->ph_bsize/disk_sector_size[index]),
- buf, blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index]));
- if((blk_cnt*(bdev->bdif->ph_bsize/disk_sector_size[index])) == result)
- {
- result = 0;
- }
- else
- {
- result = -EIO;
- }
- return result;
- }
- static int blockdev_close(struct ext4_blockdev *bdev)
- {
- int result;
- int index = get_bdev(bdev);
- rt_device_t device = disk[index];
- RT_ASSERT(index < RT_DFS_EXT_DRIVES);
- RT_ASSERT(device);
- result = rt_device_close(device);
- return result;
- }
- static int blockdev_lock(struct ext4_blockdev *bdev)
- {
- return 0;
- }
- static int blockdev_unlock(struct ext4_blockdev *bdev)
- {
- return 0;
- }
|