1 /*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef ZEPHYR_LLEXT_LOADER_H
8 #define ZEPHYR_LLEXT_LOADER_H
9
10 #include <zephyr/llext/elf.h>
11 #include <stddef.h>
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16
17 /**
18 * @file
19 * @brief LLEXT ELF loader context types.
20 *
21 * The following types are used to define the context of the ELF loader
22 * used by the \ref llext subsystem.
23 *
24 * @defgroup llext_loader_apis ELF loader context
25 * @ingroup llext_apis
26 * @{
27 */
28
29 #include <zephyr/llext/llext.h>
30
31 /** @cond ignore */
32 struct llext_elf_sect_map; /* defined in llext_internal.h */
33 /** @endcond */
34
35 /**
36 * @brief Storage type for the ELF data to be loaded.
37 *
38 * This enum defines the storage type of the ELF data that will be loaded. The
39 * storage type determines which memory optimizations can be tried by the LLEXT
40 * subsystem during the load process.
41 *
42 * @note Even with the most permissive option, LLEXT might still have to copy
43 * ELF data into a separate memory region to comply with other restrictions,
44 * such as hardware memory protection and/or alignment rules.
45 * Sections such as BSS that have no space in the file will also be allocated
46 * in the LLEXT heap.
47 */
48 enum llext_storage_type {
49 /**
50 * ELF data is only available during llext_load(); even if the loader
51 * supports directly accessing the memory via llext_peek(), the buffer
52 * contents will be discarded afterwards.
53 * LLEXT will allocate copies of all required data into its heap.
54 */
55 LLEXT_STORAGE_TEMPORARY,
56 /**
57 * ELF data is stored in a *read-only* buffer that is guaranteed to be
58 * always accessible for as long as the extension is loaded. LLEXT may
59 * directly reuse constant data from the buffer, but may still allocate
60 * copies if relocations need to be applied.
61 */
62 LLEXT_STORAGE_PERSISTENT,
63 /**
64 * ELF data is stored in a *writable* memory buffer that is guaranteed
65 * to be always accessible for as long as the extension is loaded.
66 * LLEXT may freely modify and reuse data in the buffer; so, after the
67 * extension is unloaded, the contents should be re-initialized before
68 * a subsequent llext_load() call.
69 */
70 LLEXT_STORAGE_WRITABLE,
71 };
72
73 /**
74 * @brief Linkable loadable extension loader context
75 *
76 * This object is used to access the ELF file data and cache its contents
77 * while an extension is being loaded by the LLEXT subsystem. Once the
78 * extension is loaded, this object is no longer needed.
79 */
80 struct llext_loader {
81 /**
82 * @brief Optional function to prepare the loader for loading extension.
83 *
84 * @param[in] ldr Loader
85 *
86 * @returns 0 on success, or a negative error.
87 */
88 int (*prepare)(struct llext_loader *ldr);
89
90 /**
91 * @brief Function to read (copy) from the loader
92 *
93 * Copies len bytes into buf from the current position of the
94 * loader.
95 *
96 * @param[in] ldr Loader
97 * @param[in] out Output location
98 * @param[in] len Length to copy into the output location
99 *
100 * @returns 0 on success, or a negative error code.
101 */
102 int (*read)(struct llext_loader *ldr, void *out, size_t len);
103
104 /**
105 * @brief Function to seek to a new absolute location in the stream.
106 *
107 * Changes the location of the loader position to a new absolute
108 * given position.
109 *
110 * @param[in] ldr Loader
111 * @param[in] pos Position in stream to move loader
112 *
113 * @returns 0 on success, or a negative error code.
114 */
115 int (*seek)(struct llext_loader *ldr, size_t pos);
116
117 /**
118 * @brief Optional function to peek at an absolute location in the ELF.
119 *
120 * Return a pointer to the buffer at specified offset.
121 *
122 * @param[in] ldr Loader
123 * @param[in] pos Position to obtain a pointer to
124 *
125 * @returns a pointer into the buffer or `NULL` if not supported
126 */
127 void *(*peek)(struct llext_loader *ldr, size_t pos);
128
129 /**
130 * @brief Optional function to clean after the extension has been loaded or error occurred.
131 *
132 * @param[in] ldr Loader
133 */
134 void (*finalize)(struct llext_loader *ldr);
135
136 /**
137 * @brief Storage type of the underlying data accessed by this loader.
138 */
139 enum llext_storage_type storage;
140
141 /** @cond ignore */
142 elf_ehdr_t hdr;
143 elf_shdr_t sects[LLEXT_MEM_COUNT];
144 struct llext_elf_sect_map *sect_map;
145 /** @endcond */
146 };
147
148 /** @cond ignore */
llext_prepare(struct llext_loader * l)149 static inline int llext_prepare(struct llext_loader *l)
150 {
151 if (l->prepare) {
152 return l->prepare(l);
153 }
154
155 return 0;
156 }
157
llext_read(struct llext_loader * l,void * buf,size_t len)158 static inline int llext_read(struct llext_loader *l, void *buf, size_t len)
159 {
160 return l->read(l, buf, len);
161 }
162
llext_seek(struct llext_loader * l,size_t pos)163 static inline int llext_seek(struct llext_loader *l, size_t pos)
164 {
165 return l->seek(l, pos);
166 }
167
llext_peek(struct llext_loader * l,size_t pos)168 static inline void *llext_peek(struct llext_loader *l, size_t pos)
169 {
170 if (l->peek) {
171 return l->peek(l, pos);
172 }
173
174 return NULL;
175 }
176
llext_finalize(struct llext_loader * l)177 static inline void llext_finalize(struct llext_loader *l)
178 {
179 if (l->finalize) {
180 l->finalize(l);
181 }
182 }
183 /* @endcond */
184
185 /**
186 * @}
187 */
188
189 #ifdef __cplusplus
190 }
191 #endif
192
193 #endif /* ZEPHYR_LLEXT_LOADER_H */
194