Add mynewt glue and fix multi-fs support
This adds a mynewt glue with nffs_os_* function mappings, and filesystem
operation structs including fix to allow running under Mynewt's
multi-fs.
Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/include/nffs/nffs.h b/include/nffs/nffs.h
index e10f50c..dce17df 100644
--- a/include/nffs/nffs.h
+++ b/include/nffs/nffs.h
@@ -213,6 +213,9 @@
};
struct nffs_file {
+#if !__ZEPHYR__
+ struct fs_ops *fops;
+#endif
struct nffs_inode_entry *nf_inode_entry;
uint32_t nf_offset;
uint8_t nf_access_flags;
@@ -280,11 +283,16 @@
};
struct nffs_dirent {
+#if !__ZEPHYR__
struct fs_ops *fops;
+#endif
struct nffs_inode_entry *nde_inode_entry;
};
struct nffs_dir {
+#if !__ZEPHYR__
+ struct fs_ops *fops;
+#endif
struct nffs_inode_entry *nd_parent_inode_entry;
struct nffs_dirent nd_dirent;
};
diff --git a/src/nffs_dir.c b/src/nffs_dir.c
index 5d8bc90..f232bc1 100644
--- a/src/nffs_dir.c
+++ b/src/nffs_dir.c
@@ -22,6 +22,12 @@
#include <nffs/nffs.h>
#include <nffs/os.h>
+#if !__ZEPHYR__
+#include "fs/fs.h"
+#include "fs/fs_if.h"
+struct fs_ops nffs_ops;
+#endif
+
static struct nffs_dir *
nffs_dir_alloc(void)
{
@@ -74,6 +80,9 @@
dir->nd_parent_inode_entry = parent_inode_entry;
nffs_inode_inc_refcnt(dir->nd_parent_inode_entry);
memset(&dir->nd_dirent, 0, sizeof dir->nd_dirent);
+#if !__ZEPHYR__
+ dir->fops = &nffs_ops;
+#endif
*out_dir = dir;
@@ -104,6 +113,9 @@
}
nffs_inode_inc_refcnt(child);
+#if !__ZEPHYR__
+ dir->nd_dirent.fops = &nffs_ops;
+#endif
*out_dirent = &dir->nd_dirent;
return 0;
diff --git a/src/nffs_file.c b/src/nffs_file.c
index 4be4f5f..b02db98 100644
--- a/src/nffs_file.c
+++ b/src/nffs_file.c
@@ -22,6 +22,12 @@
#include <nffs/nffs.h>
#include <nffs/os.h>
+#if !__ZEPHYR__
+#include "fs/fs.h"
+#include "fs/fs_if.h"
+struct fs_ops nffs_ops;
+#endif
+
static struct nffs_file *
nffs_file_alloc(void)
{
@@ -242,6 +248,9 @@
}
nffs_inode_inc_refcnt(file->nf_inode_entry);
file->nf_access_flags = access_flags;
+#if !__ZEPHYR__
+ file->fops = &nffs_ops;
+#endif
*out_file = file;
diff --git a/test/src/nffs_os_mynewt.c b/test/src/nffs_os_mynewt.c
new file mode 100644
index 0000000..7afff32
--- /dev/null
+++ b/test/src/nffs_os_mynewt.c
@@ -0,0 +1,427 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#if !__ZEPHYR__
+
+#include <os/mynewt.h>
+#include "fs/fs.h"
+#include "fs/fs_if.h"
+#include "nffs/nffs.h"
+#include <crc/crc16.h>
+#include "nffs_test_utils.h"
+
+static struct os_mutex nffs_mutex;
+struct nffs_config nffs_config;
+struct log nffs_log;
+
+nffs_os_mempool_t nffs_file_pool;
+nffs_os_mempool_t nffs_dir_pool;
+nffs_os_mempool_t nffs_inode_entry_pool;
+nffs_os_mempool_t nffs_block_entry_pool;
+nffs_os_mempool_t nffs_cache_inode_pool;
+nffs_os_mempool_t nffs_cache_block_pool;
+
+void *nffs_file_mem;
+void *nffs_dir_mem;
+void *nffs_inode_mem;
+void *nffs_block_entry_mem;
+void *nffs_cache_inode_mem;
+void *nffs_cache_block_mem;
+
+int
+nffs_os_mempool_init(void)
+{
+ int rc;
+
+ assert(nffs_file_mem != NULL);
+ rc = os_mempool_init(&nffs_file_pool, nffs_config.nc_num_files,
+ sizeof(struct nffs_file), nffs_file_mem, "nffs_file_pool");
+ assert(rc == 0);
+
+ rc = os_mempool_init(&nffs_dir_pool, nffs_config.nc_num_dirs,
+ sizeof(struct nffs_dir), nffs_dir_mem, "nffs_dir_pool");
+ assert(rc == 0);
+
+ rc = os_mempool_init(&nffs_inode_entry_pool, nffs_config.nc_num_inodes,
+ sizeof(struct nffs_inode_entry), nffs_inode_mem,
+ "nffs_inode_entry_pool");
+ assert(rc == 0);
+
+ rc = os_mempool_init(&nffs_block_entry_pool, nffs_config.nc_num_blocks,
+ sizeof(struct nffs_hash_entry), nffs_block_entry_mem,
+ "nffs_block_entry_pool");
+ assert(rc == 0);
+
+ rc = os_mempool_init(&nffs_cache_inode_pool, nffs_config.nc_num_cache_inodes,
+ sizeof(struct nffs_cache_inode), nffs_cache_inode_mem,
+ "nffs_cache_inode_pool");
+ assert(rc == 0);
+
+ rc = os_mempool_init(&nffs_cache_block_pool, nffs_config.nc_num_cache_blocks,
+ sizeof(struct nffs_cache_block), nffs_cache_block_mem,
+ "nffs_cache_inode_pool");
+ assert(rc == 0);
+
+ return rc;
+}
+
+void *
+nffs_os_mempool_get(nffs_os_mempool_t *pool)
+{
+ return os_memblock_get(pool);
+}
+
+int
+nffs_os_mempool_free(nffs_os_mempool_t *pool, void *block)
+{
+ return os_memblock_put(pool, block);
+}
+
+int
+nffs_os_flash_read(uint8_t id, uint32_t address, void *dst, uint32_t num_bytes)
+{
+ return hal_flash_read(id, address, dst, num_bytes);
+}
+
+int
+nffs_os_flash_write(uint8_t id, uint32_t address, const void *src,
+ uint32_t num_bytes)
+{
+ return hal_flash_write(id, address, src, num_bytes);
+}
+
+int
+nffs_os_flash_erase(uint8_t id, uint32_t address, uint32_t num_bytes)
+{
+ return hal_flash_erase(id, address, num_bytes);
+}
+
+int nffs_os_flash_info(uint8_t id, uint32_t sector, uint32_t *address,
+ uint32_t *size)
+{
+ assert(0);
+ return 0;
+}
+
+uint16_t
+nffs_os_crc16_ccitt(uint16_t initial_crc, const void *buf, int len, int final)
+{
+ (void)final;
+ return crc16_ccitt(initial_crc, buf, len);
+}
+
+const struct nffs_config nffs_config_dflt = {
+ .nc_num_inodes = 100,
+ .nc_num_blocks = 100,
+ .nc_num_files = 4,
+ .nc_num_cache_inodes = 4,
+ .nc_num_cache_blocks = 64,
+ .nc_num_dirs = 4,
+};
+
+void
+nffs_config_init(void)
+{
+ if (nffs_config.nc_num_inodes == 0) {
+ nffs_config.nc_num_inodes = nffs_config_dflt.nc_num_inodes;
+ }
+ if (nffs_config.nc_num_blocks == 0) {
+ nffs_config.nc_num_blocks = nffs_config_dflt.nc_num_blocks;
+ }
+ if (nffs_config.nc_num_files == 0) {
+ nffs_config.nc_num_files = nffs_config_dflt.nc_num_files;
+ }
+ if (nffs_config.nc_num_cache_inodes == 0) {
+ nffs_config.nc_num_cache_inodes = nffs_config_dflt.nc_num_cache_inodes;
+ }
+ if (nffs_config.nc_num_cache_blocks == 0) {
+ nffs_config.nc_num_cache_blocks = nffs_config_dflt.nc_num_cache_blocks;
+ }
+ if (nffs_config.nc_num_dirs == 0) {
+ nffs_config.nc_num_dirs = nffs_config_dflt.nc_num_dirs;
+ }
+}
+
+static int
+nffs_open(const char *path, uint8_t access_flags, struct fs_file **out_fs_file)
+{
+ int rc;
+ struct nffs_file *out_file;
+
+ if (!nffs_misc_ready()) {
+ rc = FS_EUNINIT;
+ goto done;
+ }
+
+ rc = nffs_file_open(&out_file, path, access_flags);
+ if (rc != 0) {
+ goto done;
+ }
+ *out_fs_file = (struct fs_file *)out_file;
+
+done:
+ if (rc != 0) {
+ *out_fs_file = NULL;
+ }
+ return rc;
+}
+
+static int
+nffs_close(struct fs_file *fs_file)
+{
+ if (!fs_file) {
+ return 0;
+ }
+
+ return nffs_file_close((struct nffs_file *)fs_file);
+}
+
+static int
+nffs_seek(struct fs_file *fs_file, uint32_t offset)
+{
+ return nffs_file_seek((struct nffs_file *)fs_file, offset);
+}
+
+static uint32_t
+nffs_getpos(const struct fs_file *fs_file)
+{
+ return ((const struct nffs_file *)fs_file)->nf_offset;
+}
+
+static int
+nffs_file_len(const struct fs_file *fs_file, uint32_t *out_len)
+{
+ return nffs_inode_data_len(
+ ((const struct nffs_file *)fs_file)->nf_inode_entry, out_len);
+}
+
+static int
+nffs_read(struct fs_file *fs_file, uint32_t len, void *out_data,
+ uint32_t *out_len)
+{
+ return nffs_file_read((struct nffs_file *)fs_file, len, out_data, out_len);
+}
+
+static int
+nffs_write(struct fs_file *fs_file, const void *data, int len)
+{
+ if (!nffs_misc_ready()) {
+ return FS_EUNINIT;
+ }
+
+ return nffs_write_to_file((struct nffs_file *)fs_file, data, len);
+}
+
+static int
+nffs_unlink(const char *path)
+{
+ if (!nffs_misc_ready()) {
+ return FS_EUNINIT;
+ }
+
+ return nffs_path_unlink(path);
+}
+
+static int
+nffs_rename(const char *from, const char *to)
+{
+ if (!nffs_misc_ready()) {
+ return FS_EUNINIT;
+ }
+
+ return nffs_path_rename(from, to);
+}
+
+static int
+nffs_mkdir(const char *path)
+{
+ if (!nffs_misc_ready()) {
+ return FS_EUNINIT;
+ }
+
+ return nffs_path_new_dir(path, NULL);
+}
+
+static int
+nffs_opendir(const char *path, struct fs_dir **out_fs_dir)
+{
+ if (!nffs_misc_ready()) {
+ return FS_EUNINIT;
+ }
+
+ return nffs_dir_open(path, (struct nffs_dir **)out_fs_dir);
+}
+
+static int
+nffs_readdir(struct fs_dir *fs_dir, struct fs_dirent **out_fs_dirent)
+{
+ return nffs_dir_read((struct nffs_dir *)fs_dir,
+ (struct nffs_dirent **)out_fs_dirent);
+}
+
+static int
+nffs_closedir(struct fs_dir *fs_dir)
+{
+ return nffs_dir_close((struct nffs_dir *)fs_dir);
+}
+
+static int
+nffs_dirent_name(const struct fs_dirent *fs_dirent, size_t max_len,
+ char *out_name, uint8_t *out_name_len)
+{
+ struct nffs_dirent *dirent = (struct nffs_dirent *)fs_dirent;
+ assert(dirent != NULL && dirent->nde_inode_entry != NULL);
+ return nffs_inode_read_filename(dirent->nde_inode_entry,
+ max_len, out_name, out_name_len);
+}
+
+static int
+nffs_dirent_is_dir(const struct fs_dirent *fs_dirent)
+{
+ uint32_t id;
+ const struct nffs_dirent *dirent = (const struct nffs_dirent *)fs_dirent;
+
+ assert(dirent != NULL && dirent->nde_inode_entry != NULL);
+ id = dirent->nde_inode_entry->nie_hash_entry.nhe_id;
+ return nffs_hash_id_is_dir(id);
+}
+
+struct fs_ops nffs_ops = {
+ .f_open = nffs_open,
+ .f_close = nffs_close,
+ .f_read = nffs_read,
+ .f_write = nffs_write,
+
+ .f_seek = nffs_seek,
+ .f_getpos = nffs_getpos,
+ .f_filelen = nffs_file_len,
+
+ .f_unlink = nffs_unlink,
+ .f_rename = nffs_rename,
+ .f_mkdir = nffs_mkdir,
+
+ .f_opendir = nffs_opendir,
+ .f_readdir = nffs_readdir,
+ .f_closedir = nffs_closedir,
+
+ .f_dirent_name = nffs_dirent_name,
+ .f_dirent_is_dir = nffs_dirent_is_dir,
+
+ .f_name = "nffs"
+};
+
+/**
+ * Initializes internal nffs memory and data structures. This must be called
+ * before any nffs operations are attempted.
+ *
+ * @return 0 on success; nonzero on error.
+ */
+int
+nffs_init(void)
+{
+ int rc;
+
+ log_register("nffs", &nffs_log, &log_console_handler, NULL, LOG_LEVEL_DEBUG);
+
+ nffs_config_init();
+
+ nffs_cache_clear();
+
+ rc = os_mutex_init(&nffs_mutex);
+ if (rc != 0) {
+ return FS_EOS;
+ }
+
+ free(nffs_file_mem);
+ nffs_file_mem = malloc(
+ OS_MEMPOOL_BYTES(nffs_config.nc_num_files, sizeof (struct nffs_file)));
+ if (nffs_file_mem == NULL) {
+ return FS_ENOMEM;
+ }
+
+ free(nffs_inode_mem);
+ nffs_inode_mem = malloc(OS_MEMPOOL_BYTES(
+ nffs_config.nc_num_inodes, sizeof (struct nffs_inode_entry)));
+ if (nffs_inode_mem == NULL) {
+ return FS_ENOMEM;
+ }
+
+ free(nffs_block_entry_mem);
+ nffs_block_entry_mem = malloc(OS_MEMPOOL_BYTES(
+ nffs_config.nc_num_blocks, sizeof (struct nffs_hash_entry)));
+ if (nffs_block_entry_mem == NULL) {
+ return FS_ENOMEM;
+ }
+
+ free(nffs_cache_inode_mem);
+ nffs_cache_inode_mem = malloc(OS_MEMPOOL_BYTES(
+ nffs_config.nc_num_cache_inodes,
+ sizeof (struct nffs_cache_inode)));
+ if (nffs_cache_inode_mem == NULL) {
+ return FS_ENOMEM;
+ }
+
+ free(nffs_cache_block_mem);
+ nffs_cache_block_mem = malloc(OS_MEMPOOL_BYTES(
+ nffs_config.nc_num_cache_blocks,
+ sizeof (struct nffs_cache_block)));
+ if (nffs_cache_block_mem == NULL) {
+ return FS_ENOMEM;
+ }
+
+ free(nffs_dir_mem);
+ nffs_dir_mem = malloc(OS_MEMPOOL_BYTES(
+ nffs_config.nc_num_dirs, sizeof (struct nffs_dir)));
+ if (nffs_dir_mem == NULL) {
+ return FS_ENOMEM;
+ }
+
+ rc = nffs_misc_reset();
+ if (rc != 0) {
+ return rc;
+ }
+
+ fs_register(&nffs_ops);
+ return 0;
+}
+
+void
+nffs_pkg_init(void)
+{
+ /* do nothing */
+}
+
+#endif /* !__ZEPHYR__ */