diff --git a/include/zephyr/llext/fs_loader.h b/include/zephyr/llext/fs_loader.h new file mode 100644 index 00000000000..9cb41851cb0 --- /dev/null +++ b/include/zephyr/llext/fs_loader.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LLEXT_FS_LOADER_H +#define ZEPHYR_LLEXT_FS_LOADER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @brief LLEXT filesystem loader implementation. + * + * @addtogroup llext_loader_apis + * @{ + */ + +/** + * @brief Implementation of @ref llext_loader that reads from a filesystem. + */ +struct llext_fs_loader { + /** Extension loader */ + struct llext_loader loader; + + /** @cond ignore */ + bool is_open; + const char *name; + struct fs_file_t file; + /** @endcond */ +}; + +/** @cond ignore */ +int llext_fs_prepare(struct llext_loader *ldr); +int llext_fs_read(struct llext_loader *ldr, void *buf, size_t len); +int llext_fs_seek(struct llext_loader *ldr, size_t pos); +void llext_fs_finalize(struct llext_loader *ldr); +/** @endcond */ + +/** + * @brief Initializer for an llext_fs_loader structure + * + * @param _filename Absolute path to the extension file. + */ +#define LLEXT_FS_LOADER(_filename) \ + { \ + .loader = \ + { \ + .prepare = llext_fs_prepare, \ + .read = llext_fs_read, \ + .seek = llext_fs_seek, \ + .peek = NULL, \ + .finalize = llext_fs_finalize, \ + }, \ + .is_open = false, \ + .name = (_filename), \ + } + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LLEXT_FS_LOADER_H */ diff --git a/subsys/llext/CMakeLists.txt b/subsys/llext/CMakeLists.txt index 415e012a3d2..835eae86b19 100644 --- a/subsys/llext/CMakeLists.txt +++ b/subsys/llext/CMakeLists.txt @@ -11,6 +11,7 @@ if(CONFIG_LLEXT) llext_link.c llext_export.c buf_loader.c + fs_loader.c ) zephyr_library_sources_ifdef(CONFIG_LLEXT_SHELL shell.c) endif() diff --git a/subsys/llext/fs_loader.c b/subsys/llext/fs_loader.c new file mode 100644 index 00000000000..c555c54a52b --- /dev/null +++ b/subsys/llext/fs_loader.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(llext_fs_loader, CONFIG_LLEXT_LOG_LEVEL); + +int llext_fs_prepare(struct llext_loader *l) +{ + int ret = 0; + struct llext_fs_loader *fs_l = CONTAINER_OF(l, struct llext_fs_loader, loader); + + fs_file_t_init(&fs_l->file); + + ret = fs_open(&fs_l->file, fs_l->name, FS_O_READ); + if (ret != 0) { + LOG_DBG("Failed opening a file: %d", ret); + return ret; + } + + fs_l->is_open = true; + return 0; +} + +int llext_fs_read(struct llext_loader *l, void *buf, size_t len) +{ + int ret = 0; + struct llext_fs_loader *fs_l = CONTAINER_OF(l, struct llext_fs_loader, loader); + + if (fs_l->is_open) { + ret = fs_read(&fs_l->file, buf, len); + } else { + ret = -EINVAL; + } + + return ret == len ? 0 : -EINVAL; +} + +int llext_fs_seek(struct llext_loader *l, size_t pos) +{ + struct llext_fs_loader *fs_l = CONTAINER_OF(l, struct llext_fs_loader, loader); + + if (fs_l->is_open) { + return fs_seek(&fs_l->file, pos, FS_SEEK_SET); + } else { + return -EINVAL; + } +} + +void llext_fs_finalize(struct llext_loader *l) +{ + struct llext_fs_loader *fs_l = CONTAINER_OF(l, struct llext_fs_loader, loader); + + if (fs_l->is_open) { + fs_close(&fs_l->file); + fs_l->is_open = false; + } +}