您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

librm.h 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #ifndef LIBRM_H
  2. #define LIBRM_H
  3. /* Drag in protected-mode segment selector values */
  4. #include "virtaddr.h"
  5. #include "realmode.h"
  6. #ifndef ASSEMBLY
  7. #include "stddef.h"
  8. #include "string.h"
  9. /*
  10. * Data structures and type definitions
  11. *
  12. */
  13. /* Access to variables in .data16 and .text16 */
  14. extern char *data16;
  15. extern char *text16;
  16. #define __data16( variable ) \
  17. __attribute__ (( section ( ".data16" ) )) \
  18. _data16_ ## variable __asm__ ( #variable )
  19. #define __data16_array( variable, array ) \
  20. __attribute__ (( section ( ".data16" ) )) \
  21. _data16_ ## variable array __asm__ ( #variable )
  22. #define __text16( variable ) \
  23. __attribute__ (( section ( ".text16.data" ) )) \
  24. _text16_ ## variable __asm__ ( #variable )
  25. #define __text16_array( variable, array ) \
  26. __attribute__ (( section ( ".text16.data" ) )) \
  27. _text16_ ## variable array __asm__ ( #variable )
  28. #define __use_data16( variable ) \
  29. ( * ( ( typeof ( _data16_ ## variable ) * ) \
  30. & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
  31. #define __use_text16( variable ) \
  32. ( * ( ( typeof ( _text16_ ## variable ) * ) \
  33. & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
  34. #define __from_data16( variable ) \
  35. ( * ( ( typeof ( variable ) * ) \
  36. ( ( ( void * ) &(variable) ) - ( ( void * ) data16 ) ) ) )
  37. #define __from_text16( variable ) \
  38. ( * ( ( typeof ( variable ) * ) \
  39. ( ( ( void * ) &(variable) ) - ( ( void * ) text16 ) ) ) )
  40. /* Variables in librm.S, present in the normal data segment */
  41. extern uint16_t rm_sp;
  42. extern uint16_t rm_ss;
  43. extern uint32_t pm_esp;
  44. extern uint16_t __data16 ( rm_cs );
  45. #define rm_cs __use_data16 ( rm_cs )
  46. extern uint16_t __text16 ( rm_ds );
  47. #define rm_ds __use_text16 ( rm_ds )
  48. /* Functions that librm expects to be able to link to. Included here
  49. * so that the compiler will catch prototype mismatches.
  50. */
  51. extern void gateA20_set ( void );
  52. /*
  53. * librm_mgmt: functions for manipulating base memory and executing
  54. * real-mode code.
  55. *
  56. * Full API documentation for these functions is in realmode.h.
  57. *
  58. */
  59. /* Macro for obtaining a physical address from a segment:offset pair. */
  60. #define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
  61. /* Copy to/from base memory */
  62. static inline __attribute__ (( always_inline )) void
  63. copy_to_real_librm ( unsigned int dest_seg, unsigned int dest_off,
  64. void *src, size_t n ) {
  65. memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
  66. }
  67. static inline __attribute__ (( always_inline )) void
  68. copy_from_real_librm ( void *dest, unsigned int src_seg,
  69. unsigned int src_off, size_t n ) {
  70. memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
  71. }
  72. #define put_real_librm( var, dest_seg, dest_off ) \
  73. do { \
  74. * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
  75. } while ( 0 )
  76. #define get_real_librm( var, src_seg, src_off ) \
  77. do { \
  78. var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
  79. } while ( 0 )
  80. #define copy_to_real copy_to_real_librm
  81. #define copy_from_real copy_from_real_librm
  82. #define put_real put_real_librm
  83. #define get_real get_real_librm
  84. /**
  85. * A pointer to a user buffer
  86. *
  87. * Even though we could just use a void *, we use an intptr_t so that
  88. * attempts to use normal pointers show up as compiler warnings. Such
  89. * code is actually valid for librm, but not for libkir (i.e. under
  90. * KEEP_IT_REAL), so it's good to have the warnings even under librm.
  91. */
  92. typedef intptr_t userptr_t;
  93. /**
  94. * Add offset to user pointer
  95. *
  96. * @v ptr User pointer
  97. * @v offset Offset
  98. * @ret new_ptr New pointer value
  99. */
  100. static inline __attribute__ (( always_inline )) userptr_t
  101. userptr_add ( userptr_t ptr, off_t offset ) {
  102. return ( ptr + offset );
  103. }
  104. /**
  105. * Copy data to user buffer
  106. *
  107. * @v buffer User buffer
  108. * @v offset Offset within user buffer
  109. * @v src Source
  110. * @v len Length
  111. */
  112. static inline __attribute__ (( always_inline )) void
  113. copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) {
  114. memcpy ( ( ( void * ) buffer + offset ), src, len );
  115. }
  116. /**
  117. * Copy data from user buffer
  118. *
  119. * @v dest Destination
  120. * @v buffer User buffer
  121. * @v offset Offset within user buffer
  122. * @v len Length
  123. */
  124. static inline __attribute__ (( always_inline )) void
  125. copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
  126. memcpy ( dest, ( ( void * ) buffer + offset ), len );
  127. }
  128. /**
  129. * Copy data between user buffers
  130. *
  131. * @v dest Destination user buffer
  132. * @v dest_off Offset within destination buffer
  133. * @v src Source user buffer
  134. * @v src_off Offset within source buffer
  135. * @v len Length
  136. */
  137. static inline __attribute__ (( always_inline )) void
  138. memcpy_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
  139. size_t len ) {
  140. memcpy ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
  141. len );
  142. }
  143. /**
  144. * Copy data between user buffers, allowing for overlap
  145. *
  146. * @v dest Destination user buffer
  147. * @v dest_off Offset within destination buffer
  148. * @v src Source user buffer
  149. * @v src_off Offset within source buffer
  150. * @v len Length
  151. */
  152. static inline __attribute__ (( always_inline )) void
  153. memmove_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
  154. size_t len ) {
  155. memmove ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
  156. len );
  157. }
  158. /**
  159. * Fill user buffer with a constant byte
  160. *
  161. * @v buffer User buffer
  162. * @v offset Offset within buffer
  163. * @v c Constant byte with which to fill
  164. * @v len Length
  165. */
  166. static inline __attribute__ (( always_inline )) void
  167. memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
  168. memset ( ( ( void * ) buffer + offset ), c, len );
  169. }
  170. /**
  171. * Convert virtual address to user buffer
  172. *
  173. * @v virtual Virtual address
  174. * @ret buffer User buffer
  175. *
  176. * This constructs a user buffer from an ordinary pointer. Use it
  177. * when you need to pass a pointer to an internal buffer to a function
  178. * that expects a @c userptr_t.
  179. */
  180. static inline __attribute__ (( always_inline )) userptr_t
  181. virt_to_user ( void * virtual ) {
  182. return ( ( intptr_t ) virtual );
  183. }
  184. /**
  185. * Convert segment:offset address to user buffer
  186. *
  187. * @v segment Real-mode segment
  188. * @v offset Real-mode offset
  189. * @ret buffer User buffer
  190. */
  191. static inline __attribute__ (( always_inline )) userptr_t
  192. real_to_user ( unsigned int segment, unsigned int offset ) {
  193. return virt_to_user ( VIRTUAL ( segment, offset ) );
  194. }
  195. /**
  196. * Convert physical address to user buffer
  197. *
  198. * @v physical Physical address
  199. * @ret buffer User buffer
  200. */
  201. static inline __attribute__ (( always_inline )) userptr_t
  202. phys_to_user ( physaddr_t physical ) {
  203. return virt_to_user ( phys_to_virt ( physical ) );
  204. }
  205. /**
  206. * Convert user buffer to physical address
  207. *
  208. * @v buffer User buffer
  209. * @v offset Offset within user buffer
  210. * @ret physical Physical address
  211. */
  212. static inline __attribute__ (( always_inline )) physaddr_t
  213. user_to_phys ( userptr_t buffer, off_t offset ) {
  214. return virt_to_phys ( ( void * ) buffer + offset );
  215. }
  216. /* Copy to/from real-mode stack */
  217. extern uint16_t copy_to_rm_stack ( void *data, size_t size );
  218. extern void remove_from_rm_stack ( void *data, size_t size );
  219. /* Place/remove parameter on real-mode stack in a way that's
  220. * compatible with libkir
  221. */
  222. #define BASEMEM_PARAMETER_INIT_LIBRM( param ) \
  223. copy_to_rm_stack ( & ( param ), sizeof ( param ) )
  224. #define BASEMEM_PARAMETER_DONE_LIBRM( param ) \
  225. remove_from_rm_stack ( & ( param ), sizeof ( param ) )
  226. #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
  227. #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
  228. /* TEXT16_CODE: declare a fragment of code that resides in .text16 */
  229. #define TEXT16_CODE( asm_code_str ) \
  230. ".section \".text16\", \"ax\", @progbits\n\t" \
  231. ".code16\n\t" \
  232. asm_code_str "\n\t" \
  233. ".code32\n\t" \
  234. ".previous\n\t"
  235. /* REAL_CODE: declare a fragment of code that executes in real mode */
  236. #define REAL_CODE( asm_code_str ) \
  237. "pushl $1f\n\t" \
  238. "call real_call\n\t" \
  239. "addl $4, %%esp\n\t" \
  240. TEXT16_CODE ( "\n1:\n\t" \
  241. asm_code_str \
  242. "\n\t" \
  243. "ret\n\t" )
  244. /* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
  245. #define PHYS_CODE( asm_code_str ) \
  246. "call _virt_to_phys\n\t" \
  247. asm_code_str \
  248. "call _phys_to_virt\n\t"
  249. #endif /* ASSEMBLY */
  250. #endif /* LIBRM_H */