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

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

g_tkExecPgm is overloaded, so we may change paramerters for a process later.

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