Line data Source code
1 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_priv.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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : void (*finalize)(struct llext_loader *ldr);
135 :
136 : /**
137 : * @brief Storage type of the underlying data accessed by this loader.
138 : */
139 1 : 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 */
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 :
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 :
163 : static inline int llext_seek(struct llext_loader *l, size_t pos)
164 : {
165 : return l->seek(l, pos);
166 : }
167 :
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 :
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 */
|