uaccess.h

Go to the documentation of this file.
00001 #ifndef _GPXE_UACCESS_H
00002 #define _GPXE_UACCESS_H
00003 
00004 /**
00005  * @file
00006  *
00007  * Access to external ("user") memory
00008  *
00009  * gPXE often needs to transfer data between internal and external
00010  * buffers.  On i386, the external buffers may require access via a
00011  * different segment, and the buffer address cannot be encoded into a
00012  * simple void * pointer.  The @c userptr_t type encapsulates the
00013  * information needed to identify an external buffer, and the
00014  * copy_to_user() and copy_from_user() functions provide methods for
00015  * transferring data between internal and external buffers.
00016  *
00017  * Note that userptr_t is an opaque type; in particular, performing
00018  * arithmetic upon a userptr_t is not allowed.
00019  *
00020  */
00021 
00022 FILE_LICENCE ( GPL2_OR_LATER );
00023 
00024 #include <stdint.h>
00025 #include <string.h>
00026 #include <gpxe/api.h>
00027 #include <config/ioapi.h>
00028 
00029 /**
00030  * A pointer to a user buffer
00031  *
00032  */
00033 typedef unsigned long userptr_t;
00034 
00035 /** Equivalent of NULL for user pointers */
00036 #define UNULL ( ( userptr_t ) 0 )
00037 
00038 /**
00039  * @defgroup uaccess_trivial Trivial user access API implementations
00040  *
00041  * User access API implementations that can be used by environments in
00042  * which virtual addresses allow access to all of memory.
00043  *
00044  * @{
00045  *
00046  */
00047 
00048 /**
00049  * Convert virtual address to user pointer
00050  *
00051  * @v addr              Virtual address
00052  * @ret userptr         User pointer
00053  */
00054 static inline __always_inline userptr_t
00055 trivial_virt_to_user ( volatile const void *addr ) {
00056         return ( ( userptr_t ) addr );
00057 }
00058 
00059 /**
00060  * Convert user pointer to virtual address
00061  *
00062  * @v userptr           User pointer
00063  * @v offset            Offset from user pointer
00064  * @ret addr            Virtual address
00065  *
00066  * This operation is not available under all memory models.
00067  */
00068 static inline __always_inline void *
00069 trivial_user_to_virt ( userptr_t userptr, off_t offset ) {
00070         return ( ( void * ) userptr + offset );
00071 }
00072 
00073 /**
00074  * Add offset to user pointer
00075  *
00076  * @v userptr           User pointer
00077  * @v offset            Offset
00078  * @ret userptr         New pointer value
00079  */
00080 static inline __always_inline userptr_t
00081 trivial_userptr_add ( userptr_t userptr, off_t offset ) {
00082         return ( userptr + offset );
00083 }
00084 
00085 /**
00086  * Copy data between user buffers
00087  *
00088  * @v dest              Destination
00089  * @v dest_off          Destination offset
00090  * @v src               Source
00091  * @v src_off           Source offset
00092  * @v len               Length
00093  */
00094 static inline __always_inline void
00095 trivial_memcpy_user ( userptr_t dest, off_t dest_off,
00096                       userptr_t src, off_t src_off, size_t len ) {
00097         memcpy ( ( ( void * ) dest + dest_off ),
00098                  ( ( void * ) src + src_off ), len );
00099 }
00100 
00101 /**
00102  * Copy data between user buffers, allowing for overlap
00103  *
00104  * @v dest              Destination
00105  * @v dest_off          Destination offset
00106  * @v src               Source
00107  * @v src_off           Source offset
00108  * @v len               Length
00109  */
00110 static inline __always_inline void
00111 trivial_memmove_user ( userptr_t dest, off_t dest_off,
00112                        userptr_t src, off_t src_off, size_t len ) {
00113         memmove ( ( ( void * ) dest + dest_off ),
00114                   ( ( void * ) src + src_off ), len );
00115 }
00116 
00117 /**
00118  * Fill user buffer with a constant byte
00119  *
00120  * @v buffer            User buffer
00121  * @v offset            Offset within buffer
00122  * @v c                 Constant byte with which to fill
00123  * @v len               Length
00124  */
00125 static inline __always_inline void
00126 trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
00127         memset ( ( ( void * ) buffer + offset ), c, len );
00128 }
00129 
00130 /**
00131  * Find length of NUL-terminated string in user buffer
00132  *
00133  * @v buffer            User buffer
00134  * @v offset            Offset within buffer
00135  * @ret len             Length of string (excluding NUL)
00136  */
00137 static inline __always_inline size_t
00138 trivial_strlen_user ( userptr_t buffer, off_t offset ) {
00139         return strlen ( ( void * ) buffer + offset );
00140 }
00141 
00142 /**
00143  * Find character in user buffer
00144  *
00145  * @v buffer            User buffer
00146  * @v offset            Starting offset within buffer
00147  * @v c                 Character to search for
00148  * @v len               Length of user buffer
00149  * @ret offset          Offset of character, or <0 if not found
00150  */
00151 static inline __always_inline off_t
00152 trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
00153         void *found;
00154 
00155         found = memchr ( ( ( void * ) buffer + offset ), c, len );
00156         return ( found ? ( found - ( void * ) buffer ) : -1 );
00157 }
00158 
00159 /** @} */
00160 
00161 /**
00162  * Calculate static inline user access API function name
00163  *
00164  * @v _prefix           Subsystem prefix
00165  * @v _api_func         API function
00166  * @ret _subsys_func    Subsystem API function
00167  */
00168 #define UACCESS_INLINE( _subsys, _api_func ) \
00169         SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
00170 
00171 /**
00172  * Provide an user access API implementation
00173  *
00174  * @v _prefix           Subsystem prefix
00175  * @v _api_func         API function
00176  * @v _func             Implementing function
00177  */
00178 #define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
00179         PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
00180 
00181 /**
00182  * Provide a static inline user access API implementation
00183  *
00184  * @v _prefix           Subsystem prefix
00185  * @v _api_func         API function
00186  */
00187 #define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
00188         PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
00189 
00190 /* Include all architecture-independent user access API headers */
00191 #include <gpxe/efi/efi_uaccess.h>
00192 
00193 /* Include all architecture-dependent user access API headers */
00194 #include <bits/uaccess.h>
00195 
00196 /**
00197  * Convert physical address to user pointer
00198  *
00199  * @v phys_addr         Physical address
00200  * @ret userptr         User pointer
00201  */
00202 userptr_t phys_to_user ( unsigned long phys_addr );
00203 
00204 /**
00205  * Convert user pointer to physical address
00206  *
00207  * @v userptr           User pointer
00208  * @v offset            Offset from user pointer
00209  * @ret phys_addr       Physical address
00210  */
00211 unsigned long user_to_phys ( userptr_t userptr, off_t offset );
00212 
00213 /**
00214  * Convert virtual address to user pointer
00215  *
00216  * @v addr              Virtual address
00217  * @ret userptr         User pointer
00218  */
00219 userptr_t virt_to_user ( volatile const void *addr );
00220 
00221 /**
00222  * Convert user pointer to virtual address
00223  *
00224  * @v userptr           User pointer
00225  * @v offset            Offset from user pointer
00226  * @ret addr            Virtual address
00227  *
00228  * This operation is not available under all memory models.
00229  */
00230 void * user_to_virt ( userptr_t userptr, off_t offset );
00231 
00232 /**
00233  * Add offset to user pointer
00234  *
00235  * @v userptr           User pointer
00236  * @v offset            Offset
00237  * @ret userptr         New pointer value
00238  */
00239 userptr_t userptr_add ( userptr_t userptr, off_t offset );
00240 
00241 /**
00242  * Convert virtual address to a physical address
00243  *
00244  * @v addr              Virtual address
00245  * @ret phys_addr       Physical address
00246  */
00247 static inline __always_inline unsigned long
00248 virt_to_phys ( volatile const void *addr ) {
00249         return user_to_phys ( virt_to_user ( addr ), 0 );
00250 }
00251 
00252 /**
00253  * Convert physical address to a virtual address
00254  *
00255  * @v addr              Virtual address
00256  * @ret phys_addr       Physical address
00257  *
00258  * This operation is not available under all memory models.
00259  */
00260 static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
00261         return user_to_virt ( phys_to_user ( phys_addr ), 0 );
00262 }
00263 
00264 /**
00265  * Copy data between user buffers
00266  *
00267  * @v dest              Destination
00268  * @v dest_off          Destination offset
00269  * @v src               Source
00270  * @v src_off           Source offset
00271  * @v len               Length
00272  */
00273 void memcpy_user ( userptr_t dest, off_t dest_off,
00274                    userptr_t src, off_t src_off, size_t len );
00275 
00276 /**
00277  * Copy data to user buffer
00278  *
00279  * @v dest              Destination
00280  * @v dest_off          Destination offset
00281  * @v src               Source
00282  * @v len               Length
00283  */
00284 static inline __always_inline void
00285 copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
00286         memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
00287 }
00288 
00289 /**
00290  * Copy data from user buffer
00291  *
00292  * @v dest              Destination
00293  * @v src               Source
00294  * @v src_off           Source offset
00295  * @v len               Length
00296  */
00297 static inline __always_inline void
00298 copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
00299         memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
00300 }
00301 
00302 /**
00303  * Copy data between user buffers, allowing for overlap
00304  *
00305  * @v dest              Destination
00306  * @v dest_off          Destination offset
00307  * @v src               Source
00308  * @v src_off           Source offset
00309  * @v len               Length
00310  */
00311 void memmove_user ( userptr_t dest, off_t dest_off,
00312                     userptr_t src, off_t src_off, size_t len );
00313 
00314 /**
00315  * Fill user buffer with a constant byte
00316  *
00317  * @v userptr           User buffer
00318  * @v offset            Offset within buffer
00319  * @v c                 Constant byte with which to fill
00320  * @v len               Length
00321  */
00322 void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
00323 
00324 /**
00325  * Find length of NUL-terminated string in user buffer
00326  *
00327  * @v userptr           User buffer
00328  * @v offset            Offset within buffer
00329  * @ret len             Length of string (excluding NUL)
00330  */
00331 size_t strlen_user ( userptr_t userptr, off_t offset );
00332 
00333 /**
00334  * Find character in user buffer
00335  *
00336  * @v userptr           User buffer
00337  * @v offset            Starting offset within buffer
00338  * @v c                 Character to search for
00339  * @v len               Length of user buffer
00340  * @ret offset          Offset of character, or <0 if not found
00341  */
00342 off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
00343 
00344 #endif /* _GPXE_UACCESS_H */

Generated on Tue Apr 6 20:01:09 2010 for gPXE by  doxygen 1.5.7.1