[build] Fix signed/unsigned division in util/zbin.c
[people/lynusvaz/gpxe.git] / src / arch / i386 / include / callbacks_arch.h
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
11 #ifndef CALLBACKS_ARCH_H
12 #define CALLBACKS_ARCH_H
13
14 /* Skip the definitions that won't make sense to the assembler */
15 #ifndef ASSEMBLY
16
17 /* Struct to hold general-purpose register values.  PUSHAL and POPAL
18  * can work directly with this structure; do not change the order of
19  * registers.
20  */
21 typedef struct {
22         union {
23                 uint16_t di;
24                 uint32_t edi;
25         };
26         union {
27                 uint16_t si;
28                 uint32_t esi;
29         };
30         union {
31                 uint16_t bp;
32                 uint32_t ebp;
33         };
34         union {
35                 uint16_t sp;
36                 uint32_t esp;
37         };
38         union {
39                 struct {
40                         uint8_t bl;
41                         uint8_t bh;
42                 } PACKED;
43                 uint16_t bx;
44                 uint32_t ebx;
45         };
46         union {
47                 struct {
48                         uint8_t dl;
49                         uint8_t dh;
50                 } PACKED;
51                 uint16_t dx;
52                 uint32_t edx;
53         };
54         union {
55                 struct {
56                         uint8_t cl;
57                         uint8_t ch;
58                 } PACKED;
59                 uint16_t cx;
60                 uint32_t ecx;
61         };
62         union {
63                 struct {
64                         uint8_t al;
65                         uint8_t ah;
66                 } PACKED;
67                 uint16_t ax;
68                 uint32_t eax;
69         };
70 } regs_t;
71
72 /* Struct to hold segment register values.  Don't change the order;
73  * many bits of assembly code rely on it.
74  */
75 typedef struct {
76         uint16_t cs;
77         uint16_t ss;
78         uint16_t ds;
79         uint16_t es;
80         uint16_t fs;
81         uint16_t gs;
82 } PACKED seg_regs_t;
83
84 /* Struct for a GDT descriptor */
85 typedef struct {
86                 uint16_t limit;
87                 uint32_t address;
88                 uint16_t padding;
89 } PACKED gdt_descriptor_t;
90
91 /* Struct for a GDT entry.  Use GDT_SEGMENT() to fill it in.
92  */
93 typedef struct {
94         uint16_t limit_0_15;
95         uint16_t base_0_15;
96         uint8_t base_16_23;
97         uint8_t accessed__type__sflag__dpl__present;
98         uint8_t limit_16_19__avl__size__granularity;
99         uint8_t base_24_31;
100 } PACKED gdt_segment_t;
101
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 ) ),\
111                 ( (base) >> 24 ) \
112         } )
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 \
120               & 0xf ) << 16 ) )
121 #define GDT_SEGMENT_GRANULARITY(gdt_segment) \
122         ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
123             & 0x80 ) >> 7 )
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 \
128             & 0x60 ) >> 5 )
129
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, \
148                       size, granularity )
149
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.
164  */
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)
183
184 /* Template for creating GDT structures (including segment register
185  * lists), suitable for passing as parameters to external_call().
186  */
187 #define GDT_STRUCT_t(num_segments) \
188         struct { \
189                 gdt_descriptor_t descriptor; \
190                 gdt_segment_t segments[num_segments]; \
191         } PACKED
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; \
199 }
200
201 /* Data passed in to in_call() by assembly wrapper.
202  */
203 typedef struct {
204         regs_t          regs;
205         seg_regs_t      seg_regs;
206         gdt_descriptor_t gdt_desc;
207         uint32_t        flags;
208         struct {
209                 uint32_t offset;
210                 uint32_t segment;
211         } ret_addr;
212 } PACKED i386_pm_in_call_data_t;
213
214 typedef struct {
215         seg_regs_t      seg_regs;
216         union {
217                 uint16_t        pad;
218                 uint16_t        prefix_sp;
219         };
220         uint16_t        flags;
221         struct {
222                 uint16_t offset;
223                 uint16_t segment;
224         } ret_addr;
225         uint32_t orig_opcode;
226 } PACKED i386_rm_in_call_data_t;
227
228 typedef struct {
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
233
234 /* Function prototypes
235  */
236 extern int install_rm_callback_interface ( void *address, size_t available );
237
238 #endif /* ASSEMBLY */
239
240 #define RM_IN_CALL      (0)
241 #define RM_IN_CALL_FAR  (2)
242
243 #endif /* CALLBACKS_ARCH_H */