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.

callbacks_arch.h 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* Callout/callback interface for Etherboot
  2. *
  3. * This file provides the mechanisms for making calls from Etherboot
  4. * to external programs and vice-versa.
  5. *
  6. * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
  7. *
  8. * $Id$
  9. */
  10. #ifndef CALLBACKS_ARCH_H
  11. #define CALLBACKS_ARCH_H
  12. /* Skip the definitions that won't make sense to the assembler */
  13. #ifndef ASSEMBLY
  14. /* Struct to hold general-purpose register values. PUSHAL and POPAL
  15. * can work directly with this structure; do not change the order of
  16. * registers.
  17. */
  18. typedef struct {
  19. union {
  20. uint16_t di;
  21. uint32_t edi;
  22. };
  23. union {
  24. uint16_t si;
  25. uint32_t esi;
  26. };
  27. union {
  28. uint16_t bp;
  29. uint32_t ebp;
  30. };
  31. union {
  32. uint16_t sp;
  33. uint32_t esp;
  34. };
  35. union {
  36. struct {
  37. uint8_t bl;
  38. uint8_t bh;
  39. } PACKED;
  40. uint16_t bx;
  41. uint32_t ebx;
  42. };
  43. union {
  44. struct {
  45. uint8_t dl;
  46. uint8_t dh;
  47. } PACKED;
  48. uint16_t dx;
  49. uint32_t edx;
  50. };
  51. union {
  52. struct {
  53. uint8_t cl;
  54. uint8_t ch;
  55. } PACKED;
  56. uint16_t cx;
  57. uint32_t ecx;
  58. };
  59. union {
  60. struct {
  61. uint8_t al;
  62. uint8_t ah;
  63. } PACKED;
  64. uint16_t ax;
  65. uint32_t eax;
  66. };
  67. } regs_t;
  68. /* Struct to hold segment register values. Don't change the order;
  69. * many bits of assembly code rely on it.
  70. */
  71. typedef struct {
  72. uint16_t cs;
  73. uint16_t ss;
  74. uint16_t ds;
  75. uint16_t es;
  76. uint16_t fs;
  77. uint16_t gs;
  78. } PACKED seg_regs_t;
  79. /* Struct for a GDT descriptor */
  80. typedef struct {
  81. uint16_t limit;
  82. uint32_t address;
  83. uint16_t padding;
  84. } PACKED gdt_descriptor_t;
  85. /* Struct for a GDT entry. Use GDT_SEGMENT() to fill it in.
  86. */
  87. typedef struct {
  88. uint16_t limit_0_15;
  89. uint16_t base_0_15;
  90. uint8_t base_16_23;
  91. uint8_t accessed__type__sflag__dpl__present;
  92. uint8_t limit_16_19__avl__size__granularity;
  93. uint8_t base_24_31;
  94. } PACKED gdt_segment_t;
  95. #define GDT_SEGMENT(base,limit,type,sflag,dpl,avl,size,granularity) \
  96. ( (gdt_segment_t) { \
  97. ( (limit) & 0xffff ), \
  98. ( (base) & 0xffff ), \
  99. ( ( (base) >> 16 ) & 0xff ), \
  100. ( ( 1 << 0 ) | ( (type) << 1 ) | \
  101. ( (sflag) << 4 ) | ( (dpl) << 5 ) | ( 1 << 7 ) ), \
  102. ( ( (limit) >> 16 ) | \
  103. ( (avl) << 4 ) | ( (size) << 5 ) | ( (granularity) << 7 ) ),\
  104. ( (base) >> 24 ) \
  105. } )
  106. #define GDT_SEGMENT_BASE(gdt_segment) \
  107. ( (gdt_segment)->base_0_15 | \
  108. (gdt_segment)->base_16_23 << 16 | \
  109. (gdt_segment)->base_24_31 << 24 )
  110. #define GDT_SEGMENT_LIMIT(gdt_segment) \
  111. ( (gdt_segment)->limit_0_15 | \
  112. ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
  113. & 0xf ) << 16 ) )
  114. #define GDT_SEGMENT_GRANULARITY(gdt_segment) \
  115. ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
  116. & 0x80 ) >> 7 )
  117. #define GDT_SEGMENT_TYPE(gdt_segment) \
  118. ( ( (gdt_segment)->accessed__type__sflag__dpl__present & 0x0e ) >> 1 )
  119. #define GDT_SEGMENT_SIZE(gdt_segment) \
  120. ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
  121. & 0x60 ) >> 5 )
  122. #define GDT_TYPE_DATA (0x0)
  123. #define GDT_TYPE_STACK (0x2)
  124. #define GDT_TYPE_WRITEABLE (0x1)
  125. #define GDT_TYPE_CODE (0x6)
  126. #define GDT_TYPE_EXEC_ONLY_CODE (0x4)
  127. #define GDT_TYPE_CONFORMING (0x1)
  128. #define GDT_SFLAG_SYSTEM (0)
  129. #define GDT_SFLAG_NORMAL (1)
  130. #define GDT_AVL_NORMAL (0)
  131. #define GDT_SIZE_16BIT (0x0)
  132. #define GDT_SIZE_32BIT (0x2)
  133. #define GDT_SIZE_64BIT (0x1)
  134. #define GDT_SIZE_UNKNOWN (0x3)
  135. #define GDT_GRANULARITY_SMALL (0)
  136. #define GDT_GRANULARITY_LARGE (1)
  137. #define GDT_SEGMENT_NORMAL(base,limit,type,size,granularity) \
  138. GDT_SEGMENT ( base, limit, type, \
  139. GDT_SFLAG_NORMAL, 0, GDT_AVL_NORMAL, \
  140. size, granularity )
  141. /* Protected mode code segment */
  142. #define GDT_SEGMENT_PMCS(base) GDT_SEGMENT_NORMAL ( \
  143. base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \
  144. GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
  145. #define GDT_SEGMENT_PMCS_PHYS GDT_SEGMENT_PMCS(0)
  146. /* Protected mode data segment */
  147. #define GDT_SEGMENT_PMDS(base) GDT_SEGMENT_NORMAL ( \
  148. base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
  149. GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
  150. #define GDT_SEGMENT_PMDS_PHYS GDT_SEGMENT_PMDS(0)
  151. /* Real mode code segment */
  152. /* Not sure if there's any reason to use GDT_TYPE_EXEC_ONLY_CODE
  153. * instead of just GDT_TYPE_CODE, but that's what our old GDT did and
  154. * it worked, so I'm not changing it.
  155. */
  156. #define GDT_SEGMENT_RMCS(base) GDT_SEGMENT_NORMAL ( \
  157. base, 0xffff, GDT_TYPE_EXEC_ONLY_CODE | GDT_TYPE_CONFORMING, \
  158. GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL )
  159. /* Real mode data segment */
  160. #define GDT_SEGMENT_RMDS(base) GDT_SEGMENT_NORMAL ( \
  161. base, 0xffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
  162. GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL )
  163. /* Long mode code segment */
  164. #define GDT_SEGMENT_LMCS(base) GDT_SEGMENT_NORMAL ( \
  165. base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \
  166. GDT_SIZE_64BIT, GDT_GRANULARITY_LARGE )
  167. #define GDT_SEGMENT_LMCS_PHYS GDT_SEGMENT_LMCS(0)
  168. /* Long mode data segment */
  169. /* AFIACT, GDT_SIZE_64BIT applies only to code segments */
  170. #define GDT_SEGMENT_LMDS(base) GDT_SEGMENT_NORMAL ( \
  171. base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
  172. GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
  173. #define GDT_SEGMENT_LMDS_PHYS GDT_SEGMENT_LMDS(0)
  174. /* Template for creating GDT structures (including segment register
  175. * lists), suitable for passing as parameters to external_call().
  176. */
  177. #define GDT_STRUCT_t(num_segments) \
  178. struct { \
  179. gdt_descriptor_t descriptor; \
  180. gdt_segment_t segments[num_segments]; \
  181. } PACKED
  182. /* And utility function for filling it in */
  183. #define GDT_ADJUST(structure) { \
  184. (structure)->descriptor.address = \
  185. virt_to_phys(&((structure)->descriptor.limit)); \
  186. (structure)->descriptor.limit = \
  187. sizeof((structure)->segments) + 8 - 1; \
  188. (structure)->descriptor.padding = 0; \
  189. }
  190. /* Data passed in to in_call() by assembly wrapper.
  191. */
  192. typedef struct {
  193. regs_t regs;
  194. seg_regs_t seg_regs;
  195. gdt_descriptor_t gdt_desc;
  196. uint32_t flags;
  197. struct {
  198. uint32_t offset;
  199. uint32_t segment;
  200. } ret_addr;
  201. } PACKED i386_pm_in_call_data_t;
  202. typedef struct {
  203. seg_regs_t seg_regs;
  204. union {
  205. uint16_t pad;
  206. uint16_t prefix_sp;
  207. };
  208. uint16_t flags;
  209. struct {
  210. uint16_t offset;
  211. uint16_t segment;
  212. } ret_addr;
  213. uint32_t orig_opcode;
  214. } PACKED i386_rm_in_call_data_t;
  215. typedef struct {
  216. i386_pm_in_call_data_t *pm;
  217. i386_rm_in_call_data_t *rm;
  218. } i386_in_call_data_t;
  219. #define in_call_data_t i386_in_call_data_t
  220. /* Function prototypes
  221. */
  222. extern int install_rm_callback_interface ( void *address, size_t available );
  223. #endif /* ASSEMBLY */
  224. #define RM_IN_CALL (0)
  225. #define RM_IN_CALL_FAR (2)
  226. #endif /* CALLBACKS_ARCH_H */