-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathINT.c
337 lines (321 loc) · 11.6 KB
/
INT.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/****************************************************************************/
/** **/
/** INT.c **/
/** **/
/** Stack and interrupt manipulation routines for DJGPP **/
/** **/
/** Copyright (C) Marcel de Kogel 1996 **/
/** You are not allowed to distribute this software commercially **/
/** Please, notify me, if you make any changes to this file **/
/****************************************************************************/
#include <stdlib.h>
#include <dos.h>
#include <go32.h>
#include <dpmi.h>
#include <stdio.h>
#include <string.h>
#include "INT.h"
#define MIN_STACK_SIZE 1024 /* Minumum stack size */
#define MAX_STACK_SIZE 524288 /* Maximum stack size */
#define MIN_STACK_NR 4 /* Minimum number of stacks */
#define MAX_STACK_NR 256 /* Maximum number of stacks */
static unsigned **StackPtr; /* Pointer to an array of stack pointers */
static int StackSize; /* Size of a stack */
static int NumStacks; /* Number of stacks */
static int NumStacksUsed; /* Number of stacks currently used */
static int NumFailed; /* Number of allocations currently failed */
/* Number of calls to AllocStack() that failed */
static int TotalFailed=0;
/* Number of calls to AllocStack() that succeeded */
static int TotalSuccess=0;
/* Maximum number of stacks used simultaniously */
static int MaxStacksUsed=0;
/* Maximum stack size used */
static int MaxStackSize=0;
/* Lock variables */
static int LockData (void *addr,unsigned size)
{
unsigned long base;
__dpmi_meminfo info;
if (__dpmi_get_segment_base_address(_go32_my_ds(),&base)==-1)
return 0;
info.handle=0;
info.address=base+(unsigned)addr;
info.size=size;
if (__dpmi_lock_linear_region(&info)==-1)
return 0;
return 1;
}
/* Unlock variables */
static int UnlockData (void *addr,unsigned size)
{
unsigned long base;
__dpmi_meminfo info;
if (__dpmi_get_segment_base_address(_go32_my_ds(),&base)==-1)
return 0;
info.handle=0;
info.address=base+(unsigned)addr;
info.size=size;
if (__dpmi_unlock_linear_region(&info)==-1)
return 0;
return 1;
}
/****************************************************************************/
/*** GetStackInfo() ***/
/*** Get some info useful for debugging ***/
/****************************************************************************/
void GetStackInfo (int *nFailed,int *nSuccess,int *nUsed,int *nMaxSize)
{
*nFailed=TotalFailed;
*nSuccess=TotalSuccess;
*nUsed=MaxStacksUsed;
*nMaxSize=MaxStackSize;
}
/****************************************************************************/
/*** ExitStacks() ***/
/*** Free all resources allocated by InitStacks() ***/
/****************************************************************************/
void ExitStacks (void)
{
int i,j;
int maxsize=0;
unsigned char *p;
if (!StackPtr)
return;
for (i=0;i<NumStacks;++i)
if (StackPtr[i])
{
p=(unsigned char*)StackPtr[i];
for (j=0;j<StackSize;++j)
if (p[j]!=0xF6) break;
j=(StackSize-j)&(~3);
if (maxsize<j) maxsize=j;
UnlockData (StackPtr[i],StackSize);
free (StackPtr[i]);
}
else
break;
UnlockData (StackPtr,NumStacks*sizeof(unsigned*));
free (StackPtr);
StackPtr=0;
MaxStackSize=maxsize;
}
/****************************************************************************/
/*** InitStacks() ***/
/*** Allocate stacks and initialise structures ***/
/****************************************************************************/
int InitStacks (int nr,int size)
{
int i;
if (StackPtr)
return 1; /* already called */
if (size<MIN_STACK_SIZE)
size=MIN_STACK_SIZE;
if (size>MAX_STACK_SIZE)
size=MAX_STACK_SIZE;
if (nr<MIN_STACK_NR)
nr=MIN_STACK_NR;
if (nr>MAX_STACK_NR)
nr=MAX_STACK_NR;
if (size&3)
size=(size&(~3))+4; /* stack must be dword-aligned */
StackPtr=malloc (nr*sizeof(unsigned*));
if (!StackPtr)
return 0;
if (!LockData (StackPtr,nr*sizeof(unsigned*)))
return 0;
StackSize=size;
NumStacks=nr;
for (i=0;i<nr;++i)
{
StackPtr[i]=malloc(size);
if (!StackPtr[i] || !LockData (StackPtr[i],size))
{
ExitStacks ();
return 0;
}
memset (StackPtr[i],0xF6,size);
}
NumStacksUsed=0;
NumFailed=0;
return 1;
}
/****************************************************************************/
/*** AllocStack() ***/
/*** Allocate a stack, return 0 when no stack could be allocated ***/
/*** FreeStack() must be called wether a stack could be allocated or not ***/
/*** Clobbers all registers ***/
/****************************************************************************/
asm ("
.globl _AllocStack
_AllocStack:
popl %esi
movl _NumStacksUsed,%eax
cmpl _NumStacks,%eax
jae AllocStack_Failed
incl %eax
movl %eax,_NumStacksUsed
cmpl _MaxStacksUsed,%eax
jbe Alloc_1
movl %eax,_MaxStacksUsed
Alloc_1:
incl _TotalSuccess
movl _StackPtr,%ebx
decl %eax
leal (%ebx,%eax,4),%ebx
movl (%ebx),%ebx
addl _StackSize,%ebx
subl $64,%ebx
movw %ss,%cx
movl %esp,%edx
movw %ds,%ax
movw %ax,%ss
movl %ebx,%esp
pushl %edx
pushw %cx
movl $1,%eax
jmpl %esi
AllocStack_Failed:
incl _NumFailed
incl _TotalFailed
subl %eax,%eax
jmpl %esi
/****************************************************************************/
/*** FreeStack() ***/
/*** Frees a stack previously allocated by AllocStack() ***/
/*** Clobbers all registers ***/
/****************************************************************************/
.globl _FreeStack
_FreeStack:
popl %esi
cmpl $0,_NumFailed
jne FreeStack_Failed
popw %ax
popl %edx
movw %ax,%ss
movl %edx,%esp
decl _NumStacksUsed
jmpl %esi
FreeStack_Failed:
decl _NumFailed
jmpl %esi
");
/****************************************************************************/
/*** The interrupt handler definition ***/
/****************************************************************************/
#define FILL 0x00 /* must be unique */
static unsigned char handler[] =
{
0x60, /* pushad */
0x0F,0xA8, /* push gs */
0x0F,0xA0, /* push fs */
0x06, /* push es */
0x1E, /* push ds */
0x2E,0xA1,FILL,FILL,FILL,FILL, /* mov eax,[cs:_cs_alias] */
0x8E,0xD8, /* mov ds,ax */
0x8E,0xC0, /* mov es,ax */
0x8E,0xE0, /* mov fs,ax */
0x8E,0xE8, /* mov gs,ax */
0xFC, /* cld */
0xE8,FILL,FILL,FILL,FILL, /* call _AllocStack */
0x85,0xC0, /* test eax,eax */
0x74,0x11, /* jz _0 */
0xE8,FILL,FILL,FILL,FILL, /* call _interrupt_handler */
0x85,0xC0, /* test eax,eax */
0x74,0x08, /* jz _0 */
0x9C, /* pushfd */
0x9A,FILL,FILL,FILL,FILL,FILL,FILL, /* call _old_handler */
/* _0: */
0xFA, /* cli */
0xE8,FILL,FILL,FILL,FILL, /* call _FreeStack */
0x1F, /* pop ds */
0x07, /* pop es */
0x0F,0xA1, /* pop fs */
0x0F,0xA9, /* pop gs */
0x61, /* popad */
0xCF /* iretd */
};
static int cs_alias; /* selector of our data segment */
/****************************************************************************/
/*** SetInt() ***/
/*** Allocate an interrupt handler and set the interrupt vector ***/
/*** The user-written interrupt handler must return 0 if the old ***/
/*** interrupt vector isn't to be called, and 1 otherwise ***/
/****************************************************************************/
int SetInt (int nr,_go32_dpmi_seginfo *info)
{
int i;
unsigned char *p;
_go32_dpmi_seginfo oldinfo;
/* Initialise cs_alias */
cs_alias=_my_ds ();
/* Make sure InitStacks() is called */
if (!InitStacks (8,8192))
return 0;
/* Allocate and lock memory */
p=malloc (sizeof(handler));
if (!p)
return 0;
if (!LockData (p,sizeof(handler)))
return 0;
/* Get old interrupt vector */
_go32_dpmi_get_protected_mode_interrupt_vector (nr,&oldinfo);
/* Copy the handler structure to the allocated handler */
memcpy (p,handler,sizeof(handler));
/* Initialise the handler */
i=-1;
while (p[++i]!=FILL);
*(unsigned*)(p+i)=(unsigned)&cs_alias;
i+=3;
while (p[++i]!=FILL);
*(unsigned*)(p+i)=((unsigned)AllocStack)-((unsigned)(p+i+4));
i+=3;
while (p[++i]!=FILL);
*(unsigned*)(p+i)=((unsigned)info->pm_offset)-((unsigned)(p+i+4));
i+=3;
while (p[++i]!=FILL);
*(unsigned*)(p+i)=(unsigned)oldinfo.pm_offset;
*(unsigned short*)(p+i+4)=(unsigned short)oldinfo.pm_selector;
i+=5;
while (p[++i]!=FILL);
*(unsigned*)(p+i)=((unsigned)FreeStack)-((unsigned)(p+i+4));
/* Fill the info structure */
info->pm_offset=(unsigned)p;
info->pm_selector=_go32_my_cs();
/* Set the interrupt vector */
_go32_dpmi_set_protected_mode_interrupt_vector (nr,info);
/* return success */
return 1;
}
/****************************************************************************/
/*** ResetInt() ***/
/*** Free resources allocated by SetInt() ***/
/****************************************************************************/
int ResetInt (int nr,_go32_dpmi_seginfo *info)
{
unsigned char *p;
int i;
/* get pointer */
p=(unsigned char*)info->pm_offset;
/* make sure it's valid */
if (!p) return 0;
/* check if it points to an interrupt handler */
if (*(unsigned*)p!=*(unsigned*)handler) return 0;
/* get old interrupt vector */
i=-1;
while (handler[++i]!=FILL);
i+=3;
while (handler[++i]!=FILL);
i+=3;
while (handler[++i]!=FILL);
i+=3;
while (handler[++i]!=FILL);
info->pm_offset=*(unsigned*)(p+i);
info->pm_selector=*(unsigned short*)(p+i+4);
/* set old interrupt vector */
_go32_dpmi_set_protected_mode_interrupt_vector (nr,info);
/* unlock and free memory */
UnlockData (p,sizeof(handler));
free (p);
return 1;
}