You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

uaccess.h 8.4KB

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