diff --git a/bsp/qemu-vexpress-a9/applications/mnt.c b/bsp/qemu-vexpress-a9/applications/mnt.c index 0fc9b62860b9a1d6090c433bed5a5c7873844649..e8ce2e3e91c2cbd5859b0612ffcaa33be261d56e 100644 --- a/bsp/qemu-vexpress-a9/applications/mnt.c +++ b/bsp/qemu-vexpress-a9/applications/mnt.c @@ -4,6 +4,10 @@ #include #include +#ifdef RT_USING_DFS_PMQ +#include +#endif + int mnt_init(void) { if (dfs_mount(RT_NULL, "/", "rom", 0, &romfs_root) != 0) @@ -19,6 +23,19 @@ int mnt_init(void) return -1; } +#ifdef RT_USING_DFS_PMQ + rt_thread_mdelay(200); + if (dfs_mount(RT_NULL, "/pmq", "pmq", 0, dfs_pps_init(rt_malloc(20480), 20480)) != 0) + { + rt_kprintf("Dir /pmq mount failed!\n"); + return -1; + } + else + { + rt_kprintf("PMQ service initializated!\n"); + } +#endif + rt_kprintf("file system initialization done!\n"); return 0; } diff --git a/bsp/qemu-vexpress-a9/applications/romfs.c b/bsp/qemu-vexpress-a9/applications/romfs.c index c28ba8ea7f2e52f05d808138b39f60d531ee57a2..5f2ae59d95140364de67bf895f48d8d2d108546a 100644 --- a/bsp/qemu-vexpress-a9/applications/romfs.c +++ b/bsp/qemu-vexpress-a9/applications/romfs.c @@ -8,7 +8,8 @@ static const struct romfs_dirent _romfs_root[] = { {ROMFS_DIRENT_DIR, "etc", RT_NULL, 0}, - {ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0} + {ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0}, + {ROMFS_DIRENT_DIR, "pmq", RT_NULL, 0}, }; const struct romfs_dirent romfs_root = { diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 657c8a25c42b24be2efe7588ada2debbf7860966..551d32d903b045065a1b3aa3b3684e4438c4d682 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -169,6 +169,9 @@ if RT_USING_DFS default "192.168.1.5:/" endif + config RT_USING_DFS_PMQ + bool "Enable PMQ service" + default n endif endmenu diff --git a/components/dfs/filesystems/pmq/SConscript b/components/dfs/filesystems/pmq/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..5258695d3c280df0dd0b20c4bf973760ad898901 --- /dev/null +++ b/components/dfs/filesystems/pmq/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('pmq', src, depend = ['RT_USING_DFS', 'RT_USING_MEMHEAP', 'RT_USING_DFS_PMQ'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/dfs/filesystems/pmq/dfs_pmq.c b/components/dfs/filesystems/pmq/dfs_pmq.c new file mode 100644 index 0000000000000000000000000000000000000000..648154698713f79cb437dfa579157c232531a6f8 --- /dev/null +++ b/components/dfs/filesystems/pmq/dfs_pmq.c @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: GPL-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-31 WillianChan The first version + */ + +#include +#include +#include +#include +#include "dfs_pmq.h" + +int dfs_pmq_mount(struct dfs_filesystem *fs, + unsigned long rwflag, + const void *data) +{ + struct dfs_pmq *pmq; + + if (data == NULL) + return -EIO; + + pmq = (struct dfs_pmq *)data; + fs->data = pmq; + + return RT_EOK; +} + +int dfs_pmq_unmount(struct dfs_filesystem *fs) +{ + fs->data = NULL; + + return RT_EOK; +} + +int dfs_pmq_statfs(struct dfs_filesystem *fs, struct statfs *buf) +{ + struct dfs_pmq *pmq; + + pmq = (struct dfs_pmq *)fs->data; + RT_ASSERT(pmq != NULL); + RT_ASSERT(buf != NULL); + + buf->f_bsize = 512; + buf->f_blocks = pmq->memheap.pool_size / 512; + buf->f_bfree = pmq->memheap.available_size / 512; + + return RT_EOK; +} + +int ddfs_pmq_ioctl(struct dfs_fd *file, int cmd, void *args) +{ + return -EIO; +} + +struct pmq_dirent *dfs_pmq_lookup(struct dfs_pmq *pmq, + const char *path, + rt_size_t *size) +{ + const char *subpath; + struct pmq_dirent *dirent; + + subpath = path; + while (*subpath == '/' && *subpath) + subpath ++; + if (! *subpath) /* is root directory */ + { + *size = 0; + + return &(pmq->root); + } + + for (dirent = rt_list_entry(pmq->root.list.next, struct pmq_dirent, list); + dirent != &(pmq->root); + dirent = rt_list_entry(dirent->list.next, struct pmq_dirent, list)) + { + if (rt_strcmp(dirent->name, subpath) == 0) + { + *size = dirent->size; + + return dirent; + } + } + + /* not found */ + return NULL; +} + +int dfs_pmq_read(struct dfs_fd *file, void *buf, size_t count) +{ + rt_size_t length; + struct pmq_dirent *dirent; + + dirent = (struct pmq_dirent *)file->fnode->data; + RT_ASSERT(dirent != NULL); + + if (count < file->fnode->size - file->pos) + length = count; + else + length = file->fnode->size - file->pos; + + if (length > 0) + memcpy(buf, &(dirent->data[file->pos]), length); + + /* update file current position */ + file->pos += length; + + return length; +} + +int dfs_pmq_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + struct pmq_dirent *dirent; + struct dfs_pmq *pmq; + rt_uint8_t *ptr; + char dirent_name[PMQ_NAME_MAX]; + rt_int32_t dirent_name_len; + + dirent = (struct pmq_dirent *)fd->fnode->data; + RT_ASSERT(dirent != NULL); + + pmq = dirent->fs; + RT_ASSERT(pmq != NULL); + + if (count + fd->pos > fd->fnode->size) + { + dirent_name_len = rt_snprintf(dirent_name, sizeof(dirent_name), "@%s\n", dirent->name); + ptr = rt_memheap_realloc(&(pmq->memheap), dirent->data, fd->pos + count + dirent_name_len); + if (ptr == NULL) + { + rt_set_errno(-ENOMEM); + + return 0; + } + + /* update dirent and file size */ + dirent->data = ptr; + dirent->size = fd->pos + count + dirent_name_len; + fd->fnode->size = dirent->size; + } + + if (count > 0) + { + memcpy(dirent->data, dirent_name, dirent_name_len); + memcpy(dirent->data + fd->pos + dirent_name_len, buf, count); + } + + return count; +} + +int dfs_pmq_lseek(struct dfs_fd *file, off_t offset) +{ + if (offset <= (off_t)file->fnode->size) + { + file->pos = offset; + + return file->pos; + } + + return -EIO; +} + +int dfs_pmq_close(struct dfs_fd *file) +{ + RT_ASSERT(file->fnode->ref_count > 0); + if (file->fnode->ref_count > 1) + { + return 0; + } + + file->fnode->data = NULL; + + return RT_EOK; +} + +int dfs_pmq_open(struct dfs_fd *file) +{ + rt_size_t size; + struct dfs_pmq *pmq; + struct pmq_dirent *dirent; + struct dfs_filesystem *fs; + + RT_ASSERT(file->fnode->ref_count > 0); + if (file->fnode->ref_count > 1) + { + if (file->fnode->type == FT_DIRECTORY + && !(file->flags & O_DIRECTORY)) + { + return -ENOENT; + } + file->pos = 0; + return 0; + } + + fs = file->fnode->fs; + + pmq = (struct dfs_pmq *)fs->data; + RT_ASSERT(pmq != NULL); + + if (file->flags & O_DIRECTORY) + { + if (file->flags & O_CREAT) + { + return -ENOSPC; + } + + /* open directory */ + dirent = dfs_pmq_lookup(pmq, file->fnode->path, &size); + if (dirent == NULL) + return -ENOENT; + if (dirent == &(pmq->root)) /* it's root directory */ + { + if (!(file->flags & O_DIRECTORY)) + { + return -ENOENT; + } + } + file->fnode->type = FT_DIRECTORY; + } + else + { + dirent = dfs_pmq_lookup(pmq, file->fnode->path, &size); + if (dirent == &(pmq->root)) /* it's root directory */ + { + return -ENOENT; + } + + if (dirent == NULL) + { + if (file->flags & O_CREAT || file->flags & O_WRONLY) + { + char *name_ptr; + + /* create a file entry */ + dirent = (struct pmq_dirent *) + rt_memheap_alloc(&(pmq->memheap), + sizeof(struct pmq_dirent)); + if (dirent == NULL) + { + return -ENOMEM; + } + + /* remove '/' separator */ + name_ptr = file->fnode->path; + while (*name_ptr == '/' && *name_ptr) + { + name_ptr++; + } + strncpy(dirent->name, name_ptr, PMQ_NAME_MAX); + + rt_list_init(&(dirent->list)); + dirent->data = NULL; + dirent->size = 0; + dirent->fs = pmq; + file->fnode->type = FT_DIRECTORY; + + /* add to the root directory */ + rt_list_insert_after(&(pmq->root.list), &(dirent->list)); + } + else + return -ENOENT; + } + + /* Creates a new file. + * If the file is existing, it is truncated and overwritten. + */ + if (file->flags & O_TRUNC) + { + dirent->size = 0; + if (dirent->data != NULL) + { + rt_memheap_free(dirent->data); + dirent->data = NULL; + } + } + } + + file->fnode->data = dirent; + file->fnode->size = dirent->size; + if (file->flags & O_APPEND) + { + file->pos = file->fnode->size; + } + else + { + file->pos = 0; + } + + return 0; +} + +int dfs_pmq_stat(struct dfs_filesystem *fs, + const char *path, + struct stat *st) +{ + rt_size_t size; + struct pmq_dirent *dirent; + struct dfs_pmq *ramfs; + + ramfs = (struct dfs_pmq *)fs->data; + dirent = dfs_pmq_lookup(ramfs, path, &size); + + if (dirent == NULL) + return -ENOENT; + + st->st_dev = 0; + st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | + S_IWUSR | S_IWGRP | S_IWOTH; + + st->st_size = dirent->size; + st->st_mtime = 0; + + return RT_EOK; +} + +int dfs_pmq_getdents(struct dfs_fd *file, + struct dirent *dirp, + uint32_t count) +{ + rt_size_t index, end; + struct dirent *d; + struct pmq_dirent *dirent; + struct dfs_pmq *pmq; + + dirent = (struct pmq_dirent *)file->fnode->data; + + pmq = dirent->fs; + RT_ASSERT(pmq != RT_NULL); + + if (dirent != &(pmq->root)) + return -EINVAL; + + /* make integer count */ + count = (count / sizeof(struct dirent)); + if (count == 0) + return -EINVAL; + + end = file->pos + count; + index = 0; + count = 0; + for (dirent = rt_list_entry(dirent->list.next, struct pmq_dirent, list); + dirent != &(pmq->root) && index < end; + dirent = rt_list_entry(dirent->list.next, struct pmq_dirent, list)) + { + if (index >= (rt_size_t)file->pos) + { + d = dirp + count; + d->d_type = DT_REG; + d->d_namlen = RT_NAME_MAX; + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, dirent->name, PMQ_NAME_MAX); + + count += 1; + file->pos += 1; + } + index += 1; + } + + return count * sizeof(struct dirent); +} + +static const struct dfs_file_ops _pmq_fops = +{ + dfs_pmq_open, + dfs_pmq_close, + ddfs_pmq_ioctl, + dfs_pmq_read, + dfs_pmq_write, + NULL, /* flush */ + dfs_pmq_lseek, + dfs_pmq_getdents, +}; + +static const struct dfs_filesystem_ops _pmq = +{ + "pmq", + DFS_FS_FLAG_DEFAULT, + &_pmq_fops, + + dfs_pmq_mount, + dfs_pmq_unmount, + NULL, /* mkfs */ + dfs_pmq_statfs, + + NULL, /* unlink */ + dfs_pmq_stat, + NULL, /* rename */ +}; + +int dfs_pmq_register(void) +{ + /* register pmq file system */ + dfs_register(&_pmq); + + return 0; +} +INIT_COMPONENT_EXPORT(dfs_pmq_register); + +struct dfs_pmq *dfs_pmq_init(rt_uint8_t *pool, rt_size_t size) +{ + struct dfs_pmq *pmq; + rt_uint8_t *data_ptr; + rt_err_t result; + + size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); + pmq = (struct dfs_pmq *)pool; + + data_ptr = (rt_uint8_t *)(pmq + 1); + size = size - sizeof(struct dfs_pmq); + size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); + + result = rt_memheap_init(&pmq->memheap, "pmq", data_ptr, size); + if (result != RT_EOK) + return NULL; + /* detach this memheap object from the system */ + rt_object_detach((rt_object_t) & (pmq->memheap)); + + /* initialize pmq object */ + pmq->magic = PMQ_MAGIC; + pmq->memheap.parent.type = RT_Object_Class_MemHeap | RT_Object_Class_Static; + + /* initialize root directory */ + memset(&(pmq->root), 0x00, sizeof(pmq->root)); + rt_list_init(&(pmq->root.list)); + pmq->root.size = 0; + strcpy(pmq->root.name, "."); + pmq->root.fs = pmq; + + return pmq; +} diff --git a/components/dfs/filesystems/pmq/dfs_pmq.h b/components/dfs/filesystems/pmq/dfs_pmq.h new file mode 100644 index 0000000000000000000000000000000000000000..e23b393f747e4c87b713e88493788a1a693751ec --- /dev/null +++ b/components/dfs/filesystems/pmq/dfs_pmq.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: GPL-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-31 WillianChan The first version + */ + +#ifndef __DFS_PMQ_H__ +#define __DFS_PMQ_H__ + +#include +#include + +#define PMQ_NAME_MAX 32 +#define PMQ_MAGIC 0x70707373 + +struct pmq_dirent +{ + rt_list_t list; + struct dfs_pmq *fs; /* file system ref */ + + char name[PMQ_NAME_MAX]; /* dirent name */ + rt_uint8_t *data; + + rt_size_t size; /* file size */ +}; + +/** + * DFS ramfs object + */ +struct dfs_pmq +{ + rt_uint32_t magic; + + struct rt_memheap memheap; + struct pmq_dirent root; +}; + +int dfs_pmq_register(void); +struct dfs_pmq *dfs_pmq_init(rt_uint8_t *pool, rt_size_t size); + +#endif /* __DFS_PMQ_H__ */ +