[efi] Add EFI image format and basic runtime environment
[people/sha0/gpxe.git] / src / include / gpxe / uaccess.h
1 #ifndef _GPXE_UACCESS_H
2 #define _GPXE_UACCESS_H
3
4 /**
5  * @file
6  *
7  * Access to external ("user") memory
8  *
9  * gPXE often needs to transfer data between internal and external
10  * buffers.  On i386, the external buffers may require access via a
11  * different segment, and the buffer address cannot be encoded into a
12  * simple void * pointer.  The @c userptr_t type encapsulates the
13  * information needed to identify an external buffer, and the
14  * copy_to_user() and copy_from_user() functions provide methods for
15  * transferring data between internal and external buffers.
16  *
17  * Note that userptr_t is an opaque type; in particular, performing
18  * arithmetic upon a userptr_t is not allowed.
19  *
20  */
21
22 #include <stdint.h>
23 #include <string.h>
24 #include <gpxe/api.h>
25 #include <config/ioapi.h>
26
27 /**
28  * A pointer to a user buffer
29  *
30  */
31 typedef unsigned long userptr_t;
32
33 /** Equivalent of NULL for user pointers */
34 #define UNULL ( ( userptr_t ) 0 )
35
36 /**
37  * @defgroup uaccess_trivial Trivial user access API implementations
38  *
39  * User access API implementations that can be used by environments in
40  * which virtual addresses allow access to all of memory.
41  *
42  * @{
43  *
44  */
45
46 /**
47  * Convert virtual address to user pointer
48  *
49  * @v addr              Virtual address
50  * @ret userptr         User pointer
51  */
52 static inline __always_inline userptr_t
53 trivial_virt_to_user ( volatile const void *addr ) {
54         return ( ( userptr_t ) addr );
55 }
56
57 /**
58  * Convert user pointer to virtual address
59  *
60  * @v userptr           User pointer
61  * @v offset            Offset from user pointer
62  * @ret addr            Virtual address
63  *
64  * This operation is not available under all memory models.
65  */
66 static inline __always_inline void *
67 trivial_user_to_virt ( userptr_t userptr, off_t offset ) {
68         return ( ( void * ) userptr + offset );
69 }
70
71 /**
72  * Add offset to user pointer
73  *
74  * @v userptr           User pointer
75  * @v offset            Offset
76  * @ret userptr         New pointer value
77  */
78 static inline __always_inline userptr_t
79 trivial_userptr_add ( userptr_t userptr, off_t offset ) {
80         return ( userptr + offset );
81 }
82
83 /**
84  * Copy data between user buffers
85  *
86  * @v dest              Destination
87  * @v dest_off          Destination offset
88  * @v src               Source
89  * @v src_off           Source offset
90  * @v len               Length
91  */
92 static inline __always_inline void
93 trivial_memcpy_user ( userptr_t dest, off_t dest_off,
94                       userptr_t src, off_t src_off, size_t len ) {
95         memcpy ( ( ( void * ) dest + dest_off ),
96                  ( ( void * ) src + src_off ), len );
97 }
98
99 /**
100  * Copy data between user buffers, allowing for overlap
101  *
102  * @v dest              Destination
103  * @v dest_off          Destination offset
104  * @v src               Source
105  * @v src_off           Source offset
106  * @v len               Length
107  */
108 static inline __always_inline void
109 trivial_memmove_user ( userptr_t dest, off_t dest_off,
110                        userptr_t src, off_t src_off, size_t len ) {
111         memmove ( ( ( void * ) dest + dest_off ),
112                   ( ( void * ) src + src_off ), len );
113 }
114
115 /**
116  * Fill user buffer with a constant byte
117  *
118  * @v buffer            User buffer
119  * @v offset            Offset within buffer
120  * @v c                 Constant byte with which to fill
121  * @v len               Length
122  */
123 static inline __always_inline void
124 trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
125         memset ( ( ( void * ) buffer + offset ), c, len );
126 }
127
128 /**
129  * Find length of NUL-terminated string in user buffer
130  *
131  * @v buffer            User buffer
132  * @v offset            Offset within buffer
133  * @ret len             Length of string (excluding NUL)
134  */
135 static inline __always_inline size_t
136 trivial_strlen_user ( userptr_t buffer, off_t offset ) {
137         return strlen ( ( void * ) buffer + offset );
138 }
139
140 /**
141  * Find character in user buffer
142  *
143  * @v buffer            User buffer
144  * @v offset            Starting offset within buffer
145  * @v c                 Character to search for
146  * @v len               Length of user buffer
147  * @ret offset          Offset of character, or <0 if not found
148  */
149 static inline __always_inline off_t
150 trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
151         void *found;
152
153         found = memchr ( ( ( void * ) buffer + offset ), c, len );
154         return ( found ? ( found - ( void * ) buffer ) : -1 );
155 }
156
157 /** @} */
158
159 /**
160  * Calculate static inline user access API function name
161  *
162  * @v _prefix           Subsystem prefix
163  * @v _api_func         API function
164  * @ret _subsys_func    Subsystem API function
165  */
166 #define UACCESS_INLINE( _subsys, _api_func ) \
167         SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
168
169 /**
170  * Provide an user access API implementation
171  *
172  * @v _prefix           Subsystem prefix
173  * @v _api_func         API function
174  * @v _func             Implementing function
175  */
176 #define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
177         PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
178
179 /**
180  * Provide a static inline user access API implementation
181  *
182  * @v _prefix           Subsystem prefix
183  * @v _api_func         API function
184  */
185 #define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
186         PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
187
188 /* Include all architecture-independent user access API headers */
189 #include <gpxe/efi/efi_uaccess.h>
190
191 /* Include all architecture-dependent user access API headers */
192 #include <bits/uaccess.h>
193
194 /**
195  * Convert physical address to user pointer
196  *
197  * @v phys_addr         Physical address
198  * @ret userptr         User pointer
199  */
200 userptr_t phys_to_user ( unsigned long phys_addr );
201
202 /**
203  * Convert user pointer to physical address
204  *
205  * @v userptr           User pointer
206  * @v offset            Offset from user pointer
207  * @ret phys_addr       Physical address
208  */
209 unsigned long user_to_phys ( userptr_t userptr, off_t offset );
210
211 /**
212  * Convert virtual address to user pointer
213  *
214  * @v addr              Virtual address
215  * @ret userptr         User pointer
216  */
217 userptr_t virt_to_user ( volatile const void *addr );
218
219 /**
220  * Convert user pointer to virtual address
221  *
222  * @v userptr           User pointer
223  * @v offset            Offset from user pointer
224  * @ret addr            Virtual address
225  *
226  * This operation is not available under all memory models.
227  */
228 void * user_to_virt ( userptr_t userptr, off_t offset );
229
230 /**
231  * Add offset to user pointer
232  *
233  * @v userptr           User pointer
234  * @v offset            Offset
235  * @ret userptr         New pointer value
236  */
237 userptr_t userptr_add ( userptr_t userptr, off_t offset );
238
239 /**
240  * Convert virtual address to a physical address
241  *
242  * @v addr              Virtual address
243  * @ret phys_addr       Physical address
244  */
245 static inline __always_inline unsigned long
246 virt_to_phys ( volatile const void *addr ) {
247         return user_to_phys ( virt_to_user ( addr ), 0 );
248 }
249
250 /**
251  * Convert physical address to a virtual address
252  *
253  * @v addr              Virtual address
254  * @ret phys_addr       Physical address
255  *
256  * This operation is not available under all memory models.
257  */
258 static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
259         return user_to_virt ( phys_to_user ( phys_addr ), 0 );
260 }
261
262 /**
263  * Copy data between user buffers
264  *
265  * @v dest              Destination
266  * @v dest_off          Destination offset
267  * @v src               Source
268  * @v src_off           Source offset
269  * @v len               Length
270  */
271 void memcpy_user ( userptr_t dest, off_t dest_off,
272                    userptr_t src, off_t src_off, size_t len );
273
274 /**
275  * Copy data to user buffer
276  *
277  * @v dest              Destination
278  * @v dest_off          Destination offset
279  * @v src               Source
280  * @v len               Length
281  */
282 static inline __always_inline void
283 copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
284         memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
285 }
286
287 /**
288  * Copy data from user buffer
289  *
290  * @v dest              Destination
291  * @v src               Source
292  * @v src_off           Source offset
293  * @v len               Length
294  */
295 static inline __always_inline void
296 copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
297         memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
298 }
299
300 /**
301  * Copy data between user buffers, allowing for overlap
302  *
303  * @v dest              Destination
304  * @v dest_off          Destination offset
305  * @v src               Source
306  * @v src_off           Source offset
307  * @v len               Length
308  */
309 void memmove_user ( userptr_t dest, off_t dest_off,
310                     userptr_t src, off_t src_off, size_t len );
311
312 /**
313  * Fill user buffer with a constant byte
314  *
315  * @v userptr           User buffer
316  * @v offset            Offset within buffer
317  * @v c                 Constant byte with which to fill
318  * @v len               Length
319  */
320 void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
321
322 /**
323  * Find length of NUL-terminated string in user buffer
324  *
325  * @v userptr           User buffer
326  * @v offset            Offset within buffer
327  * @ret len             Length of string (excluding NUL)
328  */
329 size_t strlen_user ( userptr_t userptr, off_t offset );
330
331 /**
332  * Find character in user buffer
333  *
334  * @v userptr           User buffer
335  * @v offset            Starting offset within buffer
336  * @v c                 Character to search for
337  * @v len               Length of user buffer
338  * @ret offset          Offset of character, or <0 if not found
339  */
340 off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
341
342 #endif /* _GPXE_UACCESS_H */