source: trunk/src/win32k/dev32/d32init.c@ 1535

Last change on this file since 1535 was 1535, checked in by bird, 26 years ago

Updated option/argument handling.
Corrected a few bugs.

File size: 13.1 KB
Line 
1/* $Id: d32init.c,v 1.3 1999-10-31 23:57:02 bird Exp $
2 *
3 * d32init.c - 32-bits init routines.
4 *
5 * Copyright (c) 1998-1999 knut st. osmundsen
6 *
7 */
8
9/*******************************************************************************
10* Defined Constants *
11*******************************************************************************/
12#define MAXSIZE_PROLOG 0x10 /* Note that this must be synced with */
13 /* the one used in calltab.asm. */
14#define static
15
16#define INCL_DOSERRORS
17#define INCL_NOPMAPI
18#define LDR_INCL_INITONLY
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <os2.h>
24
25#include <string.h>
26
27#include "OS2Krnl.h"
28#include "options.h"
29#include "dev1632.h"
30#include "dev32.h"
31#include "probkrnl.h"
32#include "log.h"
33#include "asmutils.h"
34#include "malloc.h"
35#include "ldr.h"
36#include "ldrCalls.h"
37
38
39/*******************************************************************************
40* Internal Functions *
41*******************************************************************************/
42static int interpretFunctionProlog(char *p);
43static int procInit(void);
44
45
46/* externs located in 16-bit data segement */
47extern ULONG _TKSSBase16;
48extern USHORT _R0FlatCS16;
49extern USHORT _R0FlatDS16;
50
51
52/* extern(s) located in calltab.asm */
53extern char callTab[NUMBER_OF_PROCS][MAXSIZE_PROLOG];
54
55
56/**
57 * Ring-0, 32-bit, init function.
58 * @returns Status word.
59 * @param pRpInit Pointer init request packet.
60 * @sketch Set TKSSBase32.
61 * Set default parameters.
62 * Parse command line options.
63 * Show (kprint) configuration.
64 * Init heap.
65 * Init ldr.
66 * Init procs. (overloaded ldr procedures)
67 * @status completely implemented.
68 * @author knut st. osmundsen
69 */
70USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
71{
72 char *pszTmp2;
73 char *pszTmp;
74
75 pulTKSSBase32 = (PULONG)_TKSSBase16;
76
77 SET_OPTIONS_TO_DEFAULT(options);
78
79 /*---------------------*/
80 /* commandline options */
81 /*---------------------*/
82 kprintf(("Options start\n"));
83 pszTmp = strpbrk(pRpInit->InitArgs, "-/");
84 while (pszTmp != NULL)
85 {
86 char cch;
87 pszTmp++; //skip [-/]
88 cch = strlen(pszTmp);
89 switch (*pszTmp)
90 {
91 case 'c':
92 case 'C': /* -C[1|2] - com-port no, def:-C2 */
93 switch (pszTmp[1])
94 {
95 case '1':
96 options.usCom = OUTPUT_COM1;
97 break;
98
99 case '2':
100 default:
101 options.usCom = OUTPUT_COM2;
102 }
103 break;
104
105 case 'e':
106 case 'E':/* ELF */
107 pszTmp2 = strpbrk(pszTmp, ":=/- ");
108 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
109 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
110 )
111 options.fElf = FALSE;
112 else
113 options.fElf = TRUE;
114 break;
115
116 case 'l':
117 case 'L': /* -L[..]<:|=| >[<Y..|E..| > | <N..|D..>] */
118 pszTmp2 = strpbrk(pszTmp, ":=/- ");
119 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
120 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
121 )
122 options.fLogging = FALSE;
123 else
124 options.fLogging = TRUE;
125 break;
126
127 case 'n':
128 case 'N': /* NoLoader */
129 options.fNoLoader = TRUE;
130 break;
131
132 case 'p':
133 case 'P': /* PE */
134 pszTmp2 = strpbrk(pszTmp, ":=/- ");
135 if (pszTmp2 != NULL && (*pszTmp == ':' || *pszTmp == '='))
136 {
137 pszTmp++;
138 if (strnicmp(pszTmp, "pe2lx", 5) == 0)
139 options.fPE = FLAGS_PE_PE2LX;
140 else if (strnicmp(pszTmp, "pe", 2) == 0)
141 options.fPE = FLAGS_PE_PE;
142 else if (strnicmp(pszTmp, "mixed", 2) == 0)
143 options.fPE = FLAGS_PE_MIXED;
144 else if (strnicmp(pszTmp, "not", 2) == 0)
145 options.fPE = FLAGS_PE_NOT;
146 else
147 kprintf(("R0Init32: invalid parameter -PE:...\n"));
148 }
149 else
150 kprintf(("R0Init32: invalid parameter -PE...\n"));
151 break;
152
153 case 'q':
154 case 'Q': /* quiet initialization */
155 options.fQuiet = TRUE;
156 break;
157
158 case 's':
159 case 'S': /* SMP kernel */
160 options.fKernel = KF_SMP;
161 break;
162
163 case 'v':
164 case 'V': /* verbose initialization */
165 options.fQuiet = FALSE;
166 break;
167
168 case 'u':
169 case 'U': /* UNI kernel */
170 options.fKernel = KF_SMP;
171 break;
172 }
173 pszTmp = strpbrk(pszTmp, "-/");
174 }
175
176 /* Transfer version and build number from 16-bit probkrnl.c */
177 options.ulBuild = _ulBuild;
178 options.usVerMajor = _usVerMajor;
179 options.usVerMinor = _usVerMinor;
180
181 /* log option summary */
182 kprintf(("Options - Summary\n"));
183 kprintf(("\tKernel: ver%d.%d build %d type %s\n",
184 options.usVerMajor,
185 options.usVerMinor,
186 options.ulBuild,
187 (options.fKernel & KF_SMP) ? "SMP" : "UNI"
188 ));
189 kprintf(("\tCom port no.%d\n", options.usCom));
190 if (options.fQuiet)
191 kprintf(("\tQuiet init\n"));
192 else
193 kprintf(("\tVerbose init\n"));
194 if (options.fLogging)
195 kprintf(("\tlogging enabled\n"));
196 else
197 kprintf(("\tlogging disabled\n"));
198 /* end option summary */
199
200
201 /*
202 * init sub-parts
203 */
204 /* heap */
205 if (heapInit(options.cbHeap) != NO_ERROR)
206 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
207
208 /* loader */
209 if (!options.fNoLoader)
210 if (ldrInit() != NO_ERROR)
211 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
212
213 /* functionoverrides */
214 if (!options.fNoLoader)
215 if (procInit() != NO_ERROR)
216 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
217
218 return STATUS_DONE;
219}
220
221
222/**
223 * Verifies the aProcTab.
224 * @returns 0 if ok. !0 if not ok.
225 * @remark Called from IOCtl.
226 */
227USHORT _loadds _Far32 _Pascal VerifyProcTab32(void)
228{
229 int i;
230 int cb;
231
232 /* verify */
233 for (i = 0; i < NUMBER_OF_PROCS; i++)
234 {
235 /* verify that it is found */
236 if (!_aProcTab[i].fFound)
237 {
238 kprintf(("VerifyProcTab32: procedure no.%d was not found!\n", i));
239 return STATUS_DONE | STERR | 1;
240 }
241
242 /* verify read/writeable. - FIXME */
243 if (_aProcTab[i].ulAddress < 0xffe00000UL)
244 {
245 kprintf(("VerifyProcTab32: procedure no.%d has an invlalid address, %#08x!\n",
246 i, _aProcTab[i].ulAddress));
247 return STATUS_DONE | STERR | 2;
248 }
249
250 /* verify known function prolog. (only EPT_PROC) */
251 if (_aProcTab[i].fType == EPT_PROC)
252 {
253 if ((cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress)) <= 0 && cb + 5 >= MAXSIZE_PROLOG)
254 {
255 kprintf(("VerifyProcTab32: verify failed for procedure no.%d\n",i));
256 return STATUS_DONE | STERR | 3;
257 }
258 }
259 else
260 {
261 kprintf(("VerifyProcTab32: only EPT_PROC is implemented\n",i));
262 return STATUS_DONE | STERR | 4;
263 }
264 }
265
266 return STATUS_DONE;
267}
268
269
270/**
271 * Get kernel OTEs
272 * @returns Strategy return code:
273 * STATUS_DONE on success.
274 * STATUS_DONE | STERR | errorcode on failure.
275 * @param pOTEBuf Pointer to output buffer.
276 * @status completely implemented and tested.
277 * @author knut st. osmundsen
278 * @remark Called from IOCtl.
279 */
280USHORT _loadds _Far32 _Pascal GetOTEs32(PKRNLOBJTABLE pOTEBuf)
281{
282 PMTE pMTE;
283 PSMTE pSMTE;
284 POTE pOTE;
285 int i;
286 USHORT usRc;
287
288 pMTE = GetOS2KrnlMTE();
289 if (pMTE != NULL)
290 {
291 pSMTE = pMTE->mte_swapmte;
292 if (pSMTE != NULL)
293 {
294 pOTEBuf->cObjects = pSMTE->smte_objcnt;
295 if (pSMTE->smte_objcnt <= MAXKRNLOBJECTS)
296 {
297 pOTE = pSMTE->smte_objtab;
298 if (pOTE != NULL)
299 {
300 for (i = 0; i < pOTEBuf->cObjects; i++)
301 memcpy((void*)&pOTEBuf->aObjects[i], &pOTE[i], sizeof(OTE));
302 usRc = 0;
303 }
304 else
305 usRc = 4;
306 }
307 else
308 usRc = 3;
309 }
310 else
311 usRc = 2;
312 }
313 else
314 usRc = 1;
315
316 if (usRc != 0)
317 kprintf(("GetOTEs32: failed. usRc = %d\n", usRc));
318
319 return usRc | (usRc != 0 ? STATUS_DONE | STERR : STATUS_DONE);
320}
321
322
323/**
324 * Interpret function prolog to find where to jmp back.
325 * @returns Length of prolog need to be copied - which is also the offset of
326 * where the jmp instr should be placed.
327 * On error it returns 0.
328 * @param p Pointer to prolog.
329 */
330static int interpretFunctionProlog(char *p)
331{
332 int length;
333 int rc;
334
335 /*
336 * check for the well known prolog (the only that is supported now)
337 * which is:
338 * push ebp
339 * mov ebp,esp
340 * or
341 * push ebp
342 * mov ecx, dword ptr [xxxxxxxx]
343 */
344
345 if (p[0] == 0x55 && p[1] == 0x8b)
346 {
347 if (p[2] == 0xec)
348 rc = 3;
349 else
350 rc = 1;
351 while (rc < 5)
352 {
353 /*
354 * This is not at all very stable or correct - but it works
355 * for the current functions.
356 * There will never be any doubt when something goes wrong!
357 */
358 switch(p[rc])
359 {
360 case 0x33: /* xor (ldrClose, ldrOpen) */
361 rc +=2;
362 break;
363 case 0x8b:
364 if (p[rc+1] == 0x0d)
365 rc += 6;
366 else
367 rc += 2; /*????!*/
368 break;
369 case 0x8d: /* lea (ldrRead) */
370 rc += 3;
371 break;
372 case 0x83: /* sub (LDRQAppType) */
373 rc += 3;
374 break;
375 default:
376 kprintf(("interpretFunctionProlog: unknown instruction 0x%x \n", p[rc]));
377 return 0;
378 }
379 }
380 }
381 else
382 rc = 0;
383
384 return rc;
385}
386
387
388
389/**
390 * Initiates the overrided functions.
391 * @returns NO_ERROR on success. !0 on error.
392 */
393static int procInit(void)
394{
395 int i;
396 int cb;
397
398 /* verify */
399 for (i = 0; i < NUMBER_OF_PROCS; i++)
400 {
401 cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress);
402 if (cb <= 0 || cb + 5 >= MAXSIZE_PROLOG)
403 {
404 kprintf(("rehookFunctions: verify failed for procedure no.%d, cb=%d\n", i, cb));
405 return 1;
406 }
407 }
408
409 /* rehook */
410 for (i = 0; i < NUMBER_OF_PROCS; i++)
411 {
412 cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress);
413 if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
414 {
415 char *pMy;
416 switch (i)
417 {
418 case iLDRREAD: pMy = (char*)myldrRead; break;
419 case iLDROPEN: pMy = (char*)myldrOpen; break;
420 case iLDRCLOSE: pMy = (char*)myldrClose; break;
421 case iLDRQAPPTYPE: pMy = (char*)myLDRQAppType; break;
422
423 default:
424 kprintf(("rehookFunctions: Someone has added function without updating the switch! i=%d\n", i));
425 Int3();
426 return 2;
427 }
428
429 /* copy function prolog */
430 memcpy(callTab[i], (void*)_aProcTab[i].ulAddress, (size_t)cb);
431
432 /* jump from calltab to original function */
433 callTab[i][cb] = 0xE9; /* jmp */
434 *(unsigned*)&callTab[i][cb+1] = _aProcTab[i].ulAddress + cb - (unsigned)&callTab[i][cb+5];
435
436 /* jump from original function to my function - an cli could be needed here */
437 *(char*)_aProcTab[i].ulAddress = 0xE9; /* jmp */
438 *(unsigned*)(_aProcTab[i].ulAddress + 1) = (unsigned)pMy - (_aProcTab[i].ulAddress + 5);
439 }
440 else
441 {
442 /* !fatal! - this could never happen really... */
443 kprintf(("rehookFunctions: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
444 Int3(); /* ipe - later! */
445 return 1;
446 }
447 }
448
449 return NO_ERROR;
450}
451
Note: See TracBrowser for help on using the repository browser.