|
11 | 11 | #include <zephyr/llext/elf.h> |
12 | 12 | #include <zephyr/llext/llext.h> |
13 | 13 | #include <zephyr/llext/buf_loader.h> |
| 14 | +#include <zephyr/llext/fs_loader.h> |
14 | 15 |
|
15 | 16 | #include <zephyr/logging/log.h> |
16 | 17 | LOG_MODULE_REGISTER(llext_shell, CONFIG_LLEXT_LOG_LEVEL); |
17 | 18 |
|
18 | 19 | #define LLEXT_LIST_HELP "List loaded extensions and their size in memory" |
19 | 20 |
|
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" \ |
22 | 23 | "<ext_name> <ext_hex_string>" |
23 | 24 |
|
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" \ |
26 | 27 | "<ext_name>" |
27 | 28 |
|
28 | | -#define LLEXT_LIST_SYMBOLS_HELP \ |
29 | | - "List extension symbols. Syntax:\n" \ |
| 29 | +#define LLEXT_LIST_SYMBOLS_HELP \ |
| 30 | + "List extension symbols. Syntax:\n" \ |
30 | 31 | "<ext_name>" |
31 | 32 |
|
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" \ |
34 | 35 | "<ext_name> <function_name>" |
35 | 36 |
|
| 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 | + |
36 | 44 | static int cmd_llext_list_symbols(const struct shell *sh, size_t argc, char *argv[]) |
37 | 45 | { |
38 | 46 | 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[]) |
182 | 190 | return 0; |
183 | 191 | } |
184 | 192 |
|
| 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 |
185 | 224 |
|
186 | 225 | /* clang-format off */ |
187 | 226 | SHELL_STATIC_SUBCMD_SET_CREATE(sub_llext, |
188 | 227 | 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 |
189 | 231 | SHELL_CMD_ARG(load_hex, NULL, LLEXT_LOAD_HEX_HELP, cmd_llext_load_hex, 3, 0), |
190 | 232 | SHELL_CMD_ARG(unload, &msub_llext_name, LLEXT_UNLOAD_HELP, cmd_llext_unload, 2, 0), |
191 | 233 | SHELL_CMD_ARG(list_symbols, &msub_llext_name, LLEXT_LIST_SYMBOLS_HELP, |
|
0 commit comments