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

Last change on this file since 5655 was 5247, checked in by bird, 25 years ago

Calltable fixes. Handle event. New 14062e kernels.

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