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

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

Some bugsfixes - Yield is disabled.
Added parameters.
Correcte moduleheaders.
Introduced a new base class for virtual lx modules + some elf sketches.

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