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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #ifndef _IPXE_UACCESS_H
  2. #define _IPXE_UACCESS_H
  3. /**
  4. * @file
  5. *
  6. * Access to external ("user") memory
  7. *
  8. * iPXE 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_OR_UBDL );
  21. #include <stdint.h>
  22. #include <string.h>
  23. #include <ipxe/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. * Subtract user pointers
  77. *
  78. * @v userptr User pointer
  79. * @v subtrahend User pointer to be subtracted
  80. * @ret offset Offset
  81. */
  82. static inline __always_inline off_t
  83. trivial_userptr_sub ( userptr_t userptr, userptr_t subtrahend ) {
  84. return ( userptr - subtrahend );
  85. }
  86. /**
  87. * Copy data between user buffers
  88. *
  89. * @v dest Destination
  90. * @v dest_off Destination offset
  91. * @v src Source
  92. * @v src_off Source offset
  93. * @v len Length
  94. */
  95. static inline __always_inline void
  96. trivial_memcpy_user ( userptr_t dest, off_t dest_off,
  97. userptr_t src, off_t src_off, size_t len ) {
  98. memcpy ( ( ( void * ) dest + dest_off ),
  99. ( ( void * ) src + src_off ), len );
  100. }
  101. /**
  102. * Copy data between user buffers, allowing for overlap
  103. *
  104. * @v dest Destination
  105. * @v dest_off Destination offset
  106. * @v src Source
  107. * @v src_off Source offset
  108. * @v len Length
  109. */
  110. static inline __always_inline void
  111. trivial_memmove_user ( userptr_t dest, off_t dest_off,
  112. userptr_t src, off_t src_off, size_t len ) {
  113. memmove ( ( ( void * ) dest + dest_off ),
  114. ( ( void * ) src + src_off ), len );
  115. }
  116. /**
  117. * Compare data between user buffers
  118. *
  119. * @v first First buffer
  120. * @v first_off First buffer offset
  121. * @v second Second buffer
  122. * @v second_off Second buffer offset
  123. * @v len Length
  124. * @ret diff Difference
  125. */
  126. static inline __always_inline int
  127. trivial_memcmp_user ( userptr_t first, off_t first_off,
  128. userptr_t second, off_t second_off, size_t len ) {
  129. return memcmp ( ( ( void * ) first + first_off ),
  130. ( ( void * ) second + second_off ), len );
  131. }
  132. /**
  133. * Fill user buffer with a constant byte
  134. *
  135. * @v buffer User buffer
  136. * @v offset Offset within buffer
  137. * @v c Constant byte with which to fill
  138. * @v len Length
  139. */
  140. static inline __always_inline void
  141. trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
  142. memset ( ( ( void * ) buffer + offset ), c, len );
  143. }
  144. /**
  145. * Find length of NUL-terminated string in user buffer
  146. *
  147. * @v buffer User buffer
  148. * @v offset Offset within buffer
  149. * @ret len Length of string (excluding NUL)
  150. */
  151. static inline __always_inline size_t
  152. trivial_strlen_user ( userptr_t buffer, off_t offset ) {
  153. return strlen ( ( void * ) buffer + offset );
  154. }
  155. /**
  156. * Find character in user buffer
  157. *
  158. * @v buffer User buffer
  159. * @v offset Starting offset within buffer
  160. * @v c Character to search for
  161. * @v len Length of user buffer
  162. * @ret offset Offset of character, or <0 if not found
  163. */
  164. static inline __always_inline off_t
  165. trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
  166. void *found;
  167. found = memchr ( ( ( void * ) buffer + offset ), c, len );
  168. return ( found ? ( found - ( void * ) buffer ) : -1 );
  169. }
  170. /** @} */
  171. /**
  172. * Calculate static inline user access API function name
  173. *
  174. * @v _prefix Subsystem prefix
  175. * @v _api_func API function
  176. * @ret _subsys_func Subsystem API function
  177. */
  178. #define UACCESS_INLINE( _subsys, _api_func ) \
  179. SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
  180. /**
  181. * Provide an user access API implementation
  182. *
  183. * @v _prefix Subsystem prefix
  184. * @v _api_func API function
  185. * @v _func Implementing function
  186. */
  187. #define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
  188. PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
  189. /**
  190. * Provide a static inline user access API implementation
  191. *
  192. * @v _prefix Subsystem prefix
  193. * @v _api_func API function
  194. */
  195. #define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
  196. PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
  197. /* Include all architecture-independent user access API headers */
  198. #include <ipxe/efi/efi_uaccess.h>
  199. #include <ipxe/linux/linux_uaccess.h>
  200. /* Include all architecture-dependent user access API headers */
  201. #include <bits/uaccess.h>
  202. /**
  203. * Convert physical address to user pointer
  204. *
  205. * @v phys_addr Physical address
  206. * @ret userptr User pointer
  207. */
  208. userptr_t phys_to_user ( unsigned long phys_addr );
  209. /**
  210. * Convert user pointer to physical address
  211. *
  212. * @v userptr User pointer
  213. * @v offset Offset from user pointer
  214. * @ret phys_addr Physical address
  215. */
  216. unsigned long user_to_phys ( userptr_t userptr, off_t offset );
  217. /**
  218. * Convert virtual address to user pointer
  219. *
  220. * @v addr Virtual address
  221. * @ret userptr User pointer
  222. */
  223. userptr_t virt_to_user ( volatile const void *addr );
  224. /**
  225. * Convert user pointer to virtual address
  226. *
  227. * @v userptr User pointer
  228. * @v offset Offset from user pointer
  229. * @ret addr Virtual address
  230. *
  231. * This operation is not available under all memory models.
  232. */
  233. void * user_to_virt ( userptr_t userptr, off_t offset );
  234. /**
  235. * Add offset to user pointer
  236. *
  237. * @v userptr User pointer
  238. * @v offset Offset
  239. * @ret userptr New pointer value
  240. */
  241. userptr_t userptr_add ( userptr_t userptr, off_t offset );
  242. /**
  243. * Subtract user pointers
  244. *
  245. * @v userptr User pointer
  246. * @v subtrahend User pointer to be subtracted
  247. * @ret offset Offset
  248. */
  249. off_t userptr_sub ( userptr_t userptr, userptr_t subtrahend );
  250. /**
  251. * Convert virtual address to a physical address
  252. *
  253. * @v addr Virtual address
  254. * @ret phys_addr Physical address
  255. */
  256. static inline __always_inline unsigned long
  257. virt_to_phys ( volatile const void *addr ) {
  258. return user_to_phys ( virt_to_user ( addr ), 0 );
  259. }
  260. /**
  261. * Convert physical address to a virtual address
  262. *
  263. * @v addr Virtual address
  264. * @ret phys_addr Physical address
  265. *
  266. * This operation is not available under all memory models.
  267. */
  268. static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
  269. return user_to_virt ( phys_to_user ( phys_addr ), 0 );
  270. }
  271. /**
  272. * Copy data between user buffers
  273. *
  274. * @v dest Destination
  275. * @v dest_off Destination offset
  276. * @v src Source
  277. * @v src_off Source offset
  278. * @v len Length
  279. */
  280. void memcpy_user ( userptr_t dest, off_t dest_off,
  281. userptr_t src, off_t src_off, size_t len );
  282. /**
  283. * Copy data to user buffer
  284. *
  285. * @v dest Destination
  286. * @v dest_off Destination offset
  287. * @v src Source
  288. * @v len Length
  289. */
  290. static inline __always_inline void
  291. copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
  292. memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
  293. }
  294. /**
  295. * Copy data from user buffer
  296. *
  297. * @v dest Destination
  298. * @v src Source
  299. * @v src_off Source offset
  300. * @v len Length
  301. */
  302. static inline __always_inline void
  303. copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
  304. memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
  305. }
  306. /**
  307. * Copy data between user buffers, allowing for overlap
  308. *
  309. * @v dest Destination
  310. * @v dest_off Destination offset
  311. * @v src Source
  312. * @v src_off Source offset
  313. * @v len Length
  314. */
  315. void memmove_user ( userptr_t dest, off_t dest_off,
  316. userptr_t src, off_t src_off, size_t len );
  317. /**
  318. * Compare data between user buffers
  319. *
  320. * @v first First buffer
  321. * @v first_off First buffer offset
  322. * @v second Second buffer
  323. * @v second_off Second buffer offset
  324. * @v len Length
  325. * @ret diff Difference
  326. */
  327. int memcmp_user ( userptr_t first, off_t first_off,
  328. userptr_t second, off_t second_off, size_t len );
  329. /**
  330. * Fill user buffer with a constant byte
  331. *
  332. * @v userptr User buffer
  333. * @v offset Offset within buffer
  334. * @v c Constant byte with which to fill
  335. * @v len Length
  336. */
  337. void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
  338. /**
  339. * Find length of NUL-terminated string in user buffer
  340. *
  341. * @v userptr User buffer
  342. * @v offset Offset within buffer
  343. * @ret len Length of string (excluding NUL)
  344. */
  345. size_t strlen_user ( userptr_t userptr, off_t offset );
  346. /**
  347. * Find character in user buffer
  348. *
  349. * @v userptr User buffer
  350. * @v offset Starting offset within buffer
  351. * @v c Character to search for
  352. * @v len Length of user buffer
  353. * @ret offset Offset of character, or <0 if not found
  354. */
  355. off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
  356. #endif /* _IPXE_UACCESS_H */