llext: Add filesystem based extension loader

Added loader allowing to load extensions stored in a filesystem.

Signed-off-by: Adam Wojasinski <awojasinski@baylibre.com>
This commit is contained in:
Adam Wojasinski 2024-08-21 17:20:57 +02:00 committed by Anas Nashif
parent 93ffeced6a
commit fc114e85dd
3 changed files with 139 additions and 0 deletions

View file

@ -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 <zephyr/llext/loader.h>
#include <zephyr/fs/fs.h>
#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 */

View file

@ -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()

65
subsys/llext/fs_loader.c Normal file
View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2024 BayLibre SAS
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#include <zephyr/llext/fs_loader.h>
#include <zephyr/sys/util.h>
#include <string.h>
#include <zephyr/logging/log.h>
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;
}
}