Skip to content

Commit 420891c

Browse files
awojasinskinashif
authored andcommitted
llext: Add shell command for loading LLEXT from a filesystem
This patch extends LLEXT shell commands with support for loading LLEXT from a filesystem. Use of the command requires absolute path to the llext file. Example use: `llext load_llext hello_world /lfs/hello_world.llext` Signed-off-by: Adam Wojasinski <[email protected]>
1 parent fc114e8 commit 420891c

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

subsys/llext/shell.c

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,36 @@
1111
#include <zephyr/llext/elf.h>
1212
#include <zephyr/llext/llext.h>
1313
#include <zephyr/llext/buf_loader.h>
14+
#include <zephyr/llext/fs_loader.h>
1415

1516
#include <zephyr/logging/log.h>
1617
LOG_MODULE_REGISTER(llext_shell, CONFIG_LLEXT_LOG_LEVEL);
1718

1819
#define LLEXT_LIST_HELP "List loaded extensions and their size in memory"
1920

20-
#define LLEXT_LOAD_HEX_HELP \
21-
"Load an elf file encoded in hex directly from the shell input. Syntax:\n" \
21+
#define LLEXT_LOAD_HEX_HELP \
22+
"Load an elf file encoded in hex directly from the shell input. Syntax:\n" \
2223
"<ext_name> <ext_hex_string>"
2324

24-
#define LLEXT_UNLOAD_HELP \
25-
"Unload an extension by name. Syntax:\n" \
25+
#define LLEXT_UNLOAD_HELP \
26+
"Unload an extension by name. Syntax:\n" \
2627
"<ext_name>"
2728

28-
#define LLEXT_LIST_SYMBOLS_HELP \
29-
"List extension symbols. Syntax:\n" \
29+
#define LLEXT_LIST_SYMBOLS_HELP \
30+
"List extension symbols. Syntax:\n" \
3031
"<ext_name>"
3132

32-
#define LLEXT_CALL_FN_HELP \
33-
"Call extension function with prototype void fn(void). Syntax:\n" \
33+
#define LLEXT_CALL_FN_HELP \
34+
"Call extension function with prototype void fn(void). Syntax:\n" \
3435
"<ext_name> <function_name>"
3536

37+
#ifdef CONFIG_FILE_SYSTEM
38+
#define LLEXT_LOAD_FS_HELP \
39+
"Load an elf file directly from filesystem. Syntax:\n" \
40+
"<ext_name> <ext_llext_file_name>"
41+
42+
#endif /* CONFIG_FILE_SYSTEM */
43+
3644
static int cmd_llext_list_symbols(const struct shell *sh, size_t argc, char *argv[])
3745
{
3846
struct llext *m = llext_by_name(argv[1]);
@@ -182,10 +190,44 @@ static int cmd_llext_call_fn(const struct shell *sh, size_t argc, char *argv[])
182190
return 0;
183191
}
184192

193+
#ifdef CONFIG_FILE_SYSTEM
194+
static int cmd_llext_load_fs(const struct shell *sh, size_t argc, char *argv[])
195+
{
196+
int res;
197+
struct fs_dirent dirent;
198+
199+
res = fs_stat(argv[2], &dirent);
200+
if (res) {
201+
shell_error(sh, "Failed to obtain file %s, return code %d\n", argv[2], res);
202+
return res;
203+
}
204+
205+
if (dirent.type != FS_DIR_ENTRY_FILE) {
206+
shell_error(sh, "Not a file %s", argv[2]);
207+
return -ENOEXEC;
208+
}
209+
210+
struct llext_fs_loader fs_loader = LLEXT_FS_LOADER(argv[2]);
211+
struct llext_loader *ldr = &fs_loader.loader;
212+
struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT;
213+
struct llext *ext;
214+
215+
res = llext_load(ldr, argv[1], &ext, &ldr_parm);
216+
if (res < 0) {
217+
shell_print(sh, "Failed to load extension %s, return code %d\n", ext->name, res);
218+
return -ENOEXEC;
219+
}
220+
shell_print(sh, "Successfully loaded extension %s, addr %p\n", ext->name, ext);
221+
return 0;
222+
}
223+
#endif
185224

186225
/* clang-format off */
187226
SHELL_STATIC_SUBCMD_SET_CREATE(sub_llext,
188227
SHELL_CMD(list, NULL, LLEXT_LIST_HELP, cmd_llext_list),
228+
#ifdef CONFIG_FILE_SYSTEM
229+
SHELL_CMD_ARG(load_llext, NULL, LLEXT_LOAD_FS_HELP, cmd_llext_load_fs, 3, 0),
230+
#endif
189231
SHELL_CMD_ARG(load_hex, NULL, LLEXT_LOAD_HEX_HELP, cmd_llext_load_hex, 3, 0),
190232
SHELL_CMD_ARG(unload, &msub_llext_name, LLEXT_UNLOAD_HELP, cmd_llext_unload, 2, 0),
191233
SHELL_CMD_ARG(list_symbols, &msub_llext_name, LLEXT_LIST_SYMBOLS_HELP,

0 commit comments

Comments
 (0)