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

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

ProbKrnl and code for importing krnl symbols has been enhanched.
Now we'll lock 32-bit segments into memory too.
And some other fixes...

File size: 39.0 KB
Line 
1/* $Id: d32init.c,v 1.13 2000-02-21 04:45:46 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 0x18 /* Note that this must be synced with */
15 /* the one used in calltab.asm. */
16#define static /* just to make all symbols visible in the kernel debugger. */
17
18
19#define INCL_DOSERRORS
20#define INCL_NOPMAPI
21#define LDR_INCL_INITONLY
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 "dev32hlp.h"
35#include "probkrnl.h"
36#include "log.h"
37#include "asmutils.h"
38#include "malloc.h"
39#include "ldr.h"
40#include "ldrCalls.h"
41#include "macros.h"
42
43/*******************************************************************************
44* Global Variables *
45*******************************************************************************/
46#ifdef DEBUG
47static char * apszPE[] = {"FLAGS_PE_NOT", "FLAGS_PE_PE2LX", "FLAGS_PE_PE", "FLAGS_PE_MIXED", "!invalid!"};
48static char * apszInfoLevel[] = {"INFOLEVEL_QUIET", "INFOLEVEL_ERROR", "INFOLEVEL_WARNING", "INFOLEVEL_INFO", "INFOLEVEL_INFOALL", "!invalid!"};
49#endif
50
51/*******************************************************************************
52* Internal Functions *
53*******************************************************************************/
54static ULONG readnum(const char *pszNum);
55_Inline int ModR_M_32bit(char bModRM);
56static int interpretFunctionProlog32(char *pach, BOOL fOverload);
57static int interpretFunctionProlog16(char *pach, BOOL fOverload);
58static int ImportTabInit(void);
59
60
61/* externs located in 16-bit data segement in ProbKrnl.c */
62extern ULONG _TKSSBase16;
63extern USHORT _R0FlatCS16;
64extern USHORT _R0FlatDS16;
65
66/* extern(s) located in calltab.asm */
67extern char callTab[NBR_OF_KRNLIMPORTS][MAXSIZE_PROLOG];
68
69/* extern(s) located in mytkExecPgm.asm */
70extern char mytkExecPgm;
71extern char CODE32START;
72extern char CODE32END;
73extern char CONST32_ROEND;
74extern char DATA16START;
75extern char DATA16_CONSTEND;
76
77
78/**
79 * Ring-0, 32-bit, init function.
80 * @returns Status word.
81 * @param pRpInit Pointer init request packet.
82 * @sketch Set TKSSBase32.
83 * Set default parameters.
84 * Parse command line options.
85 * Show (kprint) configuration.
86 * Init heap.
87 * Init ldr.
88 * Init procs. (overloaded ldr procedures)
89 * @status completely implemented.
90 * @author knut st. osmundsen
91 */
92USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
93{
94 char *pszTmp2;
95 char *pszTmp;
96 ULONG ul;
97 APIRET rc;
98 LOCKHANDLE lhData16={0,0,0,0, 0,0,0,0, 0,0,0,0};
99 LOCKHANDLE lhData = {0,0,0,0, 0,0,0,0, 0,0,0,0};
100 LOCKHANDLE lhCode = {0,0,0,0, 0,0,0,0, 0,0,0,0};
101
102 pulTKSSBase32 = (PULONG)_TKSSBase16;
103
104 SET_OPTIONS_TO_DEFAULT(options);
105
106 /*---------------------*/
107 /* commandline options */
108 /*---------------------*/
109 kprintf(("Options start\n"));
110 pszTmp = strpbrk(pRpInit->InitArgs, "-/");
111 while (pszTmp != NULL)
112 {
113 int cch;
114 pszTmp++; //skip [-/]
115 cch = strlen(pszTmp);
116 switch (*pszTmp)
117 {
118 case 'c':
119 case 'C': /* -C[1|2] - com-port no, def:-C2 */
120 switch (pszTmp[1])
121 {
122 case '1':
123 options.usCom = OUTPUT_COM1;
124 break;
125
126 case '2':
127 default:
128 options.usCom = OUTPUT_COM2;
129 }
130 break;
131
132 case 'e':
133 case 'E':/* ELF */
134 pszTmp2 = strpbrk(pszTmp, ":=/- ");
135 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
136 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
137 )
138 options.fElf = FALSE;
139 else
140 options.fElf = TRUE;
141 break;
142
143 case 'h':
144 case 'H': /* Heap options */
145 pszTmp2 = strpbrk(pszTmp, ":=/- ");
146 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
147 && (*pszTmp2 == ':' || *pszTmp2 == '='))
148 {
149 ul = readnum(pszTmp2 + 1);
150 if (ul > 0x1000UL && ul < 0x2000000UL) /* 4KB < ul < 32MB */
151 {
152 if (strnicmp(pszTmp, "heapm", 5) == 0)
153 options.cbSwpHeapMax = ul;
154 else
155 options.cbSwpHeapInit = ul;
156 }
157 }
158 break;
159
160 case 'l':
161 case 'L': /* -L[..]<:|=| >[<Y..|E..| > | <N..|D..>] */
162 pszTmp2 = strpbrk(pszTmp, ":=/- ");
163 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
164 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
165 )
166 options.fLogging = FALSE;
167 else
168 options.fLogging = TRUE;
169 break;
170
171 case 'n':
172 case 'N': /* NoLoader */
173 options.fNoLoader = TRUE;
174 break;
175
176 case 'p':
177 case 'P': /* PE */
178 pszTmp2 = strpbrk(pszTmp, ":=/- ");
179 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
180 && (*pszTmp2 == ':' || *pszTmp2 == '='))
181 {
182 pszTmp++;
183 if (strnicmp(pszTmp, "pe2lx", 5) == 0)
184 options.fPE = FLAGS_PE_PE2LX;
185 else if (strnicmp(pszTmp, "pe", 2) == 0)
186 options.fPE = FLAGS_PE_PE;
187 else if (strnicmp(pszTmp, "mixed", 2) == 0)
188 options.fPE = FLAGS_PE_MIXED;
189 else if (strnicmp(pszTmp, "not", 2) == 0)
190 options.fPE = FLAGS_PE_NOT;
191 else
192 kprintf(("R0Init32: invalid parameter -PE:...\n"));
193 }
194 else
195 kprintf(("R0Init32: invalid parameter -PE...\n"));
196 break;
197
198 case 'q':
199 case 'Q': /* quiet initialization */
200 options.fQuiet = TRUE;
201 break;
202
203 case 'r':
204 case 'R': /* ResHeap options */
205 pszTmp2 = strpbrk(pszTmp, ":=/- ");
206 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
207 && (*pszTmp2 == ':' || *pszTmp2 == '='))
208 {
209 ul = readnum(pszTmp2 + 1);
210 if (ul > 0x1000UL && ul < 0x700000UL) /* 4KB < ul < 7MB */
211 {
212 if (strnicmp(pszTmp, "resheapm", 8) == 0)
213 options.cbResHeapMax = ul;
214 else
215 options.cbResHeapInit = ul;
216 }
217 }
218 break;
219
220 case 's':
221 case 'S': /* Sym:<filename> or Script:<Yes|No> or Smp */
222 /* SMP kernel */
223 if (pszTmp[1] == 'm' || pszTmp[1] == 'M')
224 options.fKernel = KF_SMP;
225 else
226 {
227 if (pszTmp[1] == 'c' || pszTmp[1] == 'C')
228 {
229 pszTmp2 = strpbrk(pszTmp, ":=/- ");
230 options.fScript = pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
231 && (*pszTmp2 == ':' || *pszTmp2 == '=')
232 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
233 }
234 }
235 break;
236
237 case 'u':
238 case 'U': /* UNI kernel */
239 options.fKernel = KF_UNI;
240 break;
241
242 case 'v':
243 case 'V': /* verbose initialization */
244 options.fQuiet = FALSE;
245 break;
246
247 case 'w':
248 case 'W':
249 if (pszTmp[1] >= '0' && pszTmp[1] <= '4')
250 options.ulInfoLevel = pszTmp[1] - '0';
251 else
252 {
253 pszTmp2 = strpbrk(pszTmp, ":=/- ");
254 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
255 && (*pszTmp2 == ':' || *pszTmp2 == '=')
256 && pszTmp2[1] >= '0' && pszTmp2[1] <= '4'
257 )
258 options.ulInfoLevel = pszTmp2[1] - '0';
259 }
260 break;
261
262 }
263 pszTmp = strpbrk(pszTmp, "-/");
264 }
265
266 /* heap min/max corrections */
267 if (options.cbSwpHeapInit > options.cbSwpHeapMax)
268 options.cbSwpHeapMax = options.cbSwpHeapInit;
269 if (options.cbResHeapInit > options.cbResHeapMax)
270 options.cbResHeapMax = options.cbResHeapInit;
271
272 /* Transfer version and build number from 16-bit probkrnl.c */
273 options.ulBuild = _ulBuild;
274 options.usVerMajor = _usVerMajor;
275 options.usVerMinor = _usVerMinor;
276
277 /* log option summary - FIXME */
278 kprintf(("Options - Summary - Start\n"));
279 if (options.fQuiet)
280 kprintf(("\tQuiet init\n"));
281 else
282 kprintf(("\tVerbose init\n"));
283
284 if (options.fLogging)
285 kprintf(("\tlogging enabled\n"));
286 else
287 kprintf(("\tlogging disabled\n"));
288 kprintf(("\tCom port no.%d\n", options.usCom));
289
290 kprintf(("\tKernel: ver%d.%d build %d type %s\n",
291 options.usVerMajor,
292 options.usVerMinor,
293 options.ulBuild,
294 (options.fKernel & KF_SMP) ? "SMP" : "UNI"
295 ));
296 kprintf(("\tfPE=%d (%s)\n", options.fPE, apszPE[MIN(options.fPE, 5)]));
297 kprintf(("\tulInfoLevel=%d (%s)\n", options.ulInfoLevel, apszInfoLevel[MIN(options.ulInfoLevel, 5)]));
298 kprintf(("\tfElf=%d\n", options.fElf));
299 kprintf(("\tfScript=%d\n", options.fScript));
300 kprintf(("\tfNoLoader=%d\n", options.fNoLoader));
301 kprintf(("\tcbSwpHeapInit=0x%08x cbSwpHeapMax=0x%08x\n",
302 options.cbSwpHeapInit, options.cbSwpHeapMax));
303 kprintf(("\tcbResHeapInit=0x%08x cbResHeapMax=0x%08x\n",
304 options.cbSwpHeapInit, options.cbSwpHeapMax));
305 kprintf(("Options - Summary - End\n"));
306 /* end option summary */
307
308
309 /*
310 * init sub-parts
311 */
312 /* heap */
313 if (heapInit(options.cbResHeapInit, options.cbResHeapMax,
314 options.cbSwpHeapInit, options.cbSwpHeapMax) != NO_ERROR)
315 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
316
317 /* loader */
318 if (!options.fNoLoader)
319 if (ldrInit() != NO_ERROR)
320 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
321
322 /* functionoverrides */
323 if (!options.fNoLoader)
324 if (ImportTabInit() != NO_ERROR)
325 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
326
327 /*
328 * Lock the 32-bit objects/segments and 16-bit datasegment in memory
329 */
330 /* 32-bit code segment */
331 rc = D32Hlp_VMLock2(&CODE32START,
332 ((unsigned)&CODE32END & ~0xFFF) - (unsigned)&CODE32START, /* Round down so we don't overlap with the next request. */
333 VMDHL_LONG,
334 SSToDS(&lhCode));
335 if (rc != NO_ERROR)
336 kprintf(("code segment lock failed with with rc=%d\n", rc));
337
338 /* 32-bit data segment */
339 rc = D32Hlp_VMLock2(callTab,
340 &CONST32_ROEND - (char*)callTab,
341 VMDHL_LONG | VMDHL_WRITE,
342 SSToDS(&lhData));
343 if (rc != NO_ERROR)
344 kprintf(("data segment lock failed with with rc=%d\n", rc));
345
346 /* 16-bit data segment */
347 rc = D32Hlp_VMLock2(&DATA16START,
348 &DATA16_CONSTEND - &DATA16START,
349 VMDHL_LONG | VMDHL_WRITE,
350 SSToDS(&lhData16));
351 if (rc != NO_ERROR)
352 kprintf(("data segment lock failed with with rc=%d\n", rc));
353
354 return STATUS_DONE;
355}
356
357
358/**
359 * Reads a number (unsigned long integer) for a string.
360 * @returns number read, ~0UL on error / no number read.
361 * @param pszNum Pointer to the string containing the number.
362 * @status competely implemented.
363 * @author knut st. osmundsen
364 */
365static ULONG readnum(const char *pszNum)
366{
367 ULONG ulRet = 0;
368 ULONG ulBase = 10;
369 int i = 0;
370
371 if (*pszNum == '0')
372 if (pszNum[1] == 'x' || pszNum[1] == 'X')
373 {
374 ulBase = 16;
375 pszNum += 2;
376 }
377 else
378 {
379 ulBase = 8;
380 i = 1;
381 }
382
383 /* read digits */
384 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
385 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
386 )
387 {
388 ulRet *= ulBase;
389 if (ulBase <= 10)
390 ulRet += pszNum[i] - '0';
391 else
392 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
393
394 i++;
395 }
396
397 return i > 0 ? ulRet : ~0UL;
398}
399
400
401/**
402 * Get kernel OTEs
403 * @returns Strategy return code:
404 * STATUS_DONE on success.
405 * STATUS_DONE | STERR | errorcode on failure.
406 * @param pOTEBuf Pointer to output buffer.
407 * @status completely implemented and tested.
408 * @author knut st. osmundsen
409 * @remark Called from IOCtl.
410 */
411USHORT _loadds _Far32 _Pascal GetOTEs32(PKRNLOBJTABLE pOTEBuf)
412{
413 PMTE pMTE;
414 PSMTE pSMTE;
415 POTE pOTE;
416 int i;
417 USHORT usRc;
418
419 pMTE = GetOS2KrnlMTE();
420 if (pMTE != NULL)
421 {
422 pSMTE = pMTE->mte_swapmte;
423 if (pSMTE != NULL)
424 {
425 pOTEBuf->cObjects = (unsigned char)pSMTE->smte_objcnt;
426 if (pSMTE->smte_objcnt <= MAXKRNLOBJECTS)
427 {
428 pOTE = pSMTE->smte_objtab;
429 if (pOTE != NULL)
430 {
431 for (i = 0; i < pOTEBuf->cObjects; i++)
432 memcpy((void*)&pOTEBuf->aObjects[i], &pOTE[i], sizeof(OTE));
433 usRc = 0;
434 }
435 else
436 usRc = 4;
437 }
438 else
439 usRc = 3;
440 }
441 else
442 usRc = 2;
443 }
444 else
445 usRc = 1;
446
447 if (usRc != 0)
448 kprintf(("GetOTEs32: failed. usRc = %d\n", usRc));
449
450 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
451}
452
453
454
455/**
456 * Functions which cacluates the instructionsize given a ModR/M byte.
457 * @returns Number of bytes to add to cb and pach.
458 * @param bModRM ModR/M byte.
459 * @status completely implemented.
460 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
461 */
462_Inline int ModR_M_32bit(char bModRM)
463{
464 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
465 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
466 { /* 32-bit displacement */
467 return 5;
468 }
469 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
470 { /* 8-bit displacement */
471 return 2;
472 }
473 /* no displacement (only /r byte) */
474 return 1;
475}
476
477
478
479
480
481/**
482 * 32-bit! Interpret function prolog to find where to jmp back.
483 * @returns Length of prolog need to be copied - which is also the offset of
484 * where the jmp instr should be placed.
485 * On error it returns 0.
486 * @param pach Pointer to prolog.
487 * @param fOverload TRUE: Function is to be overloaded.
488 * FALSE: Function is to be imported.
489 */
490static int interpretFunctionProlog32(char *pach, BOOL fOverload)
491{
492 int cb = -3;
493
494 kprintf(("interpretFunctionProlog32(0x%08x, %d):\n"
495 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
496 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
497 pach, fOverload,
498 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
499 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
500
501 /*
502 * check for the well known prolog (the only that is supported now)
503 * which is:
504 * push ebp
505 * mov ebp,esp
506 * or
507 * push ebp
508 * mov ecx, dword ptr [xxxxxxxx]
509 *
510 * These are allowed when not overloading:
511 * mov eax, imm32
512 * jmp short
513 * or
514 * mov eax, imm32
515 * push ebp
516 */
517 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* two first prologs */
518 ||
519 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55) && !fOverload) /* two last prologs */
520 )
521 {
522 BOOL fForce;
523 cb = 0;
524 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
525 {
526 int cb2;
527 fForce = FALSE;
528 switch (*pach)
529 {
530 /* simple one byte prefixes */
531 case 0x2e: /* cs segment override */
532 case 0x36: /* ss segment override */
533 case 0x3e: /* ds segment override */
534 case 0x26: /* es segment override */
535 case 0x64: /* fs segment override */
536 case 0x65: /* gs segment override */
537 fForce = TRUE;
538 break;
539
540 /* simple one byte instructions */
541 case 0x50: /* push ax */
542 case 0x51: /* push cx */
543 case 0x52: /* push dx */
544 case 0x53: /* push bx */
545 case 0x54: /* push sp */
546 case 0x55: /* push bp */
547 case 0x56: /* push si */
548 case 0x57: /* push di */
549 break;
550
551 /* simple two byte instructions */
552 case 0xb0: /* mov al, imm8 */
553 case 0xb1: /* mov cl, imm8 */
554 case 0xb2: /* mov dl, imm8 */
555 case 0xb3: /* mov bl, imm8 */
556 case 0xb4: /* mov ah, imm8 */
557 case 0xb5: /* mov ch, imm8 */
558 case 0xb6: /* mov dh, imm8 */
559 case 0xb7: /* mov bh, imm8 */
560 case 0x2c: /* sub al, imm8 */
561 case 0x34: /* xor al, imm8 */
562 case 0x3c: /* cmp al, imm8 */
563 case 0x6a: /* push <byte> */
564 pach++;
565 cb++;
566 break;
567
568 /* simple five byte instructions */
569 case 0xb8: /* mov eax, imm32 */
570 case 0xb9: /* mov ecx, imm32 */
571 case 0xba: /* mov edx, imm32 */
572 case 0xbb: /* mov ebx, imm32 */
573 case 0xbc: /* mov esx, imm32 */
574 case 0xbd: /* mov ebx, imm32 */
575 case 0xbe: /* mov esi, imm32 */
576 case 0xbf: /* mov edi, imm32 */
577 case 0x2d: /* sub eax, imm32 */
578 case 0x35: /* xor eax, imm32 */
579 case 0x3d: /* cmp eax, imm32 */
580 case 0x68: /* push <dword> */
581 pach += 4;
582 cb += 4;
583 break;
584
585 /* complex sized instructions - "/r" */
586 case 0x30: /* xor r/m8, r8 */
587 case 0x31: /* xor r/m32, r32 */
588 case 0x32: /* xor r8, r/m8 */
589 case 0x33: /* xor r32, r/m32 */
590 case 0x38: /* cmp r/m8, r8 */
591 case 0x39: /* cmp r/m32, r32 */
592 case 0x3a: /* cmp r8, r/m8 */
593 case 0x3b: /* cmp r32, r/m32 */
594 case 0x28: /* sub r/m8, r8 */
595 case 0x29: /* sub r/m32, r32 */
596 case 0x2a: /* sub r8, r/m8 */
597 case 0x2b: /* sub r32, r/m32 */
598 case 0x8b: /* mov /r */
599 case 0x8d: /* lea /r */
600 if ((pach[1] & 0x7) == 4 && (pach[1] & 0xc0) != 0xc0) /* invalid instruction!?! */
601 return -1;
602 cb += cb2 = ModR_M_32bit(pach[1]);
603 pach += cb2;
604 break;
605
606 /* complex sized instruction - "/5 ib" */
607 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
608 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
609 if ((pach[1] & 0x38) == (5<<3)
610 || (pach[1] & 0x38) == (7<<3)
611 )
612 {
613 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
614 pach += cb2;
615 }
616 else
617 {
618 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
619 return -3;
620 }
621 break;
622
623 /* complex sized instruction - "/digit id" */
624 case 0x81: /* sub r/m32, imm32 + more instructions! */
625 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
626 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
627 )
628 {
629 cb += cb2 = 4 + ModR_M_32bit(pach[1]); /* 4 is the size of the imm32 */
630 pach += cb2;
631 }
632 else
633 {
634 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
635 return -2;
636 }
637 break;
638
639 default:
640 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
641 return 0;
642 }
643 pach++;
644 cb++;
645 }
646 }
647 else
648 {
649 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
650 cb = 0;
651 }
652 return cb;
653}
654
655
656/**
657 * 16-bit! Interpret function prolog to find where to jmp back.
658 * @returns Length of prolog need to be copied - which is also the offset of
659 * where the jmp instr should be placed.
660 * On error it returns 0.
661 * @param pach Pointer to prolog.
662 * @param fOverload TRUE: Function is to be overloaded.
663 * FALSE: Function is to be imported.
664 */
665static int interpretFunctionProlog16(char *pach, BOOL fOverload)
666{
667 int cb = -7;
668
669 kprintf(("interpretFunctionProlog16(0x%08x, %d):\n"
670 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
671 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
672 pach, fOverload,
673 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
674 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
675 /*
676 * Check for the well known prolog (the only that is supported now)
677 * which is:
678 * push 2
679 */
680 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
681 {
682 BOOL fForce;
683 cb = 0;
684 while (cb < 8 || fForce) /* 8 is the size of a 66h prefixed far jump instruction. */
685 {
686 fForce = FALSE;
687 switch (*pach)
688 {
689 case 0x50: /* push ax */
690 case 0x51: /* push cx */
691 case 0x52: /* push dx */
692 case 0x53: /* push bx */
693 case 0x54: /* push sp */
694 case 0x55: /* push bp */
695 case 0x56: /* push si */
696 case 0x57: /* push di */
697 break;
698
699 case 0x2e: /* cs segment override */
700 case 0x36: /* ss segment override */
701 case 0x3e: /* ds segment override */
702 case 0x26: /* es segment override */
703 case 0x64: /* fs segment override */
704 case 0x65: /* gs segment override */
705 fForce = TRUE;
706 break;
707
708 case 0x6a: /* push <byte> */
709 pach++;
710 cb++;
711 break;
712
713 case 0x68: /* push <word> */
714 pach += 2;
715 cb += 2;
716 break;
717
718 case 0x8b: /* mov /r */
719 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
720 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
721 { /* 16-bit displacement */
722 pach += 3;
723 cb += 3;
724 }
725 else
726 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
727 { /* 8-bit displacement */
728 pach += 2;
729 cb += 2;
730 }
731 else
732 { /* no displacement (only /r byte) */
733 pach++;
734 cb++;
735 }
736 break;
737
738 default:
739 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
740 return 0;
741 }
742 pach++;
743 cb++;
744 }
745 }
746
747 fOverload = fOverload;
748 return cb;
749}
750
751
752
753/**
754 * Verifies the aImportTab.
755 * @returns 0 if ok. !0 if not ok.
756 * @remark Called from IOCtl.
757 * WARNING! VerifyImporTab32 is called before the initroutine!
758 */
759USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
760{
761 int i;
762 int cb;
763 int cbmin;
764
765 /* VerifyImporTab32 is called before the initroutine! */
766 pulTKSSBase32 = (PULONG)_TKSSBase16;
767
768 /* verify */
769 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
770 {
771 /* verify that it is found */
772 if (!_aImportTab[i].fFound)
773 {
774 kprintf(("VerifyImportTab32: procedure no.%d was not found!\n", i));
775 return STATUS_DONE | STERR | 1;
776 }
777
778 /* verify read/writeable. - FIXME */
779 if (_aImportTab[i].ulAddress < 0xffe00000UL)
780 {
781 kprintf(("VerifyImportTab32: procedure no.%d has an invlalid address, %#08x!\n",
782 i, _aImportTab[i].ulAddress));
783 return STATUS_DONE | STERR | 2;
784 }
785
786 switch (_aImportTab[i].fType & ~EPT_BIT_MASK)
787 {
788 case EPT_PROC:
789 case EPT_PROCIMPORT:
790 /*
791 * Verify known function prolog.
792 */
793 if (EPT32BitEntry(_aImportTab[i]))
794 {
795 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
796 cbmin = 5; /* Size of the jump instruction */
797 }
798 else
799 {
800 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
801 cbmin = 7; /* Size of the far jump instruction */
802 }
803
804 /*
805 * Check result of the function prolog interpretations.
806 */
807 if (cb <= 0 && cb + cbmin >= MAXSIZE_PROLOG)
808 { /* failed, too small or too large. */
809 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cd=%d)\n", i, cb));
810 return STATUS_DONE | STERR | 3;
811 }
812 break;
813
814 case EPT_VARIMPORT:
815 /* do nothing! */
816 break;
817
818 default:
819 kprintf(("VerifyImportTab32: only EPT_PROC is implemented\n",i));
820 Int3(); /* temporary fix! */
821 return STATUS_DONE | STERR | 4;
822 }
823 }
824
825 return STATUS_DONE;
826}
827
828
829/**
830 * Initiates the overrided functions.
831 * @returns NO_ERROR on success. !0 on error.
832 */
833static int importTabInit(void)
834{
835 /* This table must be updated with the overloading functions. */
836 static unsigned auFuncs[NBR_OF_KRNLIMPORTS] =
837 {
838 (unsigned)myldrRead,
839 (unsigned)myldrOpen,
840 (unsigned)myldrClose,
841 0,//(unsigned)myLDRQAppType,
842 (unsigned)myldrEnum32bitRelRecs,
843 0,
844 0,
845 0,
846 0,
847 0,
848 0,
849 0,
850 0,
851 (unsigned)&mytkExecPgm,
852 0,
853 0
854 };
855
856 int i;
857 int cb;
858 int cbmin;
859
860 /*
861 * verify proctable
862 */
863 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
864 {
865 /* EPT_VARIMPORTs are skipped */
866 if ((_aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
867 continue;
868
869 if (EPT32BitEntry(_aImportTab[i]))
870 {
871 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
872 cbmin = 5; /* Size of the jump instruction */
873 }
874 else
875 {
876 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
877 cbmin = 7; /* Size of the far jump instruction */
878 }
879 if (cb <= 0 || cb + cbmin >= MAXSIZE_PROLOG)
880 {
881 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
882 return 1;
883 }
884 }
885
886 /*
887 * rehook / import
888 */
889 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
890 {
891 switch (_aImportTab[i].fType)
892 {
893 /*
894 * 32-bit procedure overload.
895 * The overloading procedure is found in the auFuncs table (at the same index
896 * as the overloaded procedure has in aImportTab).
897 * The overloaded procedure is called by issuing a call to the callTab entry.
898 */
899 case EPT_PROC32:
900 {
901 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, TRUE);
902 _aImportTab[i].cbProlog = (char)cb;
903 if (cb >= 5 && cb + 5 < MAXSIZE_PROLOG) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
904 { /* 5(2nd): size of jump instruction which jumps back to the original function after executing the prolog copied to the callTab entry for this function. */
905 /*
906 * Copy function prolog which will be overwritten by the jmp to calltabl.
907 */
908 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
909
910 /*
911 * Make jump instruction which jumps from calltab to original function.
912 * 0xE9 <four bytes displacement>
913 * Note: the displacement is relative to the next instruction
914 */
915 callTab[i][cb] = 0xE9; /* jmp */
916 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
917
918 /*
919 * Jump from original function to my function - an cli(?) could be needed here
920 */
921 *(char*)_aImportTab[i].ulAddress = 0xE9; /* jmp */
922 *(unsigned long*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
923 }
924 else
925 { /* !fatal! - this could never happen really... */
926 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
927 Int3(); /* ipe - later! */
928 return 1;
929 }
930 break;
931 }
932
933
934 /*
935 * 16-bit procedure overload.
936 * Currently disabled due to expected problems when calltab is a 32-bit segment.
937 */
938 case EPT_PROC16:
939 {
940 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
941 Int3();
942
943 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, TRUE);
944 _aImportTab[i].cbProlog = (char)cb;
945 if (cb >= 8 && cb + 7 < MAXSIZE_PROLOG) /* 8: size of a 16:32 jump which jumps to my overloading function (prefixed with 66h in a 16-bit segment) */
946 { /* 7: size of a 16:32 jump which is added to the call tab */
947 /*
948 * Copy function prolog which is to be overwritten.
949 */
950 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
951
952 /*
953 * Create far jump from calltab to original function.
954 * 0xEA <four byte target address> <two byte target selector>
955 */
956 callTab[i][cb] = 0xEA; /* jmp far ptr */
957 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].offObject;
958 *(unsigned short*)(void*)&callTab[i][cb+5] = _aImportTab[i].usSel;
959
960 /*
961 * jump from original function to my function - an cli(?) could be needed here
962 * 0x66 0xEA <four byte target address> <two byte target selector>
963 */
964 *(char*)(_aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
965 *(char*)(_aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
966 *(unsigned long*)(_aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
967 *(unsigned short*)(_aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
968 }
969 else
970 { /* !fatal! - this could never happen really... */
971 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
972 Int3(); /* ipe - later! */
973 return 1;
974 }
975 break;
976 }
977
978
979 /*
980 * 32-bit imported procedure
981 * This is called by issuing a near call to the callTab entry.
982 */
983 case EPT_PROCIMPORT32:
984 {
985 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, FALSE);
986 _aImportTab[i].cbProlog = (char)cb;
987 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
988 {
989 /*
990 * Make jump instruction which jumps from calltab to original function.
991 * 0xE9 <four bytes displacement>
992 * Note: the displacement is relative to the next instruction
993 */
994 callTab[i][0] = 0xE9; /* jmp */
995 *(unsigned*)(void*)&callTab[i][1] = _aImportTab[i].ulAddress - (unsigned)&callTab[i][cb+5];
996 }
997 else
998 { /* !fatal! - this should never really happen... */
999 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1000 Int3(); /* ipe - later! */
1001 return 1;
1002 }
1003 break;
1004 }
1005
1006
1007 /*
1008 * 16-bit imported procedure.
1009 * This is called by issuing a far call to the calltab entry.
1010 */
1011 case EPT_PROCIMPORT16:
1012 {
1013 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, FALSE);
1014 _aImportTab[i].cbProlog = (char)cb;
1015 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1016 {
1017 /*
1018 * Create far jump from calltab to original function.
1019 * 0xEA <four byte target address> <two byte target selector>
1020 */
1021 callTab[i][0] = 0xEA; /* jmp far ptr */
1022 *(unsigned long*)(void*)&callTab[i][1] = _aImportTab[i].offObject;
1023 *(unsigned short*)(void*)&callTab[i][5] = _aImportTab[i].usSel;
1024 }
1025 else
1026 { /* !fatal! - this should never really happen... */
1027 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1028 Int3(); /* ipe - later! */
1029 return 1;
1030 }
1031 break;
1032 }
1033
1034
1035 /*
1036 * 16/32-bit importe variable.
1037 * This is used by accessing the 32-bit flat address in the callTab.
1038 * callTab-entry + 4 holds the offset of the variable into the object.
1039 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1040 * callTab-entry + a holds the 16-bit offset for the variable.
1041 * callTab-entry + c holds the selector for the object. (These two fiels is the 16:16-bit pointer to the variable.)
1042 */
1043 case EPT_VARIMPORT32:
1044 case EPT_VARIMPORT16:
1045 _aImportTab[i].cbProlog = (char)0;
1046 *(unsigned long*)(void*)&callTab[i][0] = _aImportTab[i].ulAddress;
1047 *(unsigned long*)(void*)&callTab[i][4] = _aImportTab[i].offObject;
1048 *(unsigned short*)(void*)&callTab[i][8] = _aImportTab[i].usSel;
1049 *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)_aImportTab[i].offObject;
1050 *(unsigned short*)(void*)&callTab[i][0xc] = _aImportTab[i].usSel;
1051 break;
1052
1053 default:
1054 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1055 Int3(); /* ipe - later! */
1056 return 1;
1057 } /* switch - type */
1058 } /* for */
1059
1060 return NO_ERROR;
1061}
1062
Note: See TracBrowser for help on using the repository browser.