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.

librm.h 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. /* Real-mode call parameter block, as passed to real_call */
  14. struct real_call_params {
  15. struct i386_seg_regs;
  16. struct i386_regs;
  17. segoff_t rm_code;
  18. segoff_t reserved;
  19. } PACKED;
  20. /* Current location of librm in base memory */
  21. extern char *installed_librm;
  22. /* Start and size of our source copy of librm (i.e. the one that we
  23. * can install by copying it to base memory and setting
  24. * installed_librm)
  25. */
  26. extern char librm[];
  27. extern size_t _librm_size[];
  28. /* Linker symbols for offsets within librm. Other symbols should
  29. * almost certainly not be referred to from C code.
  30. */
  31. extern void (*_real_to_prot[]) ( void );
  32. extern void (*_prot_to_real[]) ( void );
  33. extern void (*_prot_call[]) ( void );
  34. extern void (*_real_call[]) ( void );
  35. extern segoff_t _rm_stack[];
  36. extern uint32_t _pm_stack[];
  37. extern char _librm_ref_count[];
  38. /* Symbols within current installation of librm */
  39. #define LIBRM_VAR( sym ) \
  40. ( * ( ( typeof ( * _ ## sym ) * ) \
  41. & ( installed_librm [ (int) _ ## sym ] ) ) )
  42. #define LIBRM_FN( sym ) \
  43. ( ( typeof ( * _ ## sym ) ) \
  44. & ( installed_librm [ (int) _ ## sym ] ) )
  45. #define LIBRM_CONSTANT( sym ) \
  46. ( ( typeof ( * _ ## sym ) ) ( _ ## sym ) )
  47. #define inst_real_to_prot LIBRM_FN ( real_to_prot )
  48. #define inst_prot_to_real LIBRM_FN ( prot_to_real )
  49. #define inst_prot_call LIBRM_FN ( prot_call )
  50. #define inst_real_call LIBRM_FN ( real_call )
  51. #define inst_rm_stack LIBRM_VAR ( rm_stack )
  52. #define inst_pm_stack LIBRM_VAR ( pm_stack )
  53. #define inst_librm_ref_count LIBRM_VAR ( librm_ref_count )
  54. #define librm_size LIBRM_CONSTANT ( librm_size )
  55. /* Functions that librm expects to be able to link to. Included here
  56. * so that the compiler will catch prototype mismatches.
  57. */
  58. extern void _phys_to_virt ( void );
  59. extern void _virt_to_phys ( void );
  60. extern void gateA20_set ( void );
  61. /*
  62. * librm_mgmt: functions for manipulating base memory and executing
  63. * real-mode code.
  64. *
  65. * Full API documentation for these functions is in realmode.h.
  66. *
  67. */
  68. /* Macro for obtaining a physical address from a segment:offset pair. */
  69. #define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
  70. /* Copy to/from base memory */
  71. static inline void copy_to_real_librm ( uint16_t dest_seg, uint16_t dest_off,
  72. void *src, size_t n ) {
  73. memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
  74. }
  75. static inline void copy_from_real_librm ( void *dest,
  76. uint16_t src_seg, uint16_t src_off,
  77. size_t n ) {
  78. memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
  79. }
  80. #define put_real_librm( var, dest_seg, dest_off ) \
  81. do { \
  82. * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
  83. } while ( 0 )
  84. #define get_real_librm( var, src_seg, src_off ) \
  85. do { \
  86. var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
  87. } while ( 0 )
  88. #define copy_to_real copy_to_real_librm
  89. #define copy_from_real copy_from_real_librm
  90. #define put_real put_real_librm
  91. #define get_real get_real_librm
  92. /* Copy to/from real-mode stack */
  93. extern uint16_t copy_to_rm_stack ( void *data, size_t size );
  94. extern void remove_from_rm_stack ( void *data, size_t size );
  95. /* Place/remove parameter on real-mode stack in a way that's
  96. * compatible with libkir
  97. */
  98. #define BASEMEM_PARAMETER_INIT_LIBRM( param ) \
  99. copy_to_rm_stack ( & ( param ), sizeof ( param ) )
  100. #define BASEMEM_PARAMETER_DONE_LIBRM( param ) \
  101. remove_from_rm_stack ( & ( param ), sizeof ( param ) )
  102. #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
  103. #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
  104. /* REAL_FRAGMENT: Declare and define a real-mode code fragment in .text16 */
  105. #define REAL_FRAGMENT( name, asm_code_str ) \
  106. extern void name ( void ); \
  107. extern char name ## _size[]; \
  108. __asm__ __volatile__ ( \
  109. ".section \".text16\"\n\t" \
  110. ".code16\n\t" \
  111. ".arch i386\n\t" \
  112. #name ":\n\t" \
  113. asm_code_str "\n\t" \
  114. "lret\n\t" \
  115. #name "_end:\n\t" \
  116. ".equ " #name "_size, " #name "_end - " #name "\n\t" \
  117. ".code32\n\t" \
  118. ".previous\n\t" \
  119. : : \
  120. )
  121. #define FRAGMENT_SIZE( fragment ) ( (size_t) fragment ## _size )
  122. /* REAL_CALL: call a real-mode routine via librm */
  123. #define OUT_CONSTRAINTS(...) __VA_ARGS__
  124. #define IN_CONSTRAINTS(...) "m" ( __routine ), ## __VA_ARGS__
  125. #define CLOBBER(...) __VA_ARGS__
  126. #define REAL_CALL( routine, num_out_constraints, out_constraints, \
  127. in_constraints, clobber ) \
  128. do { \
  129. segoff_t __routine = routine; \
  130. __asm__ __volatile__ ( \
  131. "pushl %" #num_out_constraints "\n\t" \
  132. "call 1f\n\t" \
  133. "jmp 2f\n\t" \
  134. "\n1:\n\t" \
  135. "pushl installed_librm\n\t" \
  136. "addl $_real_call, 0(%%esp)\n\t" \
  137. "ret\n\t" \
  138. "\n2:\n\t" \
  139. "addl $4, %%esp\n\t" \
  140. : out_constraints \
  141. : in_constraints \
  142. : clobber \
  143. ); \
  144. } while ( 0 )
  145. /* REAL_EXEC: combine RM_FRAGMENT and REAL_CALL into one handy unit */
  146. #define PASSTHRU(...) __VA_ARGS__
  147. #define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
  148. in_constraints, clobber ) \
  149. do { \
  150. segoff_t fragment; \
  151. \
  152. REAL_FRAGMENT ( name, asm_code_str ); \
  153. \
  154. fragment.segment = inst_rm_stack.segment; \
  155. fragment.offset = \
  156. copy_to_rm_stack ( name, FRAGMENT_SIZE ( name ) ); \
  157. \
  158. REAL_CALL ( fragment, num_out_constraints, \
  159. PASSTHRU ( out_constraints ), \
  160. PASSTHRU ( in_constraints ), \
  161. PASSTHRU ( clobber ) ); \
  162. \
  163. remove_from_rm_stack ( NULL, FRAGMENT_SIZE ( name ) ); \
  164. } while ( 0 )
  165. #endif /* ASSEMBLY */
  166. #endif /* LIBRM_H */