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 Linkable loadable extension loader context
37  *
38  * This object is used to access the ELF file data and cache its contents
39  * while an extension is being loaded by the LLEXT subsystem. Once the
40  * extension is loaded, this object is no longer needed.
41  */
42 struct llext_loader {
43 	/**
44 	 * @brief Optional function to prepare the loader for loading extension.
45 	 *
46 	 * @param[in] ldr Loader
47 	 *
48 	 * @returns 0 on success, or a negative error.
49 	 */
50 	int (*prepare)(struct llext_loader *ldr);
51 
52 	/**
53 	 * @brief Function to read (copy) from the loader
54 	 *
55 	 * Copies len bytes into buf from the current position of the
56 	 * loader.
57 	 *
58 	 * @param[in] ldr Loader
59 	 * @param[in] out Output location
60 	 * @param[in] len Length to copy into the output location
61 	 *
62 	 * @returns 0 on success, or a negative error code.
63 	 */
64 	int (*read)(struct llext_loader *ldr, void *out, size_t len);
65 
66 	/**
67 	 * @brief Function to seek to a new absolute location in the stream.
68 	 *
69 	 * Changes the location of the loader position to a new absolute
70 	 * given position.
71 	 *
72 	 * @param[in] ldr Loader
73 	 * @param[in] pos Position in stream to move loader
74 	 *
75 	 * @returns 0 on success, or a negative error code.
76 	 */
77 	int (*seek)(struct llext_loader *ldr, size_t pos);
78 
79 	/**
80 	 * @brief Optional function to peek at an absolute location in the ELF.
81 	 *
82 	 * Return a pointer to the buffer at specified offset.
83 	 *
84 	 * @param[in] ldr Loader
85 	 * @param[in] pos Position to obtain a pointer to
86 	 *
87 	 * @returns a pointer into the buffer or `NULL` if not supported
88 	 */
89 	void *(*peek)(struct llext_loader *ldr, size_t pos);
90 
91 	/**
92 	 * @brief Optional function to clean after the extension has been loaded or error occurred.
93 	 *
94 	 * @param[in] ldr Loader
95 	 */
96 	void (*finalize)(struct llext_loader *ldr);
97 
98 	/** @cond ignore */
99 	elf_ehdr_t hdr;
100 	elf_shdr_t sects[LLEXT_MEM_COUNT];
101 	struct llext_elf_sect_map *sect_map;
102 	/** @endcond */
103 };
104 
105 /** @cond ignore */
llext_prepare(struct llext_loader * l)106 static inline int llext_prepare(struct llext_loader *l)
107 {
108 	if (l->prepare) {
109 		return l->prepare(l);
110 	}
111 
112 	return 0;
113 }
114 
llext_read(struct llext_loader * l,void * buf,size_t len)115 static inline int llext_read(struct llext_loader *l, void *buf, size_t len)
116 {
117 	return l->read(l, buf, len);
118 }
119 
llext_seek(struct llext_loader * l,size_t pos)120 static inline int llext_seek(struct llext_loader *l, size_t pos)
121 {
122 	return l->seek(l, pos);
123 }
124 
llext_peek(struct llext_loader * l,size_t pos)125 static inline void *llext_peek(struct llext_loader *l, size_t pos)
126 {
127 	if (l->peek) {
128 		return l->peek(l, pos);
129 	}
130 
131 	return NULL;
132 }
133 
llext_finalize(struct llext_loader * l)134 static inline void llext_finalize(struct llext_loader *l)
135 {
136 	if (l->finalize) {
137 		l->finalize(l);
138 	}
139 }
140 /* @endcond */
141 
142 /**
143  * @}
144  */
145 
146 #ifdef __cplusplus
147 }
148 #endif
149 
150 #endif /* ZEPHYR_LLEXT_LOADER_H */
151