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

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

Nearly there!

File size: 39.0 KB
Line 
1/* $Id: d32init.c,v 1.14 2000-02-21 09:24:00 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 (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 0
855 };
856
857 int i;
858 int cb;
859 int cbmin;
860
861 /*
862 * verify proctable
863 */
864 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
865 {
866 /* EPT_VARIMPORTs are skipped */
867 if ((_aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
868 continue;
869
870 if (EPT32BitEntry(_aImportTab[i]))
871 {
872 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
873 cbmin = 5; /* Size of the jump instruction */
874 }
875 else
876 {
877 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
878 cbmin = 7; /* Size of the far jump instruction */
879 }
880 if (cb <= 0 || cb + cbmin >= MAXSIZE_PROLOG)
881 {
882 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
883 return 1;
884 }
885 }
886
887 /*
888 * rehook / import
889 */
890 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
891 {
892 switch (_aImportTab[i].fType)
893 {
894 /*
895 * 32-bit procedure overload.
896 * The overloading procedure is found in the auFuncs table (at the same index
897 * as the overloaded procedure has in aImportTab).
898 * The overloaded procedure is called by issuing a call to the callTab entry.
899 */
900 case EPT_PROC32:
901 {
902 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, TRUE);
903 _aImportTab[i].cbProlog = (char)cb;
904 if (cb >= 5 && cb + 5 < MAXSIZE_PROLOG) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
905 { /* 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. */
906 /*
907 * Copy function prolog which will be overwritten by the jmp to calltabl.
908 */
909 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
910
911 /*
912 * Make jump instruction which jumps from calltab to original function.
913 * 0xE9 <four bytes displacement>
914 * Note: the displacement is relative to the next instruction
915 */
916 callTab[i][cb] = 0xE9; /* jmp */
917 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
918
919 /*
920 * Jump from original function to my function - an cli(?) could be needed here
921 */
922 *(char*)_aImportTab[i].ulAddress = 0xE9; /* jmp */
923 *(unsigned long*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
924 }
925 else
926 { /* !fatal! - this could never happen really... */
927 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
928 Int3(); /* ipe - later! */
929 return 1;
930 }
931 break;
932 }
933
934
935 /*
936 * 16-bit procedure overload.
937 * Currently disabled due to expected problems when calltab is a 32-bit segment.
938 */
939 case EPT_PROC16:
940 {
941 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
942 Int3();
943
944 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, TRUE);
945 _aImportTab[i].cbProlog = (char)cb;
946 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) */
947 { /* 7: size of a 16:32 jump which is added to the call tab */
948 /*
949 * Copy function prolog which is to be overwritten.
950 */
951 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
952
953 /*
954 * Create far jump from calltab to original function.
955 * 0xEA <four byte target address> <two byte target selector>
956 */
957 callTab[i][cb] = 0xEA; /* jmp far ptr */
958 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].offObject;
959 *(unsigned short*)(void*)&callTab[i][cb+5] = _aImportTab[i].usSel;
960
961 /*
962 * jump from original function to my function - an cli(?) could be needed here
963 * 0x66 0xEA <four byte target address> <two byte target selector>
964 */
965 *(char*)(_aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
966 *(char*)(_aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
967 *(unsigned long*)(_aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
968 *(unsigned short*)(_aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
969 }
970 else
971 { /* !fatal! - this could never happen really... */
972 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
973 Int3(); /* ipe - later! */
974 return 1;
975 }
976 break;
977 }
978
979
980 /*
981 * 32-bit imported procedure
982 * This is called by issuing a near call to the callTab entry.
983 */
984 case EPT_PROCIMPORT32:
985 {
986 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, FALSE);
987 _aImportTab[i].cbProlog = (char)cb;
988 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
989 {
990 /*
991 * Make jump instruction which jumps from calltab to original function.
992 * 0xE9 <four bytes displacement>
993 * Note: the displacement is relative to the next instruction
994 */
995 callTab[i][0] = 0xE9; /* jmp */
996 *(unsigned*)(void*)&callTab[i][1] = _aImportTab[i].ulAddress - (unsigned)&callTab[i][5];
997 }
998 else
999 { /* !fatal! - this should never really happen... */
1000 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1001 Int3(); /* ipe - later! */
1002 return 1;
1003 }
1004 break;
1005 }
1006
1007
1008 /*
1009 * 16-bit imported procedure.
1010 * This is called by issuing a far call to the calltab entry.
1011 */
1012 case EPT_PROCIMPORT16:
1013 {
1014 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, FALSE);
1015 _aImportTab[i].cbProlog = (char)cb;
1016 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1017 {
1018 /*
1019 * Create far jump from calltab to original function.
1020 * 0xEA <four byte target address> <two byte target selector>
1021 */
1022 callTab[i][0] = 0xEA; /* jmp far ptr */
1023 *(unsigned long*)(void*)&callTab[i][1] = _aImportTab[i].offObject;
1024 *(unsigned short*)(void*)&callTab[i][5] = _aImportTab[i].usSel;
1025 }
1026 else
1027 { /* !fatal! - this should never really happen... */
1028 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1029 Int3(); /* ipe - later! */
1030 return 1;
1031 }
1032 break;
1033 }
1034
1035
1036 /*
1037 * 16/32-bit importe variable.
1038 * This is used by accessing the 32-bit flat address in the callTab.
1039 * callTab-entry + 4 holds the offset of the variable into the object.
1040 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1041 * callTab-entry + a holds the 16-bit offset for the variable.
1042 * callTab-entry + c holds the selector for the object. (These two fiels is the 16:16-bit pointer to the variable.)
1043 */
1044 case EPT_VARIMPORT32:
1045 case EPT_VARIMPORT16:
1046 _aImportTab[i].cbProlog = (char)0;
1047 *(unsigned long*)(void*)&callTab[i][0] = _aImportTab[i].ulAddress;
1048 *(unsigned long*)(void*)&callTab[i][4] = _aImportTab[i].offObject;
1049 *(unsigned short*)(void*)&callTab[i][8] = _aImportTab[i].usSel;
1050 *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)_aImportTab[i].offObject;
1051 *(unsigned short*)(void*)&callTab[i][0xc] = _aImportTab[i].usSel;
1052 break;
1053
1054 default:
1055 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1056 Int3(); /* ipe - later! */
1057 return 1;
1058 } /* switch - type */
1059 } /* for */
1060
1061 return NO_ERROR;
1062}
1063
Note: See TracBrowser for help on using the repository browser.