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

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

Temporary backup checkin.

File size: 19.1 KB
Line 
1/* $Id: d32init.c,v 1.5 2000-01-22 18:20:57 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.cbHeapMax = ul;
132 else
133 options.cbHeap = 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.cbHeapMaxResident = ul;
192 else
193 options.cbHeapResident = 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.cbHeap > options.cbHeapMax)
246 options.cbHeapMax = options.cbHeap;
247 if (options.cbHeapResident > options.cbHeapMaxResident)
248 options.cbHeapMaxResident = options.cbHeapResident;
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.cbHeap) != NO_ERROR)
280 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
281
282 /* loader */
283 if (!options.fNoLoader)
284 if (ldrInit() != NO_ERROR)
285 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
286
287 /* functionoverrides */
288 if (!options.fNoLoader)
289 if (procInit() != NO_ERROR)
290 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
291
292 return STATUS_DONE;
293}
294
295
296/**
297 * Reads a number (unsigned long integer) for a string.
298 * @returns number read, ~0UL on error / no number read.
299 * @param pszNum Pointer to the string containing the number.
300 * @status competely implemented.
301 * @author knut st. osmundsen
302 */
303static ULONG readnum(const char *pszNum)
304{
305 ULONG ulRet = 0;
306 ULONG ulBase = 10;
307 int i = 0;
308
309 if (*pszNum == '0')
310 if (pszNum[1] == 'x' || pszNum[1] == 'X')
311 {
312 ulBase = 16;
313 pszNum += 2;
314 }
315 else
316 {
317 ulBase = 8;
318 i = 1;
319 }
320
321 /* read digits */
322 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
323 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
324 )
325 {
326 ulRet *= ulBase;
327 if (ulBase <= 10)
328 ulRet += pszNum[i] - '0';
329 else
330 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
331
332 i++;
333 }
334
335 return i > 0 ? ulRet : ~0UL;
336}
337
338
339/**
340 * Verifies the aProcTab.
341 * @returns 0 if ok. !0 if not ok.
342 * @remark Called from IOCtl.
343 */
344USHORT _loadds _Far32 _Pascal VerifyProcTab32(void)
345{
346 int i;
347 int cb;
348
349 /* verify */
350 for (i = 0; i < NUMBER_OF_PROCS; i++)
351 {
352 /* verify that it is found */
353 if (!_aProcTab[i].fFound)
354 {
355 kprintf(("VerifyProcTab32: procedure no.%d was not found!\n", i));
356 return STATUS_DONE | STERR | 1;
357 }
358
359 /* verify read/writeable. - FIXME */
360 if (_aProcTab[i].ulAddress < 0xffe00000UL)
361 {
362 kprintf(("VerifyProcTab32: procedure no.%d has an invlalid address, %#08x!\n",
363 i, _aProcTab[i].ulAddress));
364 return STATUS_DONE | STERR | 2;
365 }
366
367 switch (_aProcTab[i].fType)
368 {
369 case EPT_PROC:
370 case EPT_PROCIMPORT:
371 /* verify known function prolog. */
372 if ((cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress, _aProcTab[i].fType == EPT_PROC))
373 <= 0 && cb + 5 >= MAXSIZE_PROLOG)
374 {
375 kprintf(("VerifyProcTab32: verify failed for procedure no.%d\n",i));
376 return STATUS_DONE | STERR | 3;
377 }
378 break;
379
380 default:
381 kprintf(("VerifyProcTab32: only EPT_PROC is implemented\n",i));
382 return STATUS_DONE | STERR | 4;
383 }
384 }
385
386 return STATUS_DONE;
387}
388
389
390/**
391 * Get kernel OTEs
392 * @returns Strategy return code:
393 * STATUS_DONE on success.
394 * STATUS_DONE | STERR | errorcode on failure.
395 * @param pOTEBuf Pointer to output buffer.
396 * @status completely implemented and tested.
397 * @author knut st. osmundsen
398 * @remark Called from IOCtl.
399 */
400USHORT _loadds _Far32 _Pascal GetOTEs32(PKRNLOBJTABLE pOTEBuf)
401{
402 PMTE pMTE;
403 PSMTE pSMTE;
404 POTE pOTE;
405 int i;
406 USHORT usRc;
407
408 pMTE = GetOS2KrnlMTE();
409 if (pMTE != NULL)
410 {
411 pSMTE = pMTE->mte_swapmte;
412 if (pSMTE != NULL)
413 {
414 pOTEBuf->cObjects = (unsigned char)pSMTE->smte_objcnt;
415 if (pSMTE->smte_objcnt <= MAXKRNLOBJECTS)
416 {
417 pOTE = pSMTE->smte_objtab;
418 if (pOTE != NULL)
419 {
420 for (i = 0; i < pOTEBuf->cObjects; i++)
421 memcpy((void*)&pOTEBuf->aObjects[i], &pOTE[i], sizeof(OTE));
422 usRc = 0;
423 }
424 else
425 usRc = 4;
426 }
427 else
428 usRc = 3;
429 }
430 else
431 usRc = 2;
432 }
433 else
434 usRc = 1;
435
436 if (usRc != 0)
437 kprintf(("GetOTEs32: failed. usRc = %d\n", usRc));
438
439 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
440}
441
442
443/**
444 * Interpret function prolog to find where to jmp back.
445 * @returns Length of prolog need to be copied - which is also the offset of
446 * where the jmp instr should be placed.
447 * On error it returns 0.
448 * @param pach Pointer to prolog.
449 * @param fOverload TRUE: Function is to be overloaded.
450 * FALSE: Function is to be imported.
451 */
452static int interpretFunctionProlog(char *pach, BOOL fOverload)
453{
454 int rc;
455
456 /*
457 * check for the well known prolog (the only that is supported now)
458 * which is:
459 * push ebp
460 * mov ebp,esp
461 * or
462 * push ebp
463 * mov ecx, dword ptr [xxxxxxxx]
464 */
465
466 if (pach[0] == 0x55 && pach[1] == 0x8b)
467 {
468 if (pach[2] == 0xec)
469 rc = 3;
470 else
471 rc = 1;
472 while (rc < 5)
473 {
474 /*
475 * This is not at all very stable or correct - but it works
476 * for the current functions.
477 * There will never be any doubt when something goes wrong!
478 */
479 switch(pach[rc])
480 {
481 case 0x33: /* xor (ldrClose, ldrOpen) */
482 rc +=2;
483 break;
484 case 0x8b:
485 if (pach[rc+1] == 0x0d)
486 rc += 6;
487 else
488 rc += 2; /*????!*/
489 break;
490 case 0x8d: /* lea (ldrRead) */
491 rc += 3;
492 break;
493 case 0x83: /* sub (LDRQAppType) */
494 rc += 3;
495 break;
496 default:
497 kprintf(("interpretFunctionProlog: unknown instruction 0x%x\n", pach[rc]));
498 return 0;
499 }
500 }
501 }
502 else
503 {
504 /* special case for IOSftReadAt and IOSftWriteAt */
505 if (fOverload == FALSE && pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55))
506 rc = 5;
507 else
508 rc = 0;
509 }
510
511 return rc;
512}
513
514
515
516/**
517 * Initiates the overrided functions.
518 * @returns NO_ERROR on success. !0 on error.
519 */
520static int procInit(void)
521{
522 int i;
523 int cb;
524
525 /*
526 * verify proctable
527 */
528 for (i = 0; i < NUMBER_OF_PROCS; i++)
529 {
530 if (_aProcTab[i].fType != EPT_PROC && _aProcTab[i].fType != EPT_PROCIMPORT)
531 {
532 kprintf(("procInit: EPT_VAR is not supported. (procedure no.%d, cb=%d)\n", i, cb));
533 return 1;
534 }
535 cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress, _aProcTab[i].fType == EPT_PROC);
536 if (cb <= 0 || cb + 5 >= MAXSIZE_PROLOG)
537 {
538 kprintf(("procInit: verify failed for procedure no.%d, cb=%d\n", i, cb));
539 return 1;
540 }
541 }
542
543 /*
544 * rehook / import
545 */
546 for (i = 0; i < NUMBER_OF_PROCS; i++)
547 {
548 switch (_aProcTab[i].fType)
549 {
550 case EPT_PROC:
551 {
552 cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress, TRUE);
553 if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
554 {
555 static unsigned auFuncs[NUMBER_OF_PROCS] = /* This table must be updated with the overloading functions. */
556 {
557 (unsigned)myldrRead,
558 (unsigned)myldrOpen,
559 (unsigned)myldrClose,
560 (unsigned)myLDRQAppType,
561 (unsigned)myldrEnum32bitRelRecs,
562 0,
563 0,
564 0,
565 0,
566 0,
567 };
568
569 /* copy function prolog */
570 memcpy(callTab[i], (void*)_aProcTab[i].ulAddress, (size_t)cb);
571
572 /* jump from calltab to original function */
573 callTab[i][cb] = 0xE9; /* jmp */
574 *(unsigned*)(void*)&callTab[i][cb+1] = _aProcTab[i].ulAddress + cb - (unsigned)&callTab[i][cb+5];
575
576
577 /* jump from original function to my function - an cli(?) could be needed here */
578 *(char*)_aProcTab[i].ulAddress = 0xE9; /* jmp */
579 *(unsigned*)(_aProcTab[i].ulAddress + 1) = auFuncs[i] - (_aProcTab[i].ulAddress + 5);
580 }
581 else
582 { /* !fatal! - this could never happen really... */
583 kprintf(("procInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
584 Int3(); /* ipe - later! */
585 return 1;
586 }
587 break;
588 }
589
590 case EPT_PROCIMPORT:
591 {
592 cb = interpretFunctionProlog((char*)_aProcTab[i].ulAddress, FALSE);
593 if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
594 {
595 /* jump from calltab to original function */
596 callTab[i][0] = 0xE9; /* jmp */
597 *(unsigned*)(void*)&callTab[i][1] = _aProcTab[i].ulAddress - (unsigned)&callTab[i][cb+5];
598 }
599 else
600 { /* !fatal! - this could never happen really... */
601 kprintf(("procInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
602 Int3(); /* ipe - later! */
603 return 1;
604 }
605 break;
606 }
607
608 default:
609 kprintf(("procInit: EPT_VAR is not supported. (procedure no.%d, cb=%d)\n", i, cb));
610 Int3(); /* ipe - later! */
611 return 1;
612 } /* switch - type */
613 } /* for */
614
615 return NO_ERROR;
616}
617
Note: See TracBrowser for help on using the repository browser.