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

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