source: trunk/src/win32k/dev32/d32CallGate.asm@ 5229

Last change on this file since 5229 was 5224, checked in by bird, 25 years ago

CallGate changes.

File size: 13.2 KB
Line 
1; $Id: d32CallGate.asm,v 1.2 2001-02-21 07:44:57 bird Exp $
2;
3; 32-bit CallGate used to communitcate fast between Ring-3 and Ring-0.
4; This module contains all assembly workers for this.
5;
6; Copyright (c) 2001 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
7;
8; Project Odin Software License can be found in LICENSE.TXT
9;
10
11 .386p
12
13;
14; Defined Constants And Macros
15;
16 INCL_ERRORS EQU 1
17
18
19;
20; Header Files
21;
22 include bseerr.inc
23 include devsegdf.inc
24 include devhlp.inc
25 include win32k.inc
26
27
28;
29; Exported symbols
30;
31 public CallGateGDT
32
33 public InitCallGate
34 public Win32kAPIRouter
35
36
37;
38; External symbols
39;
40 extrn _Device_Help:dword
41 extrn pulTKSSBase32:dword
42
43 extrn KMEnterKmodeSEF:near
44 extrn KMExitKmodeSEF8:near
45 extrn _TKFuBuff@16:near
46
47 extrn k32AllocMemEx:near
48 extrn k32QueryOTEs:near
49 extrn k32QueryOptionsStatus:near
50 extrn k32SetOptions:near
51 extrn k32ProcessReadWrite:near
52 ;extrn k32HandleSystemEvent:near
53 extrn k32QuerySystemMemInfo:near
54 extrn k32QueryCallGate:near
55
56
57;
58; Global Variables
59;
60DATA16 segment
61CallGateGDT dw 0 ; GDT used for the 32-bit Ring-3 -> Ring-0 call gate.
62DATA16 ends
63
64DATA32 segment
65GDTR_limit dw ? ; The limit field of the GDTR.
66GDTR_base dd ? ; The base field of the GDTR. (linear flat address)
67
68
69;
70; Structure containing the K32 API parameter packet size.
71;
72; Used for parameter packet validation, and for copying the parameter
73; packet from user address space into system address space (the stack).
74;
75acbK32Params:
76 dd 0 ; Not used - ie. invalid
77 dd SIZE K32ALLOCMEMEX ; K32_ALLOCMEMEX 0x01
78 dd SIZE K32QUERYOTES ; K32_QUERYOTES 0x02
79 dd SIZE K32QUERYOPTIONSSTATUS ; K32_QUERYOPTIONSSTATUS 0x03
80 dd SIZE K32SETOPTIONS ; K32_SETOPTIONS 0x04
81 dd SIZE K32PROCESSREADWRITE ; K32_PROCESSREADWRITE 0x05
82 dd SIZE K32HANDLESYSTEMEVENT ; K32_HANDLESYSTEMEVENT 0x06
83 dd SIZE K32QUERYSYSTEMMEMINFO ; K32_QUERYSYSTEMMEMINFO 0x07
84 dd SIZE K32QUERYCALLGATE ; K32_QUERYCALLGATE 0x08
85
86;
87; Structure containing the offsets of K32 API worker routines.
88;
89; Used for calling the workers indirectly.
90;
91apfnK32APIs:
92 dd FLAT:k32APIStub ; Not used - ie. invalid
93 dd FLAT:k32AllocMemEx ; K32_ALLOCMEMEX 0x01
94 dd FLAT:k32QueryOTEs ; K32_QUERYOTES 0x02
95 dd FLAT:k32QueryOptionsStatus ; K32_QUERYOPTIONSSTATUS 0x03
96 dd FLAT:k32SetOptions ; K32_SETOPTIONS 0x04
97 dd FLAT:k32ProcessReadWrite ; K32_PROCESSREADWRITE 0x05
98 ;dd FLAT:k32HandleSystemEvent ; K32_HANDLESYSTEMEVENT 0x06
99 dd FLAT:k32APIStub
100 dd FLAT:k32QuerySystemMemInfo ; K32_QUERYSYSTEMMEMINFO 0x07
101 dd FLAT:k32QueryCallGate ; K32_QUERYCALLGATE 0x08
102DATA32 ends
103
104
105
106CODE32 segment
107 assume cs:CODE32, ds:FLAT ;, es:nothing, ss:nothing
108
109;;
110; This function initiates the callgate.
111; @cproto extern ULONG _Optlink InitCallGate(void);
112; @returns 0 (NO_ERROR) on success.
113; appropriate error code on error.
114; @uses eax, ecx, edx
115; @sketch
116; @status
117; @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
118; @remark
119InitCallGate proc near
120 push ebp
121 mov ebp, esp
122 push edi
123 push esi
124 push ebx
125 push ds
126 push es
127
128 ;
129 ; Allocate GDT selector for the call gate.
130 ; (URG! This call also allocates 68kb of virtual memory which i don't need!)
131 ;
132 mov di, seg DATA16:CallGateGDT
133 mov es, di
134 mov di, offset DATA16:CallGateGDT
135 mov cx, 1
136 mov dl, DevHlp_AllocGDTSelector
137 jmp far ptr CODE16:Thunk16_AllocGDTSelector
138Thunk32_AllocGDTSelector::
139 jnc ICG_allocok
140 movzx eax, ax ; We failed, zero high word of eax to return proper return code.
141 jmp ICG_end ; bail out.
142
143 ;
144 ; We successfully allocate the callgate GDT.
145 ; How we'll find the descriptor entry for it.
146 ;
147ICG_allocok:
148 ASSUME ds:FLAT
149 sgdt GDTR_limit ; Get the GDTR content.
150 mov ax, GDTR_limit
151 mov ebx, GDTR_base
152 movzx ecx, CallGateGDT
153 and cx, 0fff8h ; clear the dpl bits and descriptor type bit. (paranoia!)
154 cmp cx, ax ; check limit. (paranoia!!!)
155 jl ICG_limitok
156 mov eax, 0ffffffffh ; return failure.
157 jmp ICG_end
158ICG_limitok:
159 add ebx, ecx ; GDTR_base + selector offset -> flat pointer to selector.
160
161 ;
162 ; ebx is pointing to the descriptor table entry for my GDT selector.
163 ; Now we'll have to change it into a callgate.
164 ; This is the layout of a callgate descriptor:
165 ; bits
166 ; 0-15 Segment offset low word
167 ; 16-31 Segment selector
168 ; -------second dword-------
169 ; 0-4 Param Count
170 ; 5-7 Reserved (zero)
171 ; 8-11 Selector type - 1100b
172 ; 12 Reserved (UVirt) zero
173 ; 13-14 Descriptor Privelege Level (DPL)
174 ; 15 Present flag / Gate valid.
175 ; 16-31 Segment offset high word.
176 ;
177 mov eax, offset FLAT:Win32kCallGate
178 mov word ptr [ebx], ax ; set low segment offset word
179 shr eax, 10h
180 mov word ptr [ebx + 6], ax ; set high segment offset word
181
182 mov word ptr [ebx + 4], 1110110000000010b ; set flags and stuff.
183 ; param count: Two (2) - parameter struct and function number
184 ; type: 32-bit call gate
185 ; DPL: Ring-3
186 ; Gate Valid: Yes
187 mov word ptr [ebx + 2], seg FLAT:CODE32 ; Set the selector to FLAT Ring-0 code selector.
188 xor eax, eax ; return successfully.
189
190ICG_end:
191 pop es
192 pop ds
193 pop ebx
194 pop esi
195 pop edi
196 leave
197 ret
198InitCallGate endp
199
200
201
202;;
203; This is the callgate procedure.
204; @cproto none
205; @returns return value of the callgate router.
206; @param fill inn later....
207; @uses eax, ecx, edx
208; @sketch
209; @status
210; @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
211; @remark
212; stack frame - before KMEnterKmodeSEF:
213; --bottom of stack---
214; calling ss 1ch
215; calling esp 18h
216; pParameter (parameter 1) 14h
217; ulFunctionCode (parameter 0) 10h
218; calling cs 0ch
219; calling eip <-- esp points here upon entry. 8h
220; ---top of stack---
221; flags (pushf) 4h
222; parameter size (push 8h) 0h
223;
224; After the call to KMEnterKmodeSEF:
225; --bottom of stack---
226; calling ss 50
227; calling esp 4c
228; pParameter (parameter 1) 48
229; ulFunctionCode (parameter 0) 44
230; sef_cs 40
231; sef_eip 3c
232; sef_eflag 38
233; sef_cbargs 34
234; sef_retaddr 30
235; sef_ds 2c
236; sef_es 28
237; sef_fs 24
238; sef_gs 20
239; sef_eax 1c
240; sef_ecx 18
241; sef_edx 14
242; sef_ebx 10
243; sef_padesp c
244; sef_ebp 8
245; sef_esi 4h
246; sef_edi 0h
247;
248Win32kCallGate proc near
249 ASSUME ds:nothing, ss:nothing
250 pushfd ; Push all flags (eflags)
251 push 8h ; Size of parameters.
252
253 call KMEnterKmodeSEF ; This is an OS2 kernel function which does
254 ; kernel entry housekeeping.
255
256 mov edx, [esp + 48h] ; pParameter (parameter 1)
257 mov eax, [esp + 44h] ; ulFunctionCode (parameter 2)
258 sub esp, 8h ; (Even when using _Oplink we have to reserve space for parameters.)
259 call Win32kAPIRouter ; This is my Ring-0 api. (d32Win32kIOCtl.c)
260 add esp, 8h
261
262 jmp KMExitKmodeSEF8 ; This a an OS2 kernel function which does
263 ; kernel exist housekeeping.
264Win32kCallGate endp
265
266
267;;
268; Internal function router which calls the correct function.
269; Called from IOCtl worker in d32Win32kIOCtl.c and callgate.
270; @cproto APIRET _Optlink Win32kAPIRouter(ULONG ulFunction, PVOID pvParam);
271; @returns function return code.
272; 0xdeadbeef if invalid function number.
273; @param eax - ulFunction Function number to call.
274; @param edx - pvParam Parameter packet for that function.
275; @uses eax, edx, ecx
276; @sketch Validate function number
277; Fetch the parameter pacted from user mode and place it on the stack.
278; Validate the size field of the parameter packet.
279; Remove the packet header from the stack => we have a callframe for the api.
280; Call the API worker.
281; Return.
282; @status Completely implemented.
283; @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
284Win32kAPIRouter proc near
285 ASSUME ds:FLAT, es:nothing, ss:nothing
286 ;
287 ; Validate function number.
288 ;
289 cmp eax, 0
290 jne APIR_notnull ; This code should be faster (though it may look stupid to
291 ; jump around like this). IIRC branch prediction allways
292 ; takes a branch. And btw there are 4 NOPs after this jump!
293 jmp APIR_InvalidFunction
294
295APIR_notnull:
296 cmp eax, K32_LASTIOCTLFUNCTION
297 jle APIR_ValidFunction
298APIR_InvalidFunction:
299 mov eax, 0deadbeefh
300 ret
301
302 ;
303 ; We have a valid function number now.
304 ; Copy the parameter struct on to the stack.
305 ;
306APIR_ValidFunction:
307 push ebp ; Make stack frame
308 mov ebp, esp
309 mov [ebp+8], eax ; Save eax on the stack (reserved by caller according to _Optlink)
310 mov ecx, acbK32Params[eax*4] ; ecx <- size of parameter packet.
311 sub esp, ecx ; Reserve stack space for the parameter packet.
312 mov eax, [pulTKSSBase32]
313 mov eax, [eax]
314 add eax, esp ; Calculate the FLAT address of esp.
315 push ecx ; Save the size.
316 ; TKFuBuff(pv, pvParam, acbParams[ulFunction], TK_FUSU_NONFATAL);
317 push 0 ; TK_FUSU_NOFATAL
318 push ecx ; Size of parameter packet
319 push edx ; Pointer to user memory to fetch
320 push eax ; Pointer to target memory.
321 call _TKFuBuff@16 ; __stdcall (cleanup done by the called function)
322 pop ecx ; Restore size
323 test eax, eax
324 jz APIR_FetchOK
325 jmp APIR_end
326
327 ;
328 ; Parameter packet is now read onto the stack. esp is pointing to it.
329 ; Check the size of the struct as the caller sees it.
330 ;
331APIR_FetchOK:
332 cmp ecx, [esp] ; (esp now point at the parameter struct)
333 je APIR_sizeok
334 mov eax, ERROR_BAD_ARGUMENTS ; return code.
335 jmp APIR_end
336
337 ;
338 ; The size is correct.
339 ; Call the worker and return.
340 ;
341APIR_sizeok:
342 add esp, SIZE K32HDR ; Skip the parameter header.
343 mov eax, [ebp + 8] ; Restore function number.
344 mov eax, apfnK32APIs[eax*4] ; eax <- address of the K32 API worker.
345 call eax ; Call the worker.
346 ; No cleanup needed as leave takes care of that
347 ; We're ready for returning.
348APIR_end:
349 leave
350 ret
351Win32kAPIRouter endp
352
353
354;;
355; This is a stub function which does nothing but returning an error code.
356; @return ERROR_NOT_SUPPORTED
357k32APIStub proc near
358 mov eax, ERROR_NOT_SUPPORTED
359 ret
360k32APIStub endp
361
362CODE32 ends
363
364
365
366
367
368CODE16 segment
369 assume cs:CODE16, ds:FLAT
370
371;
372; Thunker used by the InitCallGate procedure call the AllocGDTSelector devhelper.
373;
374Thunk16_AllocGDTSelector:
375 call [_Device_Help]
376 jmp far ptr FLAT:Thunk32_AllocGDTSelector
377
378CODE16 ends
379
380end
381
Note: See TracBrowser for help on using the repository browser.