1 /*
2  * Copyright (c) 2023 Intel Corporation
3  * Copyright (c) 2024 Schneider Electric
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_LLEXT_H
9 #define ZEPHYR_LLEXT_H
10 
11 #include <zephyr/sys/slist.h>
12 #include <zephyr/llext/elf.h>
13 #include <zephyr/llext/symbol.h>
14 #include <zephyr/kernel.h>
15 #include <sys/types.h>
16 #include <stdbool.h>
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /**
23  * @file
24  * @brief Support for linkable loadable extensions
25  *
26  * This file describes the APIs for loading and interacting with Linkable
27  * Loadable Extensions (LLEXTs) in Zephyr.
28  *
29  * @defgroup llext_apis Linkable loadable extensions
30  * @since 3.5
31  * @version 0.1.0
32  * @ingroup os_services
33  * @{
34  */
35 
36 /**
37  * @brief List of memory regions stored or referenced in the LLEXT subsystem
38  *
39  * This enum lists the different types of memory regions that are used by the
40  * LLEXT subsystem. The names match common ELF file section names; but note
41  * that at load time multiple ELF sections with similar flags may be merged
42  * together into a single memory region.
43  */
44 enum llext_mem {
45 	LLEXT_MEM_TEXT,         /**< Executable code */
46 	LLEXT_MEM_DATA,         /**< Initialized data */
47 	LLEXT_MEM_RODATA,       /**< Read-only data */
48 	LLEXT_MEM_BSS,          /**< Uninitialized data */
49 	LLEXT_MEM_EXPORT,       /**< Exported symbol table */
50 	LLEXT_MEM_SYMTAB,       /**< Symbol table */
51 	LLEXT_MEM_STRTAB,       /**< Symbol name strings */
52 	LLEXT_MEM_SHSTRTAB,     /**< Section name strings */
53 	LLEXT_MEM_PREINIT,      /**< Array of early setup functions */
54 	LLEXT_MEM_INIT,         /**< Array of setup functions */
55 	LLEXT_MEM_FINI,         /**< Array of cleanup functions */
56 
57 	LLEXT_MEM_COUNT,        /**< Number of regions managed by LLEXT */
58 };
59 
60 /** @cond ignore */
61 
62 /* Number of memory partitions used by LLEXT */
63 #define LLEXT_MEM_PARTITIONS (LLEXT_MEM_BSS+1)
64 
65 struct llext_loader;
66 /** @endcond */
67 
68 /* Maximim number of dependency LLEXTs */
69 #define LLEXT_MAX_DEPENDENCIES 8
70 
71 /**
72  * @brief Structure describing a linkable loadable extension
73  *
74  * This structure holds the data for a loaded extension. It is created by the
75  * @ref llext_load function and destroyed by the @ref llext_unload function.
76  */
77 struct llext {
78 	/** @cond ignore */
79 	sys_snode_t _llext_list;
80 
81 #ifdef CONFIG_USERSPACE
82 	struct k_mem_partition mem_parts[LLEXT_MEM_PARTITIONS];
83 	struct k_mem_domain mem_domain;
84 #endif
85 
86 	/** @endcond */
87 
88 	/** Name of the llext */
89 	char name[16];
90 
91 	/** Lookup table of memory regions */
92 	void *mem[LLEXT_MEM_COUNT];
93 
94 	/** Is the memory for this region allocated on heap? */
95 	bool mem_on_heap[LLEXT_MEM_COUNT];
96 
97 	/** Size of each stored region */
98 	size_t mem_size[LLEXT_MEM_COUNT];
99 
100 	/** Total llext allocation size */
101 	size_t alloc_size;
102 
103 	/**
104 	 * Table of all global symbols in the extension; used internally as
105 	 * part of the linking process. E.g. if the extension is built out of
106 	 * several files, if any symbols are referenced between files, this
107 	 * table will be used to link them.
108 	 */
109 	struct llext_symtable sym_tab;
110 
111 	/**
112 	 * Table of symbols exported by the llext via @ref LL_EXTENSION_SYMBOL.
113 	 * This can be used in the main Zephyr binary to find symbols in the
114 	 * extension.
115 	 */
116 	struct llext_symtable exp_tab;
117 
118 	/** Extension use counter, prevents unloading while in use */
119 	unsigned int use_count;
120 
121 	/** Array of extensions, whose symbols this extension accesses */
122 	struct llext *dependency[LLEXT_MAX_DEPENDENCIES];
123 
124 	/** @cond ignore */
125 	unsigned int sect_cnt;
126 	elf_shdr_t *sect_hdrs;
127 	bool sect_hdrs_on_heap;
128 	bool mmu_permissions_set;
129 	/** @endcond */
130 };
131 
llext_section_headers(const struct llext * ext)132 static inline const elf_shdr_t *llext_section_headers(const struct llext *ext)
133 {
134 	return ext->sect_hdrs;
135 }
136 
llext_section_count(const struct llext * ext)137 static inline unsigned int llext_section_count(const struct llext *ext)
138 {
139 	return ext->sect_cnt;
140 }
141 
142 /**
143  * @brief Advanced llext_load parameters
144  *
145  * This structure contains advanced parameters for @ref llext_load.
146  */
147 struct llext_load_param {
148 	/** Perform local relocation */
149 	bool relocate_local;
150 
151 	/**
152 	 * Use the virtual symbol addresses from the ELF, not addresses within
153 	 * the memory buffer, when calculating relocation targets. It also
154 	 * means, that the application will take care to place the extension at
155 	 * those pre-defined addresses, so the LLEXT core doesn't have to do any
156 	 * allocation and copying internally. Any MMU permission adjustment will
157 	 * be done by the application too.
158 	 */
159 	bool pre_located;
160 
161 	/**
162 	 * Extensions can implement custom ELF sections to be loaded in specific
163 	 * memory regions, detached from other sections of compatible types.
164 	 * This optional callback checks whether a section should be detached.
165 	 */
166 	bool (*section_detached)(const elf_shdr_t *shdr);
167 
168 	/**
169 	 * Keep the ELF section data in memory after loading the extension. This
170 	 * is needed to use some of the functions in @ref llext_inspect_apis.
171 	 *
172 	 * @note Related memory must be freed by @ref llext_free_inspection_data
173 	 *       before the extension can be unloaded via @ref llext_unload.
174 	 */
175 	bool keep_section_info;
176 };
177 
178 /** Default initializer for @ref llext_load_param */
179 #define LLEXT_LOAD_PARAM_DEFAULT { .relocate_local = true, }
180 
181 /**
182  * @brief Find an llext by name
183  *
184  * @param[in] name String name of the llext
185  * @returns a pointer to the @ref llext, or `NULL` if not found
186  */
187 struct llext *llext_by_name(const char *name);
188 
189 /**
190  * @brief Iterate over all loaded extensions
191  *
192  * Calls a provided callback function for each registered extension or until the
193  * callback function returns a non-0 value.
194  *
195  * @param[in] fn callback function
196  * @param[in] arg a private argument to be provided to the callback function
197  * @returns the value returned by the last callback invocation
198  * @retval 0 if no extensions are registered
199  */
200 int llext_iterate(int (*fn)(struct llext *ext, void *arg), void *arg);
201 
202 /**
203  * @brief Load and link an extension
204  *
205  * Loads relevant ELF data into memory and provides a structure to work with it.
206  *
207  * @param[in] loader An extension loader that provides input data and context
208  * @param[in] name A string identifier for the extension
209  * @param[out] ext Pointer to the newly allocated @ref llext structure
210  * @param[in] ldr_parm Optional advanced load parameters (may be `NULL`)
211  *
212  * @returns the previous extension use count on success, or a negative error code.
213  * @retval -ENOMEM Not enough memory
214  * @retval -ENOEXEC Invalid ELF stream
215  * @retval -ENOTSUP Unsupported ELF features
216  */
217 int llext_load(struct llext_loader *loader, const char *name, struct llext **ext,
218 	       const struct llext_load_param *ldr_parm);
219 
220 /**
221  * @brief Unload an extension
222  *
223  * @param[in] ext Extension to unload
224  */
225 int llext_unload(struct llext **ext);
226 
227 /**
228  * @brief Free any inspection-related memory for the specified loader and extension.
229  *
230  * This is only required if inspection data was requested at load time by
231  * setting @ref llext_load_param.keep_section_info; otherwise, this call will
232  * be a no-op.
233  *
234  * @param[in] ldr Extension loader
235  * @param[in] ext Extension
236  * @returns 0 on success, or a negative error code.
237  */
238 int llext_free_inspection_data(struct llext_loader *ldr, struct llext *ext);
239 
240 /** @brief Entry point function signature for an extension. */
241 typedef void (*llext_entry_fn_t)(void *user_data);
242 
243 /**
244  * @brief Calls bringup functions for an extension.
245  *
246  * Must be called before accessing any symbol in the extension. Will execute
247  * the extension's own setup functions in the caller context.
248  * @see llext_bootstrap
249  *
250  * @param[in] ext Extension to initialize.
251  * @returns 0 on success, or a negative error code.
252  * @retval -EFAULT A relocation issue was detected
253  */
254 int llext_bringup(struct llext *ext);
255 
256 /**
257  * @brief Calls teardown functions for an extension.
258  *
259  * Will execute the extension's own cleanup functions in the caller context.
260  * After this function completes, the extension is no longer usable and must be
261  * fully unloaded with @ref llext_unload.
262  * @see llext_bootstrap
263  *
264  * @param[in] ext Extension to de-initialize.
265  * @returns 0 on success, or a negative error code.
266  * @retval -EFAULT A relocation issue was detected
267  */
268 int llext_teardown(struct llext *ext);
269 
270 /**
271  * @brief Bring up, execute, and teardown an extension.
272  *
273  * Calls the extension's own setup functions, an additional entry point and
274  * the extension's cleanup functions in the current thread context.
275  *
276  * This is a convenient wrapper around @ref llext_bringup and @ref
277  * llext_teardown that matches the @ref k_thread_entry_t signature, so it can
278  * be directly started as a new user or kernel thread via @ref k_thread_create.
279  *
280  * @param[in] ext Extension to execute. Passed as `p1` in @ref k_thread_create.
281  * @param[in] entry_fn Main entry point of the thread after performing
282  *                     extension setup. Passed as `p2` in @ref k_thread_create.
283  * @param[in] user_data Argument passed to @a entry_fn. Passed as `p3` in
284  *                      @ref k_thread_create.
285  */
286 void llext_bootstrap(struct llext *ext, llext_entry_fn_t entry_fn, void *user_data);
287 
288 /**
289  * @brief Get pointers to setup or cleanup functions for an extension.
290  *
291  * This syscall can be used to get the addresses of all the functions that
292  * have to be called for full extension setup or cleanup.
293  *
294  * @see llext_bootstrap
295  *
296  * @param[in]    ext Extension to initialize.
297  * @param[in]    is_init `true` to get functions to be called at setup time,
298  *                       `false` to get the cleanup ones.
299  * @param[inout] buf Buffer to store the function pointers in. Can be `NULL`
300  *                   to only get the minimum required size.
301  * @param[in]    size Allocated size of the buffer in bytes.
302  * @returns the size used by the array in bytes, or a negative error code.
303  * @retval -EFAULT A relocation issue was detected
304  * @retval -ENOMEM Array does not fit in the allocated buffer
305  */
306 __syscall ssize_t llext_get_fn_table(struct llext *ext, bool is_init, void *buf, size_t size);
307 
308 /**
309  * @brief Find the address for an arbitrary symbol.
310  *
311  * Searches for a symbol address, either in the list of symbols exported by
312  * the main Zephyr binary or in an extension's symbol table.
313  *
314  * @param[in] sym_table Symbol table to lookup symbol in, or `NULL` to search
315  *                      in the main Zephyr symbol table
316  * @param[in] sym_name Symbol name to find
317  *
318  * @returns the address of symbol in memory, or `NULL` if not found
319  */
320 const void *llext_find_sym(const struct llext_symtable *sym_table, const char *sym_name);
321 
322 /**
323  * @brief Call a function by name.
324  *
325  * Expects a symbol representing a `void fn(void)` style function exists
326  * and may be called.
327  *
328  * @param[in] ext Extension to call function in
329  * @param[in] sym_name Function name (exported symbol) in the extension
330  *
331  * @retval 0 Success
332  * @retval -ENOENT Symbol name not found
333  */
334 int llext_call_fn(struct llext *ext, const char *sym_name);
335 
336 /**
337  * @brief Add an extension to a memory domain.
338  *
339  * Allows an extension to be executed in user mode threads when memory
340  * protection hardware is enabled by adding memory partitions covering the
341  * extension's memory regions to a memory domain.
342  *
343  * @param[in] ext Extension to add to a domain
344  * @param[in] domain Memory domain to add partitions to
345  *
346  * @returns 0 on success, or a negative error code.
347  * @retval -ENOSYS Option @kconfig{CONFIG_USERSPACE} is not enabled or supported
348  */
349 int llext_add_domain(struct llext *ext, struct k_mem_domain *domain);
350 
351 /**
352  * @brief Architecture specific opcode update function
353  *
354  * ELF files include sections describing a series of _relocations_, which are
355  * instructions on how to rewrite opcodes given the actual placement of some
356  * symbolic data such as a section, function, or object. These relocations
357  * are architecture specific and each architecture supporting LLEXT must
358  * implement this.
359  * Arguments sym_base_addr, sym_name can be computed from the sym parameter,
360  * but these parameters are provided redundantly to increase efficiency.
361  *
362  * @param[in] ldr Extension loader
363  * @param[in] ext Extension being relocated refers to
364  * @param[in] rel Relocation data provided by ELF
365  * @param[in] shdr Header of the ELF section currently being located
366  * @retval 0 Success
367  * @retval -ENOTSUP Unsupported relocation
368  * @retval -ENOEXEC Invalid relocation
369  */
370 int arch_elf_relocate(struct llext_loader *ldr, struct llext *ext, elf_rela_t *rel,
371 		      const elf_shdr_t *shdr);
372 
373 /**
374  * @brief Locates an ELF section in the file.
375  *
376  * Searches for a section by name in the ELF file and returns its offset.
377  *
378  * @param[in] loader Extension loader data and context
379  * @param[in] search_name Section name to search for
380  * @returns the section offset or a negative error code
381  */
382 ssize_t llext_find_section(struct llext_loader *loader, const char *search_name);
383 
384 /**
385  * @brief Extract ELF section header by name.
386  *
387  * Searches for a section by name in the ELF file and retrieves its full header.
388  *
389  * @param[in] loader Extension loader data and context
390  * @param[in] ext Extension to be searched
391  * @param[in] search_name Section name to search for
392  * @param[out] shdr Buffer for the section header
393  * @retval 0 Success
394  * @retval -ENOTSUP "peek" method not supported
395  * @retval -ENOENT section not found
396  */
397 int llext_get_section_header(struct llext_loader *loader, struct llext *ext,
398 			     const char *search_name, elf_shdr_t *shdr);
399 
400 /**
401  * @brief Architecture specific function for local binding relocations
402  *
403  * @param[in] loader Extension loader data and context
404  * @param[in] ext Extension to call function in
405  * @param[in] rel Relocation data provided by elf
406  * @param[in] sym Corresponding symbol table entry
407  * @param[in] rel_addr Address where relocation should be performed
408  * @param[in] ldr_parm Loader parameters
409  */
410 void arch_elf_relocate_local(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel,
411 			     const elf_sym_t *sym, uint8_t *rel_addr,
412 			     const struct llext_load_param *ldr_parm);
413 
414 /**
415  * @brief Architecture specific function for global binding relocations
416  *
417  * @param[in] loader Extension loader data and context
418  * @param[in] ext Extension to call function in
419  * @param[in] rel Relocation data provided by elf
420  * @param[in] sym Corresponding symbol table entry
421  * @param[in] rel_addr Address where relocation should be performed
422  * @param[in] link_addr target address for table-based relocations
423  */
424 void arch_elf_relocate_global(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel,
425 			      const elf_sym_t *sym, uint8_t *rel_addr, const void *link_addr);
426 
427 /**
428  * @}
429  */
430 
431 #ifdef __cplusplus
432 }
433 #endif
434 
435 #include <zephyr/syscalls/llext.h>
436 
437 #endif /* ZEPHYR_LLEXT_H */
438