1 /* Callout/callback interface for Etherboot
3 * This file provides the mechanisms for making calls from Etherboot
4 * to external programs and vice-versa.
6 * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
11 #ifndef CALLBACKS_ARCH_H
12 #define CALLBACKS_ARCH_H
14 /* Skip the definitions that won't make sense to the assembler */
17 /* Struct to hold general-purpose register values. PUSHAL and POPAL
18 * can work directly with this structure; do not change the order of
72 /* Struct to hold segment register values. Don't change the order;
73 * many bits of assembly code rely on it.
84 /* Struct for a GDT descriptor */
89 } PACKED gdt_descriptor_t;
91 /* Struct for a GDT entry. Use GDT_SEGMENT() to fill it in.
97 uint8_t accessed__type__sflag__dpl__present;
98 uint8_t limit_16_19__avl__size__granularity;
100 } PACKED gdt_segment_t;
102 #define GDT_SEGMENT(base,limit,type,sflag,dpl,avl,size,granularity) \
103 ( (gdt_segment_t) { \
104 ( (limit) & 0xffff ), \
105 ( (base) & 0xffff ), \
106 ( ( (base) >> 16 ) & 0xff ), \
107 ( ( 1 << 0 ) | ( (type) << 1 ) | \
108 ( (sflag) << 4 ) | ( (dpl) << 5 ) | ( 1 << 7 ) ), \
109 ( ( (limit) >> 16 ) | \
110 ( (avl) << 4 ) | ( (size) << 5 ) | ( (granularity) << 7 ) ),\
113 #define GDT_SEGMENT_BASE(gdt_segment) \
114 ( (gdt_segment)->base_0_15 | \
115 (gdt_segment)->base_16_23 << 16 | \
116 (gdt_segment)->base_24_31 << 24 )
117 #define GDT_SEGMENT_LIMIT(gdt_segment) \
118 ( (gdt_segment)->limit_0_15 | \
119 ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
121 #define GDT_SEGMENT_GRANULARITY(gdt_segment) \
122 ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
124 #define GDT_SEGMENT_TYPE(gdt_segment) \
125 ( ( (gdt_segment)->accessed__type__sflag__dpl__present & 0x0e ) >> 1 )
126 #define GDT_SEGMENT_SIZE(gdt_segment) \
127 ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
130 #define GDT_TYPE_DATA (0x0)
131 #define GDT_TYPE_STACK (0x2)
132 #define GDT_TYPE_WRITEABLE (0x1)
133 #define GDT_TYPE_CODE (0x6)
134 #define GDT_TYPE_EXEC_ONLY_CODE (0x4)
135 #define GDT_TYPE_CONFORMING (0x1)
136 #define GDT_SFLAG_SYSTEM (0)
137 #define GDT_SFLAG_NORMAL (1)
138 #define GDT_AVL_NORMAL (0)
139 #define GDT_SIZE_16BIT (0x0)
140 #define GDT_SIZE_32BIT (0x2)
141 #define GDT_SIZE_64BIT (0x1)
142 #define GDT_SIZE_UNKNOWN (0x3)
143 #define GDT_GRANULARITY_SMALL (0)
144 #define GDT_GRANULARITY_LARGE (1)
145 #define GDT_SEGMENT_NORMAL(base,limit,type,size,granularity) \
146 GDT_SEGMENT ( base, limit, type, \
147 GDT_SFLAG_NORMAL, 0, GDT_AVL_NORMAL, \
150 /* Protected mode code segment */
151 #define GDT_SEGMENT_PMCS(base) GDT_SEGMENT_NORMAL ( \
152 base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \
153 GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
154 #define GDT_SEGMENT_PMCS_PHYS GDT_SEGMENT_PMCS(0)
155 /* Protected mode data segment */
156 #define GDT_SEGMENT_PMDS(base) GDT_SEGMENT_NORMAL ( \
157 base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
158 GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
159 #define GDT_SEGMENT_PMDS_PHYS GDT_SEGMENT_PMDS(0)
160 /* Real mode code segment */
161 /* Not sure if there's any reason to use GDT_TYPE_EXEC_ONLY_CODE
162 * instead of just GDT_TYPE_CODE, but that's what our old GDT did and
163 * it worked, so I'm not changing it.
165 #define GDT_SEGMENT_RMCS(base) GDT_SEGMENT_NORMAL ( \
166 base, 0xffff, GDT_TYPE_EXEC_ONLY_CODE | GDT_TYPE_CONFORMING, \
167 GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL )
168 /* Real mode data segment */
169 #define GDT_SEGMENT_RMDS(base) GDT_SEGMENT_NORMAL ( \
170 base, 0xffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
171 GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL )
172 /* Long mode code segment */
173 #define GDT_SEGMENT_LMCS(base) GDT_SEGMENT_NORMAL ( \
174 base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \
175 GDT_SIZE_64BIT, GDT_GRANULARITY_LARGE )
176 #define GDT_SEGMENT_LMCS_PHYS GDT_SEGMENT_LMCS(0)
177 /* Long mode data segment */
178 /* AFIACT, GDT_SIZE_64BIT applies only to code segments */
179 #define GDT_SEGMENT_LMDS(base) GDT_SEGMENT_NORMAL ( \
180 base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
181 GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
182 #define GDT_SEGMENT_LMDS_PHYS GDT_SEGMENT_LMDS(0)
184 /* Template for creating GDT structures (including segment register
185 * lists), suitable for passing as parameters to external_call().
187 #define GDT_STRUCT_t(num_segments) \
189 gdt_descriptor_t descriptor; \
190 gdt_segment_t segments[num_segments]; \
192 /* And utility function for filling it in */
193 #define GDT_ADJUST(structure) { \
194 (structure)->descriptor.address = \
195 virt_to_phys(&((structure)->descriptor.limit)); \
196 (structure)->descriptor.limit = \
197 sizeof((structure)->segments) + 8 - 1; \
198 (structure)->descriptor.padding = 0; \
201 /* Data passed in to in_call() by assembly wrapper.
206 gdt_descriptor_t gdt_desc;
212 } PACKED i386_pm_in_call_data_t;
225 uint32_t orig_opcode;
226 } PACKED i386_rm_in_call_data_t;
229 i386_pm_in_call_data_t *pm;
230 i386_rm_in_call_data_t *rm;
231 } i386_in_call_data_t;
232 #define in_call_data_t i386_in_call_data_t
234 /* Function prototypes
236 extern int install_rm_callback_interface ( void *address, size_t available );
238 #endif /* ASSEMBLY */
240 #define RM_IN_CALL (0)
241 #define RM_IN_CALL_FAR (2)
243 #endif /* CALLBACKS_ARCH_H */