iPXE
uaccess.h
Go to the documentation of this file.
1 #ifndef _IPXE_UACCESS_H
2 #define _IPXE_UACCESS_H
3 
4 /**
5  * @file
6  *
7  * Access to external ("user") memory
8  *
9  * iPXE 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 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
23 
24 #include <stdint.h>
25 #include <string.h>
26 #include <ipxe/api.h>
27 #include <config/ioapi.h>
28 
29 /**
30  * A pointer to a user buffer
31  *
32  */
33 typedef unsigned long userptr_t;
34 
35 /** Equivalent of NULL for user pointers */
36 #define UNULL ( ( userptr_t ) 0 )
37 
38 /**
39  * @defgroup uaccess_trivial Trivial user access API implementations
40  *
41  * User access API implementations that can be used by environments in
42  * which virtual addresses allow access to all of memory.
43  *
44  * @{
45  *
46  */
47 
48 /**
49  * Convert virtual address to user pointer
50  *
51  * @v addr Virtual address
52  * @ret userptr User pointer
53  */
54 static inline __always_inline userptr_t
55 trivial_virt_to_user ( volatile const void *addr ) {
56  return ( ( userptr_t ) addr );
57 }
58 
59 /**
60  * Convert user pointer to virtual address
61  *
62  * @v userptr User pointer
63  * @v offset Offset from user pointer
64  * @ret addr Virtual address
65  *
66  * This operation is not available under all memory models.
67  */
68 static inline __always_inline void *
70  return ( ( void * ) userptr + offset );
71 }
72 
73 /**
74  * Add offset to user pointer
75  *
76  * @v userptr User pointer
77  * @v offset Offset
78  * @ret userptr New pointer value
79  */
80 static inline __always_inline userptr_t
82  return ( userptr + offset );
83 }
84 
85 /**
86  * Subtract user pointers
87  *
88  * @v userptr User pointer
89  * @v subtrahend User pointer to be subtracted
90  * @ret offset Offset
91  */
92 static inline __always_inline off_t
94  return ( userptr - subtrahend );
95 }
96 
97 /**
98  * Copy data between user buffers
99  *
100  * @v dest Destination
101  * @v dest_off Destination offset
102  * @v src Source
103  * @v src_off Source offset
104  * @v len Length
105  */
106 static inline __always_inline void
108  userptr_t src, off_t src_off, size_t len ) {
109  memcpy ( ( ( void * ) dest + dest_off ),
110  ( ( void * ) src + src_off ), len );
111 }
112 
113 /**
114  * Copy data between user buffers, allowing for overlap
115  *
116  * @v dest Destination
117  * @v dest_off Destination offset
118  * @v src Source
119  * @v src_off Source offset
120  * @v len Length
121  */
122 static inline __always_inline void
124  userptr_t src, off_t src_off, size_t len ) {
125  memmove ( ( ( void * ) dest + dest_off ),
126  ( ( void * ) src + src_off ), len );
127 }
128 
129 /**
130  * Compare data between user buffers
131  *
132  * @v first First buffer
133  * @v first_off First buffer offset
134  * @v second Second buffer
135  * @v second_off Second buffer offset
136  * @v len Length
137  * @ret diff Difference
138  */
139 static inline __always_inline int
141  userptr_t second, off_t second_off, size_t len ) {
142  return memcmp ( ( ( void * ) first + first_off ),
143  ( ( void * ) second + second_off ), len );
144 }
145 
146 /**
147  * Fill user buffer with a constant byte
148  *
149  * @v buffer User buffer
150  * @v offset Offset within buffer
151  * @v c Constant byte with which to fill
152  * @v len Length
153  */
154 static inline __always_inline void
156  memset ( ( ( void * ) buffer + offset ), c, len );
157 }
158 
159 /**
160  * Find length of NUL-terminated string in user buffer
161  *
162  * @v buffer User buffer
163  * @v offset Offset within buffer
164  * @ret len Length of string (excluding NUL)
165  */
166 static inline __always_inline size_t
168  return strlen ( ( void * ) buffer + offset );
169 }
170 
171 /**
172  * Find character in user buffer
173  *
174  * @v buffer User buffer
175  * @v offset Starting offset within buffer
176  * @v c Character to search for
177  * @v len Length of user buffer
178  * @ret offset Offset of character, or <0 if not found
179  */
180 static inline __always_inline off_t
182  void *found;
183 
184  found = memchr ( ( ( void * ) buffer + offset ), c, len );
185  return ( found ? ( found - ( void * ) buffer ) : -1 );
186 }
187 
188 /** @} */
189 
190 /**
191  * Calculate static inline user access API function name
192  *
193  * @v _prefix Subsystem prefix
194  * @v _api_func API function
195  * @ret _subsys_func Subsystem API function
196  */
197 #define UACCESS_INLINE( _subsys, _api_func ) \
198  SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
199 
200 /**
201  * Provide an user access API implementation
202  *
203  * @v _prefix Subsystem prefix
204  * @v _api_func API function
205  * @v _func Implementing function
206  */
207 #define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
208  PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
209 
210 /**
211  * Provide a static inline user access API implementation
212  *
213  * @v _prefix Subsystem prefix
214  * @v _api_func API function
215  */
216 #define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
217  PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
218 
219 /* Include all architecture-independent user access API headers */
220 #include <ipxe/efi/efi_uaccess.h>
222 
223 /* Include all architecture-dependent user access API headers */
224 #include <bits/uaccess.h>
225 
226 /**
227  * Convert physical address to user pointer
228  *
229  * @v phys_addr Physical address
230  * @ret userptr User pointer
231  */
232 userptr_t phys_to_user ( unsigned long phys_addr );
233 
234 /**
235  * Convert user pointer to physical address
236  *
237  * @v userptr User pointer
238  * @v offset Offset from user pointer
239  * @ret phys_addr Physical address
240  */
241 unsigned long user_to_phys ( userptr_t userptr, off_t offset );
242 
243 /**
244  * Convert virtual address to user pointer
245  *
246  * @v addr Virtual address
247  * @ret userptr User pointer
248  */
249 userptr_t virt_to_user ( volatile const void *addr );
250 
251 /**
252  * Convert user pointer to virtual address
253  *
254  * @v userptr User pointer
255  * @v offset Offset from user pointer
256  * @ret addr Virtual address
257  *
258  * This operation is not available under all memory models.
259  */
260 void * user_to_virt ( userptr_t userptr, off_t offset );
261 
262 /**
263  * Add offset to user pointer
264  *
265  * @v userptr User pointer
266  * @v offset Offset
267  * @ret userptr New pointer value
268  */
270 
271 /**
272  * Subtract user pointers
273  *
274  * @v userptr User pointer
275  * @v subtrahend User pointer to be subtracted
276  * @ret offset Offset
277  */
279 
280 /**
281  * Convert virtual address to a physical address
282  *
283  * @v addr Virtual address
284  * @ret phys_addr Physical address
285  */
286 static inline __always_inline unsigned long
287 virt_to_phys ( volatile const void *addr ) {
288  return user_to_phys ( virt_to_user ( addr ), 0 );
289 }
290 
291 /**
292  * Convert physical address to a virtual address
293  *
294  * @v addr Virtual address
295  * @ret phys_addr Physical address
296  *
297  * This operation is not available under all memory models.
298  */
299 static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
300  return user_to_virt ( phys_to_user ( phys_addr ), 0 );
301 }
302 
303 /**
304  * Copy data between user buffers
305  *
306  * @v dest Destination
307  * @v dest_off Destination offset
308  * @v src Source
309  * @v src_off Source offset
310  * @v len Length
311  */
313  userptr_t src, off_t src_off, size_t len );
314 
315 /**
316  * Copy data to user buffer
317  *
318  * @v dest Destination
319  * @v dest_off Destination offset
320  * @v src Source
321  * @v len Length
322  */
323 static inline __always_inline void
324 copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
326 }
327 
328 /**
329  * Copy data from user buffer
330  *
331  * @v dest Destination
332  * @v src Source
333  * @v src_off Source offset
334  * @v len Length
335  */
336 static inline __always_inline void
338  memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
339 }
340 
341 /**
342  * Copy data between user buffers, allowing for overlap
343  *
344  * @v dest Destination
345  * @v dest_off Destination offset
346  * @v src Source
347  * @v src_off Source offset
348  * @v len Length
349  */
351  userptr_t src, off_t src_off, size_t len );
352 
353 /**
354  * Compare data between user buffers
355  *
356  * @v first First buffer
357  * @v first_off First buffer offset
358  * @v second Second buffer
359  * @v second_off Second buffer offset
360  * @v len Length
361  * @ret diff Difference
362  */
364  userptr_t second, off_t second_off, size_t len );
365 
366 /**
367  * Fill user buffer with a constant byte
368  *
369  * @v userptr User buffer
370  * @v offset Offset within buffer
371  * @v c Constant byte with which to fill
372  * @v len Length
373  */
374 void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
375 
376 /**
377  * Find length of NUL-terminated string in user buffer
378  *
379  * @v userptr User buffer
380  * @v offset Offset within buffer
381  * @ret len Length of string (excluding NUL)
382  */
383 size_t strlen_user ( userptr_t userptr, off_t offset );
384 
385 /**
386  * Find character in user buffer
387  *
388  * @v userptr User buffer
389  * @v offset Starting offset within buffer
390  * @v c Character to search for
391  * @v len Length of user buffer
392  * @ret offset Offset of character, or <0 if not found
393  */
394 off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
395 
396 #endif /* _IPXE_UACCESS_H */
static __always_inline int off_t userptr_t off_t second_off
Definition: librm.h:166
static const void * src
Definition: string.h:47
static __always_inline size_t trivial_strlen_user(userptr_t buffer, off_t offset)
Find length of NUL-terminated string in user buffer.
Definition: uaccess.h:167
static __always_inline void off_t int c
Definition: librm.h:173
iPXE internal APIs
static __always_inline int trivial_memcmp_user(userptr_t first, off_t first_off, userptr_t second, off_t second_off, size_t len)
Compare data between user buffers.
Definition: uaccess.h:140
uint32_t first
First block in range.
Definition: pccrr.h:14
static __always_inline void * trivial_user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
Definition: uaccess.h:69
off_t memchr_user(userptr_t userptr, off_t offset, int c, size_t len)
Find character in user buffer.
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
iPXE user access API for Linux
static __always_inline int off_t first_off
Definition: librm.h:166
static __always_inline userptr_t trivial_userptr_add(userptr_t userptr, off_t offset)
Add offset to user pointer.
Definition: uaccess.h:81
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
static __always_inline void trivial_memmove_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers, allowing for overlap.
Definition: uaccess.h:123
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
static __always_inline off_t trivial_memchr_user(userptr_t buffer, off_t offset, int c, size_t len)
Find character in user buffer.
Definition: uaccess.h:181
void * memchr(const void *src, int character, size_t len)
Find character within a memory region.
Definition: string.c:135
off_t userptr_sub(userptr_t userptr, userptr_t subtrahend)
Subtract user pointers.
static __always_inline void * phys_to_virt(unsigned long phys_addr)
Convert physical address to a virtual address.
Definition: uaccess.h:299
void memset_user(userptr_t userptr, off_t offset, int c, size_t len)
Fill user buffer with a constant byte.
userptr_t userptr_add(userptr_t userptr, off_t offset)
Add offset to user pointer.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint32_t userptr_t
A pointer to a user buffer.
Definition: libkir.h:159
static __always_inline void off_t userptr_t off_t src_off
Definition: librm.h:152
#define __always_inline
Declare a function to be always inline.
Definition: compiler.h:611
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
iPXE user access API for EFI
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * memmove(void *dest, const void *src, size_t len) __nonnull
static __always_inline void off_t dest_off
Definition: librm.h:152
static __always_inline off_t trivial_userptr_sub(userptr_t userptr, userptr_t subtrahend)
Subtract user pointers.
Definition: uaccess.h:93
size_t strlen_user(userptr_t userptr, off_t offset)
Find length of NUL-terminated string in user buffer.
signed long off_t
Definition: stdint.h:8
I/O API configuration.
int memcmp_user(userptr_t first, off_t first_off, userptr_t second, off_t second_off, size_t len)
Compare data between user buffers.
u32 addr
Definition: sky2.h:8
static __always_inline void trivial_memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.
Definition: uaccess.h:107
userptr_t virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
void * user_to_virt(userptr_t userptr, off_t offset)
Convert user pointer to virtual address.
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
void memmove_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers, allowing for overlap.
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
static __always_inline off_t userptr_t subtrahend
Definition: librm.h:147
static __always_inline userptr_t trivial_virt_to_user(volatile const void *addr)
Convert virtual address to user pointer.
Definition: uaccess.h:55
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
uint32_t len
Length.
Definition: ena.h:14
static __always_inline int off_t userptr_t second
Definition: librm.h:166
void memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.
String functions.
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
static __always_inline void trivial_memset_user(userptr_t buffer, off_t offset, int c, size_t len)
Fill user buffer with a constant byte.
Definition: uaccess.h:155
void * memset(void *dest, int character, size_t len) __nonnull