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

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

The interpretFunctionProlog didn't recognize the _ldrEnum32bitRelRecs function
on WS4eB.

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