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

Last change on this file since 6496 was 6278, checked in by bird, 24 years ago

New hybrid 16-bit import proc. New import prologs.

File size: 67.7 KB
Line 
1/* $Id: d32init.c,v 1.41 2001-07-10 05:18:04 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/*
15 * Calltab entry sizes.
16 */
17#define OVERLOAD16_ENTRY 0x18 /* This is intentionally 4 bytes larger than the one defined in calltaba.asm. */
18#define OVERLOAD32_ENTRY 0x14
19#define IMPORT16_ENTRY 0x08
20#define IMPORTH16_ENTRY 0x08
21#define IMPORT32_ENTRY 0x08
22#define VARIMPORT_ENTRY 0x10
23
24#if 0
25 #define kprintf2(a) kprintf
26#else
27 #define kprintf2(a) (void)0
28#endif
29
30#define INCL_DOSERRORS
31#define INCL_NOPMAPI
32#define LDR_INCL_INITONLY
33#define INCL_OS2KRNL_ALL
34#define INCL_OS2KRNL_LDR
35
36/*******************************************************************************
37* Header Files *
38*******************************************************************************/
39#include <os2.h>
40
41#include <string.h>
42
43#include "devSegDf.h"
44#include "OS2Krnl.h"
45#include "options.h"
46#include "dev1632.h"
47#include "dev32.h"
48#include "dev32hlp.h"
49#include "probkrnl.h"
50#include "log.h"
51#include "asmutils.h"
52#include "malloc.h"
53#include "ldr.h"
54#include "macros.h"
55#include "errors.h"
56
57#ifdef R3TST
58 #include "test.h"
59 #define x86DisableWriteProtect() 0
60 #define x86RestoreWriteProtect(a) (void)0
61#endif
62
63
64/*******************************************************************************
65* Global Variables *
66*******************************************************************************/
67#ifdef DEBUG
68static char * apszPE[] = {"FLAGS_PE_NOT", "FLAGS_PE_PE2LX", "FLAGS_PE_PE", "FLAGS_PE_MIXED", "!invalid!"};
69static char * apszPEOneObject[] = {"FLAGS_PEOO_DISABLED", "FLAGS_PEOO_ENABLED", "FLAGS_PEOO_FORCED", "!invalid!"};
70static char * apszInfoLevel[] = {"INFOLEVEL_QUIET", "INFOLEVEL_ERROR", "INFOLEVEL_WARNING", "INFOLEVEL_INFO", "INFOLEVEL_INFOALL", "!invalid!"};
71#endif
72PMTE pKrnlMTE = NULL;
73PSMTE pKrnlSMTE = NULL;
74POTE pKrnlOTE = NULL;
75
76
77/*******************************************************************************
78* Internal Functions *
79*******************************************************************************/
80 ULONG readnum(const char *pszNum);
81_Inline int ModR_M_32bit(char bModRM);
82_Inline int ModR_M_16bit(char bModRM);
83int interpretFunctionProlog32(char *pach, BOOL fOverload);
84int interpretFunctionProlog16(char *pach, BOOL fOverload);
85int importTabInit(void);
86#ifdef R3TST
87PMTE GetOS2KrnlMTETst(void);
88void R3TstFixImportTab(void);
89#endif
90PSZ SECCALL nopSecPathFromSFN(SFN hFile);
91
92
93
94/* externs located in 16-bit data segement in ProbKrnl.c */
95extern ULONG _TKSSBase16;
96extern USHORT _R0FlatCS16;
97extern USHORT _R0FlatDS16;
98
99/* extern(s) located in calltab.asm */
100extern char callTab[1];
101extern char callTab16[1];
102extern unsigned auFuncs[NBR_OF_KRNLIMPORTS];
103
104
105/**
106 * Ring-0, 32-bit, init function.
107 * @returns Status word.
108 * @param pRpInit Pointer init request packet.
109 * @sketch Set TKSSBase32.
110 * Set default parameters.
111 * Parse command line options.
112 * Show (kprint) configuration.
113 * Init heap.
114 * Init ldr.
115 * Init procs. (overloaded ldr procedures)
116 * @status completely implemented.
117 * @author knut st. osmundsen
118 */
119USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
120{
121 char * pszTmp2;
122 char * pszTmp;
123 ULONG ul;
124 APIRET rc;
125 LOCKHANDLE lockhandle;
126
127 pulTKSSBase32 = (PULONG)_TKSSBase16;
128
129 /*---------------------*/
130 /* commandline options */
131 /*---------------------*/
132 kprintf(("Options start\n"));
133 pszTmp = strpbrk(pRpInit->InitArgs, "-/");
134 while (pszTmp != NULL)
135 {
136 int cch;
137 pszTmp++; //skip [-/]
138 cch = strlen(pszTmp);
139 switch (*pszTmp)
140 {
141 case '1': /* All-In-One-Object fix - temporary...- -1<-|+|*> */
142 if (pszTmp[1] == '-')
143 options.fPEOneObject = FLAGS_PEOO_DISABLED;
144 else if (pszTmp[1] == '+')
145 options.fPEOneObject = FLAGS_PEOO_ENABLED;
146 else
147 options.fPEOneObject = FLAGS_PEOO_FORCED;
148 break;
149
150 case 'c':
151 case 'C': /* -C[1|2|3|4] or -Com:[1|2|3|4] - com-port no, def:-C2 */
152 pszTmp2 = strpbrk(pszTmp, ":=/- ");
153 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
154 pszTmp2++;
155 else
156 pszTmp2 = pszTmp + 1;
157 ul = readnum(pszTmp2);
158 switch (ul)
159 {
160 case 1: options.usCom = OUTPUT_COM1; break;
161 case 2: options.usCom = OUTPUT_COM2; break;
162 case 3: options.usCom = OUTPUT_COM3; break;
163 case 4: options.usCom = OUTPUT_COM4; break;
164 }
165 break;
166
167 case 'd':
168 case 'D':
169 pszTmp2 = strpbrk(pszTmp, ":=/- ");
170 if (pszTmp2 != NULL
171 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
172 )
173 options.fDllFixes = FALSE;
174 else
175 options.fDllFixes = TRUE;
176 break;
177
178 case 'e':
179 case 'E':/* Elf or EXe */
180 pszTmp2 = strpbrk(pszTmp, ":=/- ");
181 if (pszTmp[1] != 'x' && pszTmp[1] != 'X')
182 {
183 options.fElf = !(pszTmp2 != NULL
184 && ( pszTmp2[1] == 'N' || pszTmp2[1] == 'n'
185 || pszTmp2[1] == 'D' || pszTmp2[1] == 'd'));
186 }
187 else
188 {
189 options.fExeFixes = !(pszTmp2 != NULL
190 && ( pszTmp2[1] == 'N' || pszTmp2[1] == 'n'
191 || pszTmp2[1] == 'D' || pszTmp2[1] == 'd'));
192 }
193 break;
194
195 case 'f':
196 case 'F': /* -F[..]<:|=| >[<Y..|E..| > | <N..|D..>] - force preload */
197 pszTmp2 = strpbrk(pszTmp, ":=/- ");
198 if (pszTmp2 == NULL
199 || (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y' || pszTmp2[1] == 'E' || pszTmp2[1] == 'e')
200 )
201 options.fForcePreload = TRUE;
202 else
203 options.fForcePreload = FALSE;
204 break;
205
206 case 'h':
207 case 'H': /* Heap options */
208 pszTmp2 = strpbrk(pszTmp, ":=/- ");
209 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
210 {
211 ul = readnum(pszTmp2 + 1);
212 if (ul > 0x1000UL && ul < 0x2000000UL) /* 4KB < ul < 32MB */
213 {
214 if (strnicmp(pszTmp, "heapm", 5) == 0)
215 options.cbSwpHeapMax = ul;
216 else
217 options.cbSwpHeapInit = ul;
218 }
219 }
220 break;
221
222 case 'j':
223 case 'J': /* -Java:<Yes|No> */
224 pszTmp2 = strpbrk(pszTmp, ":=/- ");
225 options.fJava =
226 pszTmp2 != NULL
227 && (int)(pszTmp2-pszTmp) < cch-1
228 && (*pszTmp2 == ':' || *pszTmp2 == '=')
229 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
230 break;
231
232 case 'l':
233 case 'L': /* -L[..]<:|=| >[<Y..|E..| > | <N..|D..>] */
234 pszTmp2 = strpbrk(pszTmp, ":=/- ");
235 if (pszTmp2 != NULL
236 && (pszTmp2[1] == 'Y' ||pszTmp2[1] == 'y' || pszTmp2[1] == 'E' || pszTmp2[1] == 'e')
237 )
238 options.fLogging = TRUE;
239 else
240 options.fLogging = FALSE;
241 break;
242
243 case 'n':
244 case 'N': /* NoLoader */
245 options.fNoLoader = TRUE;
246 break;
247
248 case 'p':
249 case 'P': /* PE */
250 pszTmp2 = strpbrk(pszTmp, ":=/- ");
251 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
252 {
253 pszTmp2++;
254 if (strnicmp(pszTmp2, "pe2lx", 5) == 0)
255 options.fPE = FLAGS_PE_PE2LX;
256 else if (strnicmp(pszTmp2, "pe", 2) == 0)
257 options.fPE = FLAGS_PE_PE;
258 else if (strnicmp(pszTmp2, "mixed", 2) == 0)
259 options.fPE = FLAGS_PE_MIXED;
260 else if (strnicmp(pszTmp2, "not", 2) == 0)
261 options.fPE = FLAGS_PE_NOT;
262 else
263 kprintf(("R0Init32: invalid parameter -PE:...\n"));
264 }
265 else
266 kprintf(("R0Init32: invalid parameter -PE...\n"));
267 break;
268
269 case 'q':
270 case 'Q': /* quiet initialization */
271 options.fQuiet = TRUE;
272 break;
273
274 case 'r':
275 case 'R': /* ResHeap options or REXX option */
276 pszTmp2 = strpbrk(pszTmp, ":=/- ");
277 if ( (pszTmp[1] == 'E' || pszTmp[1] == 'e')
278 && (pszTmp[2] == 'X' || pszTmp[2] == 'x'))
279 { /* REXX */
280 options.fREXXScript =
281 pszTmp2 != NULL
282 && (int)(pszTmp2-pszTmp) < cch-1
283 && (*pszTmp2 == ':' || *pszTmp2 == '=')
284 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
285 }
286 else
287 { /* ResHeap options */
288 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
289 {
290 ul = readnum(pszTmp2 + 1);
291 if (ul > 0x1000UL && ul < 0x700000UL) /* 4KB < ul < 7MB */
292 {
293 if (strnicmp(pszTmp, "resheapm", 8) == 0)
294 options.cbResHeapMax = ul;
295 else
296 options.cbResHeapInit = ul;
297 }
298 }
299 }
300 break;
301
302 case 's':
303 case 'S': /* Sym:<filename> or Script:<Yes|No> or Smp */
304 /* SMP kernel */
305 pszTmp2 = strpbrk(pszTmp, ":=/- ");
306 if (pszTmp[1] == 'c' || pszTmp[1] == 'C')
307 {
308 options.fUNIXScript =
309 pszTmp2 != NULL
310 && (int)(pszTmp2-pszTmp) < cch-1
311 && (*pszTmp2 == ':' || *pszTmp2 == '=')
312 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
313 }
314 break;
315
316 case 'v':
317 case 'V': /* verbose initialization */
318 options.fQuiet = FALSE;
319 break;
320
321 case 'w':
322 case 'W': /* ModuleBase info level; -W<n> or -Warning:<n> */
323 if (pszTmp[1] >= '0' && pszTmp[1] <= '4')
324 options.ulInfoLevel = pszTmp[1] - '0';
325 else
326 {
327 pszTmp2 = strpbrk(pszTmp, ":=/- ");
328 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
329 pszTmp2++;
330 else
331 pszTmp2 = pszTmp + 1;
332
333 if (*pszTmp2 >= '0' && *pszTmp2 <= '4')
334 options.ulInfoLevel = *pszTmp2 - '0';
335 }
336 break;
337
338 }
339 pszTmp = strpbrk(pszTmp, "-/");
340 }
341
342 /* heap min/max corrections */
343 if (options.cbSwpHeapInit > options.cbSwpHeapMax)
344 options.cbSwpHeapMax = options.cbSwpHeapInit;
345 if (options.cbResHeapInit > options.cbResHeapMax)
346 options.cbResHeapMax = options.cbResHeapInit;
347
348 /* Log option summary */
349 #ifdef DEBUG
350 kprintf(("Options - Summary - Start\n"));
351 if (options.fQuiet)
352 kprintf(("\tQuiet init\n"));
353 else
354 kprintf(("\tVerbose init\n"));
355
356 if (options.fLogging)
357 kprintf(("\tlogging enabled\n"));
358 else
359 kprintf(("\tlogging disabled\n"));
360 kprintf(("\tCom port no.%03xh\n", options.usCom));
361
362 kprintf(("\tKernel: v%d.%d build %d%c type ",
363 options.usVerMajor,
364 options.usVerMinor,
365 options.ulBuild,
366 (options.fKernel & KF_REV_MASK)
367 ? ((options.fKernel & KF_REV_MASK) >> KF_REV_SHIFT) + 'a'-1
368 : ' '
369 ));
370 if (options.fKernel & KF_SMP)
371 kprintf(("SMP "));
372 else if (options.fKernel & KF_W4)
373 kprintf(("W4 "));
374 else
375 kprintf(("UNI "));
376 if (options.fKernel & KF_DEBUG)
377 kprintf(("DEBUG\n"));
378 else
379 kprintf(("\n"));
380
381 kprintf(("\tfPE=%d (%s)\n", options.fPE, apszPE[MIN(options.fPE, 5)]));
382 kprintf(("\tfPEOneObject=%d (%s)\n", options.fPEOneObject, apszPEOneObject[MIN(options.fPEOneObject, 3)]));
383 kprintf(("\tulInfoLevel=%d (%s)\n", options.ulInfoLevel, apszInfoLevel[MIN(options.ulInfoLevel, 5)]));
384 kprintf(("\tfElf=%d\n", options.fElf));
385 kprintf(("\tfUNIXScript=%d\n", options.fUNIXScript));
386 kprintf(("\tfREXXScript=%d\n", options.fREXXScript));
387 kprintf(("\tfJAVA=%d\n", options.fJava));
388 kprintf(("\tfNoLoader=%d\n", options.fNoLoader));
389 kprintf(("\tcbSwpHeapInit=0x%08x cbSwpHeapMax=0x%08x\n",
390 options.cbSwpHeapInit, options.cbSwpHeapMax));
391 kprintf(("\tcbResHeapInit=0x%08x cbResHeapMax=0x%08x\n",
392 options.cbResHeapInit, options.cbResHeapMax));
393 kprintf(("Options - Summary - End\n"));
394 #endif /* debug */
395 /* end option summary */
396
397
398 /*
399 * init sub-parts
400 */
401 /* heap */
402 if (heapInit(options.cbResHeapInit, options.cbResHeapMax,
403 options.cbSwpHeapInit, options.cbSwpHeapMax) != NO_ERROR)
404 return ERROR_D32_HEAPINIT_FAILED;
405
406 /* loader */
407 if (ldrInit() != NO_ERROR)
408 return ERROR_D32_LDR_INIT_FAILED;
409
410 /* functionoverrides */
411 if ((rc = importTabInit()) != NO_ERROR)
412 return (USHORT)rc;
413
414 /* apis */
415 #if 0
416 if ((rc = APIInit()) != NO_ERROR)
417 return (USHORT)rc;
418 #endif
419
420 /* callgate */
421 #ifndef R3TST
422 if ((rc = InitCallGate()) != NO_ERROR)
423 {
424 kprintf(("R0Init32: InitCallGate failed with rc=%d\n", rc));
425 return (USHORT)rc;
426 }
427 #endif
428
429
430 /*
431 * Lock the 32-bit objects/segments and 16-bit datasegment in memory
432 */
433 /* 32-bit code segment */
434 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
435 rc = D32Hlp_VMLock2(&CODE32START,
436 ((unsigned)&CODE32END & ~0xFFF) - (unsigned)&CODE32START, /* Round down so we don't overlap with the next request. */
437 VMDHL_LONG,
438 SSToDS(&lockhandle));
439 if (rc != NO_ERROR)
440 kprintf(("code segment lock failed with with rc=%d\n", rc));
441
442 /* 32-bit data segment */
443 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
444 rc = D32Hlp_VMLock2(callTab,
445 &CONST32_ROEND - (char*)callTab,
446 VMDHL_LONG | VMDHL_WRITE,
447 SSToDS(&lockhandle));
448 if (rc != NO_ERROR)
449 kprintf(("data segment lock failed with with rc=%d\n", rc));
450
451 return NO_ERROR;
452}
453
454
455/**
456 * Reads a number (unsigned long integer) for a string.
457 * @returns number read, ~0UL on error / no number read.
458 * @param pszNum Pointer to the string containing the number.
459 * @status competely implemented.
460 * @author knut st. osmundsen
461 */
462ULONG readnum(const char *pszNum)
463{
464 ULONG ulRet = 0;
465 ULONG ulBase = 10;
466 int i = 0;
467
468 /* determin ulBase */
469 if (*pszNum == '0')
470 if (pszNum[1] == 'x' || pszNum[1] == 'X')
471 {
472 ulBase = 16;
473 pszNum += 2;
474 }
475 else
476 {
477 ulBase = 8;
478 i = 1;
479 }
480
481 /* read digits */
482 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
483 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
484 )
485 {
486 ulRet *= ulBase;
487 if (ulBase <= 10)
488 ulRet += pszNum[i] - '0';
489 else
490 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
491
492 i++;
493 }
494
495 return i > 0 ? ulRet : ~0UL;
496}
497
498
499/**
500 * Get kernel OTEs
501 * This function set pKrnlMTE, pKrnlSMTE and pKrnlOTE.
502 * @returns Strategy return code:
503 * STATUS_DONE on success.
504 * STATUS_DONE | STERR | errorcode on failure.
505 * @param pKrnlInfo Pointer to output buffer.
506 * If NULL only the three global variables are set.
507 * @status completely implemented and tested.
508 * @author knut st. osmundsen
509 * @remark Called from IOCtl.
510 * WARNING! This function is called before the initroutine (R0INIT)!
511 */
512USHORT _loadds _Far32 _Pascal GetKernelInfo32(PKRNLINFO pKrnlInfo)
513{
514 int i;
515 USHORT usRc;
516
517 /* VerifyImportTab32 is called before the initroutine! */
518 pulTKSSBase32 = (PULONG)_TKSSBase16;
519
520 /* Find the kernel OTE table */
521#ifndef R3TST
522 pKrnlMTE = GetOS2KrnlMTE();
523#else
524 pKrnlMTE = GetOS2KrnlMTETst();
525#endif
526 if (pKrnlMTE != NULL)
527 {
528 pKrnlSMTE = pKrnlMTE->mte_swapmte;
529 if (pKrnlSMTE != NULL)
530 {
531 if (pKrnlSMTE->smte_objcnt <= MAXKRNLOBJECTS)
532 {
533 pKrnlOTE = pKrnlSMTE->smte_objtab;
534 if (pKrnlOTE != NULL)
535 {
536 BOOL fKrnlTypeOk;
537
538 /*
539 * Thats all?
540 */
541 if (pKrnlInfo == NULL)
542 return NO_ERROR;
543
544 pKrnlInfo->cObjects = (unsigned char)pKrnlSMTE->smte_objcnt;
545
546 /*
547 * Copy OTEs
548 */
549 for (i = 0; i < pKrnlInfo->cObjects; i++)
550 {
551 memcpy((void*)&pKrnlInfo->aObjects[i], &pKrnlOTE[i], sizeof(OTE));
552 kprintf2(("GetKernelInfo32: %d base=0x%08x size=0x%08x flags=0x%08x\n",
553 i, pKrnlOTE[i].ote_base, pKrnlOTE[i].ote_size, pKrnlOTE[i].ote_flags));
554 }
555 usRc = 0;
556
557 /*
558 * Search for internal revision stuff AND 'SAB KNL?' signature in the two first objects.
559 */
560 fKrnlTypeOk = FALSE;
561 pKrnlInfo->fKernel = 0;
562 pKrnlInfo->ulBuild = 0;
563 for (i = 0; i < 2 && pKrnlInfo->ulBuild == 0; i++)
564 {
565 const char *psz = (const char*)pKrnlOTE[i].ote_base;
566 const char *pszEnd = psz + pKrnlOTE[i].ote_size - 50; /* Last possible search position. */
567
568 while (psz < pszEnd)
569 {
570 if (strncmp(psz, "Internal revision ", 18) == 0 && (psz[18] >= '0' && psz[18] <= '9'))
571 {
572 int j;
573 kprintf2(("GetKernelInfo32: found internal revision: '%s'\n", psz));
574
575 /* skip to end of "Internal revision " string. */
576 psz += 18;
577
578 /* Read number*/
579 while ((*psz >= '0' && *psz <= '9') || *psz == '.')
580 {
581 if (*psz != '.')
582 pKrnlInfo->ulBuild = (unsigned short)(pKrnlInfo->ulBuild * 10 + (*psz - '0'));
583 psz++;
584 }
585
586 /* Check if build number seems valid. */
587 if ( !(pKrnlInfo->ulBuild >= 8254 && pKrnlInfo->ulBuild < 8383) /* Warp 3 fp 32 -> fp 60 */
588 && !(pKrnlInfo->ulBuild >= 9023 && pKrnlInfo->ulBuild <= 9036) /* Warp 4 GA -> fp 12 */
589 && !(pKrnlInfo->ulBuild >= 14039 && pKrnlInfo->ulBuild < 14100) /* Warp 4.5 GA -> fp 40 */
590 && !(pKrnlInfo->ulBuild >= 6600 && pKrnlInfo->ulBuild <= 6678) /* Warp 2.1x fix?? (just for fun!) */
591 )
592 {
593 kprintf(("GetKernelInfo32: info summary: Build %d is invalid - invalid fixpack?\n", pKrnlInfo->ulBuild));
594 usRc = ERROR_D32_INVALID_BUILD;
595 break;
596 }
597
598 /* Check for any revision flag */
599 if ((*psz >= 'A' && *psz <= 'Z') || (*psz >= 'a' && *psz <= 'z'))
600 {
601 pKrnlInfo->fKernel |= (USHORT)((*psz - (*psz >= 'a' ? 'a'-1 : 'A'-1)) << KF_REV_SHIFT);
602 psz++;
603 }
604 if (*psz == ',') /* This is ignored! */
605 *psz++;
606
607 /* If this is an Aurora/Warp 4.5 or Warp 3 kernel there is more info! */
608 if (psz[0] == '_' && (psz[1] == 'S' || psz[1] == 's')) /* _SMP */
609 pKrnlInfo->fKernel |= KF_SMP;
610 else
611 if (*psz != ','
612 && ( (psz[0] == '_' && psz[1] == 'W' && psz[2] == '4') /* _W4 */
613 || (psz[0] == '_' && psz[1] == 'U' && psz[2] == 'N' && psz[3] == 'I' && psz[4] == '4') /* _UNI4 */
614 )
615 )
616 pKrnlInfo->fKernel |= KF_W4 | KF_UNI;
617 else
618 pKrnlInfo->fKernel |= KF_UNI;
619
620
621 /* Check if its a debug kernel (look for DEBUG at start of object 3-5) */
622 if (!fKrnlTypeOk)
623 {
624 j = 3;
625 while (j < 5)
626 {
627 /* There should be no iopl object preceding the debugger data object. */
628 if ((pKrnlOTE[j].ote_flags & OBJIOPL) != 0)
629 break;
630 /* Is this is? */
631 if ((pKrnlOTE[j].ote_flags & OBJINVALID) == 0
632 && (pKrnlOTE[j].ote_flags & (OBJREAD | OBJWRITE)) == (OBJREAD | OBJWRITE)
633 && strncmp((char*)pKrnlOTE[j].ote_base, "DEBUG", 5) == 0)
634 {
635 pKrnlInfo->fKernel |= KF_DEBUG;
636 break;
637 }
638 j++;
639 }
640 }
641
642 /* Display info */
643 kprintf(("GetKernelInfo32: info summary: Build %d, fKernel=0x%x\n",
644 pKrnlInfo->ulBuild, pKrnlInfo->fKernel));
645
646 /* Break out */
647 break;
648 }
649
650 /*
651 * Look for the SAB KNL? signature to check which kernel type we're
652 * dealing with. This could also be reached thru the selector found
653 * in the first element for the SAS_tables_area array.
654 */
655 if (!fKrnlTypeOk && strncmp(psz, "SAB KNL", 7) == 0)
656 {
657 fKrnlTypeOk = TRUE;
658 if (psz[7] == 'D')
659 pKrnlInfo->fKernel |= KF_ALLSTRICT;
660 else if (psz[7] == 'B')
661 pKrnlInfo->fKernel |= KF_HALFSTRICT;
662 else if (psz[7] != 'R')
663 fKrnlTypeOk = FALSE;
664 }
665
666 /* next */
667 psz++;
668 } /* while loop searching for "Internal revision " */
669 } /* for loop on objects 0-1. */
670
671 /* Set error code if not found */
672 if (pKrnlInfo->ulBuild == 0)
673 {
674 usRc = ERROR_D32_BUILD_INFO_NOT_FOUND;
675 kprintf(("GetKernelInfo32: Internal revision was not found!\n"));
676 }
677 }
678 else
679 usRc = ERROR_D32_NO_OBJECT_TABLE;
680 }
681 else
682 usRc = ERROR_D32_TOO_MANY_OBJECTS;
683 }
684 else
685 usRc = ERROR_D32_NO_SWAPMTE;
686 }
687 else
688 usRc = ERROR_D32_GETOS2KRNL_FAILED;
689
690 if (usRc != NO_ERROR)
691 kprintf(("GetKernelInfo32: failed. usRc = %d\n", usRc));
692
693 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
694}
695
696
697
698/**
699 * Functions which cacluates the instructionsize given a ModR/M byte.
700 * @returns Number of bytes to add to cb and pach.
701 * @param bModRM ModR/M byte.
702 * @status completely implemented.
703 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
704 */
705int ModR_M_32bit(char bModRM)
706{
707 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
708 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
709 { /* 32-bit displacement */
710 return 5 + ((bModRM & 0x7) == 0x4); // + SIB
711 }
712 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
713 { /* 8-bit displacement */
714 return 2 + ((bModRM & 0x7) == 0x4); // + SIB
715 }
716 /* no displacement (only /r byte) */
717 return 1;
718}
719
720
721/**
722 * Functions which cacluates the instructionsize given a ModR/M byte.
723 * @returns Number of bytes to add to cb and pach.
724 * @param bModRM ModR/M byte.
725 * @status completely implemented.
726 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
727 */
728int ModR_M_16bit(char bModRM)
729{
730 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
731 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
732 { /* 16-bit displacement */
733 return 4;
734 }
735 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
736 { /* 8-bit displacement */
737 return 2;
738 }
739 /* no displacement (only /r byte) */
740 return 1;
741}
742
743
744
745
746
747/**
748 * 32-bit! Interpret function prolog to find where to jmp back.
749 * @returns Length of prolog need to be copied - which is also the offset of
750 * where the jmp instr should be placed.
751 * On error it returns 0.
752 * @param pach Pointer to prolog.
753 * @param fOverload TRUE: Function is to be overloaded.
754 * FALSE: Function is to be imported.
755 */
756int interpretFunctionProlog32(char *pach, BOOL fOverload)
757{
758 int cb = -3;
759 kprintf2(("interpretFunctionProlog32(0x%08x, %d):\n"
760 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
761 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
762 pach, fOverload,
763 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
764 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
765
766 /*
767 * check for the well known prolog (the only that is supported now)
768 * which is:
769 * push ebp
770 * mov ebp,esp
771 * or
772 * push ebp
773 * mov eax, dword ptr [xxxxxxxx]
774 * or
775 * sub esp, imm8
776 * push ebx
777 * push edi
778 *
779 * These are allowed when not overloading:
780 * mov eax, imm32
781 * jmp short
782 * or
783 * mov eax, imm32
784 * push ebp
785 * or
786 * mov ecx, r/m32
787 * or
788 * jmp dword
789 * or
790 * sub esp, imm8
791 * or
792 * call ptr16:32
793 * or
794 * enter imm16, imm8 (2.1x)
795 * or
796 * mov eax, imm32 (2.1x)
797 * <anything>
798 * or
799 * xor r32, r/m32
800 * or
801 * mov eax, msoff32
802 * or
803 * push edi
804 * mov eax, dword ptr [xxxxxxxx]
805 * or
806 * movzx esp, sp
807 * or
808 * call rel32
809 * popf
810 */
811 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* the two first prologs */
812 ||
813 (pach[0] == 0x83 && pach[3] == 0x53 && pach[4] == 0x57) /* the third prolog */
814 ||
815 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55) && !fOverload) /* the two next prologs */
816 ||
817 (pach[0] == 0x8B && !fOverload) /* the next prolog */
818 ||
819 (pach[0] == 0xFF && !fOverload) /* the next prolog */
820 ||
821 (pach[0] == 0x83 && !fOverload) /* the next prolog */
822 ||
823 (pach[0] == 0x9a && !fOverload) /* the next prolog */
824 ||
825 (pach[0] == 0xc8) /* the next prolog */
826 ||
827 (pach[0] == 0xB8 && !fOverload) /* the next prolog */
828 ||
829 (pach[0] == 0x33 && !fOverload) /* the next prolog */
830 ||
831 (pach[0] == 0xa1 && !fOverload) /* the next prolog */
832 ||
833 (pach[0] == 0x57 && pach[1] == 0x8b && !fOverload) /* the next prolog */
834 ||
835 (pach[0] == 0x0f && pach[1] == 0xb7 && pach[2] == 0xe4 && !fOverload) /* the next prolog */
836 ||
837 (pach[0] == 0xe8 && pach[5] == 0x9d && !fOverload) /* the next prolog */
838 /* push ebx
839 * push edi
840 * push imm32
841 */
842 || (pach[0] == 0x53 && pach[1] == 0x57 && pach[2] == 0x68 && !fOverload)
843 /* push ebx
844 * push edi
845 * push esi
846 * mov /r
847 */
848 || (pach[0] == 0x53 && pach[1] == 0xe8 && !fOverload)
849 /* push ebx
850 * push edi
851 * push esi
852 * mov /r
853 */
854 || (pach[0] == 0x53 && pach[1] == 0x57 && pach[2] == 0x56 && pach[3] == 0x8b && !fOverload)
855 /* pop eax
856 * push imm8
857 * push eax
858 * jmp imm32
859 */
860 || (pach[0] == 0x58 && pach[1] == 0x6a && pach[3] == 0x50 && pach[4] == 0xe9 && !fOverload)
861 /* push imm32
862 * call imm32
863 */
864 || (pach[0] == 0x68 && pach[5] == 0xe8 && !fOverload)
865 )
866 {
867 BOOL fForce = FALSE;
868 int cbWord = 4;
869 cb = 0;
870 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
871 {
872 int cb2;
873 if (!fForce && cbWord != 4)
874 cbWord = 4;
875 fForce = FALSE;
876 switch (*pach)
877 {
878 case 0x0f:
879 if (pach[1] != 0xb7 && pach[2] != 0xe4) /* movzx esp, sp */
880 {
881 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
882 return -11;
883 }
884 pach += 2;
885 cb += 2;
886 break;
887
888
889 /* simple one byte prefixes */
890 case 0x2e: /* cs segment override */
891 case 0x36: /* ss segment override */
892 case 0x3e: /* ds segment override */
893 case 0x26: /* es segment override */
894 case 0x64: /* fs segment override */
895 case 0x65: /* gs segment override */
896 fForce = TRUE;
897 break;
898
899 case 0x66: /* 16 bit */
900 fForce = TRUE;
901 cbWord = 2;
902 break;
903
904 /* simple one byte instructions e*/
905 case 0x50: /* push eax */
906 case 0x51: /* push ecx */
907 case 0x52: /* push edx */
908 case 0x53: /* push ebx */
909 case 0x54: /* push esp */
910 case 0x55: /* push ebp */
911 case 0x56: /* push esi */
912 case 0x57: /* push edi */
913 case 0x58: /* pop eax */
914 case 0x59: /* pop ecx */
915 case 0x5a: /* pop edx */
916 case 0x5b: /* pop ebx */
917 case 0x06: /* push es */
918 case 0x0e: /* push cs */
919 case 0x1e: /* push ds */
920 case 0x16: /* push ss */
921 break;
922
923 /* simple two byte instructions */
924 case 0xb0: /* mov al, imm8 */
925 case 0xb1: /* mov cl, imm8 */
926 case 0xb2: /* mov dl, imm8 */
927 case 0xb3: /* mov bl, imm8 */
928 case 0xb4: /* mov ah, imm8 */
929 case 0xb5: /* mov ch, imm8 */
930 case 0xb6: /* mov dh, imm8 */
931 case 0xb7: /* mov bh, imm8 */
932 case 0x2c: /* sub al, imm8 */
933 case 0x34: /* xor al, imm8 */
934 case 0x3c: /* cmp al, imm8 */
935 case 0x6a: /* push <byte> */
936 case 0xa0: /* mov al, moffs8 */
937 case 0xa2: /* mov moffs8, al */
938 pach++;
939 cb++;
940 break;
941
942 /* simple five byte instructions */
943 case 0xb8: /* mov eax, imm32 */
944 case 0xb9: /* mov ecx, imm32 */
945 case 0xba: /* mov edx, imm32 */
946 case 0xbb: /* mov ebx, imm32 */
947 case 0xbc: /* mov esx, imm32 */
948 case 0xbd: /* mov ebx, imm32 */
949 case 0xbe: /* mov esi, imm32 */
950 case 0xbf: /* mov edi, imm32 */
951 case 0xe9: /* jmp rel32 */
952 case 0x2d: /* sub eax, imm32 */
953 case 0x35: /* xor eax, imm32 */
954 case 0x3d: /* cmp eax, imm32 */
955 case 0x68: /* push <dword> */
956 case 0xa1: /* mov eax, moffs16 */
957 case 0xa3: /* mov moffs16, eax */
958 pach += cbWord;
959 cb += cbWord;
960 break;
961
962 /* fixed five byte instructions */
963 case 0xe8: /* call imm32 */
964 pach += 4;
965 cb += 4;
966 break;
967
968 /* complex sized instructions - "/r" */
969 case 0x30: /* xor r/m8, r8 */
970 case 0x31: /* xor r/m32, r32 */
971 case 0x32: /* xor r8, r/m8 */
972 case 0x33: /* xor r32, r/m32 */
973 case 0x38: /* cmp r/m8, r8 */
974 case 0x39: /* cmp r/m32, r32 */
975 case 0x3a: /* cmp r8, r/m8 */
976 case 0x3b: /* cmp r32, r/m32 */
977 case 0x28: /* sub r/m8, r8 */
978 case 0x29: /* sub r/m32, r32 */
979 case 0x2a: /* sub r8, r/m8 */
980 case 0x2b: /* sub r32, r/m32 */
981 case 0x8b: /* mov /r */
982 case 0x8d: /* lea /r */
983 cb += cb2 = ModR_M_32bit(pach[1]);
984 pach += cb2;
985 break;
986
987 /* complex sized instruction - "/5 ib" */
988 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
989 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
990 if ((pach[1] & 0x38) == (5<<3)
991 || (pach[1] & 0x38) == (7<<3)
992 )
993 {
994 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
995 pach += cb2;
996 }
997 else
998 {
999 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1000 return -3;
1001 }
1002 break;
1003
1004 /* complex sized instruction - "/digit id" */
1005 case 0x81: /* sub r/m32, imm32 + more instructions! */
1006 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
1007 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
1008 )
1009 {
1010 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
1011 pach += cb2;
1012 }
1013 else
1014 {
1015 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1016 return -2;
1017 }
1018 break;
1019
1020 case 0x9a: /* call ptr16:32 */
1021 cb += cb2 = 6;
1022 pach += cb2;
1023 break;
1024
1025 case 0xc8: /* enter imm16, imm8 */
1026 cb += cb = 3;
1027 pach += cb2;
1028 break;
1029
1030 /*
1031 * jmp /digit
1032 */
1033 case 0xff:
1034 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
1035 pach += cb2;
1036 break;
1037
1038 default:
1039 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1040 return 0;
1041 }
1042 pach++;
1043 cb++;
1044 }
1045 }
1046 else
1047 {
1048 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1049 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5]));
1050 cb = 0;
1051 }
1052 return cb;
1053}
1054
1055
1056/**
1057 * 16-bit! Interpret function prolog to find where to jmp back.
1058 * @returns Length of prolog need to be copied - which is also the offset of
1059 * where the jmp instr should be placed.
1060 * On error it returns 0.
1061 * @param pach Pointer to prolog.
1062 * @param fOverload TRUE: Function is to be overloaded.
1063 * FALSE: Function is to be imported.
1064 */
1065int interpretFunctionProlog16(char *pach, BOOL fOverload)
1066{
1067 int cb = -7;
1068
1069 kprintf2(("interpretFunctionProlog16(0x%08x, %d):\n"
1070 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
1071 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
1072 pach, fOverload,
1073 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
1074 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
1075 /*
1076 * Check for the well known prolog (the only that is supported now)
1077 * which is:
1078 */
1079 if ((*pach == 0x6A && !fOverload) /* push 2 (don't check for the 2) */
1080 ||
1081 *pach == 0x60 /* pushf */
1082 ||
1083 (*pach == 0x53 && pach[1] == 0x51) /* push bx, push cx */
1084 ||
1085 (*pach == 0x8c && pach[1] == 0xd8) /* mov ax, ds */
1086 ||
1087 (*pach == 0xb8) /* mov ax, imm16 */
1088 )
1089 {
1090 BOOL fForce;
1091 int cOpPrefix = 0;
1092 cb = 0;
1093 while (cb < 5 || fForce) /* 5 is the size of a 16:16 far jump instruction. */
1094 {
1095 int cb2;
1096 fForce = FALSE;
1097 switch (*pach)
1098 {
1099 case 0x06: /* push es */
1100 case 0x0e: /* push cs */
1101 case 0x1e: /* push ds */
1102 case 0x16: /* push ss */
1103 break;
1104
1105 case 0x0f: /* push gs and push fs */
1106 if (pach[1] != 0xA0 && pach[1] != 0xA8)
1107 {
1108 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1109 return -11;
1110 }
1111 pach++;
1112 cb++;
1113 break;
1114
1115 case 0x50: /* push ax */
1116 case 0x51: /* push cx */
1117 case 0x52: /* push dx */
1118 case 0x53: /* push bx */
1119 case 0x54: /* push sp */
1120 case 0x55: /* push bp */
1121 case 0x56: /* push si */
1122 case 0x57: /* push di */
1123 case 0x60: /* pusha */
1124 break;
1125
1126 /* simple three byte instructions */
1127 case 0xb8: /* mov eax, imm16 */
1128 case 0xb9: /* mov ecx, imm16 */
1129 case 0xba: /* mov edx, imm16 */
1130 case 0xbb: /* mov ebx, imm16 */
1131 case 0xbc: /* mov esx, imm16 */
1132 case 0xbd: /* mov ebx, imm16 */
1133 case 0xbe: /* mov esi, imm16 */
1134 case 0xbf: /* mov edi, imm16 */
1135 case 0x2d: /* sub eax, imm16 */
1136 case 0x35: /* xor eax, imm16 */
1137 case 0x3d: /* cmp eax, imm16 */
1138 case 0x68: /* push <dword> */
1139 case 0xa1: /* mov eax, moffs16 */
1140 case 0xa3: /* mov moffs16, eax */
1141 if (cOpPrefix > 0) /* FIXME see 32-bit interpreter. */
1142 {
1143 pach += 2;
1144 cb += 2;
1145 }
1146 pach += 2;
1147 cb += 2;
1148 break;
1149
1150 case 0x2e: /* cs segment override */
1151 case 0x36: /* ss segment override */
1152 case 0x3e: /* ds segment override */
1153 case 0x26: /* es segment override */
1154 case 0x64: /* fs segment override */
1155 case 0x65: /* gs segment override */
1156 fForce = TRUE;
1157 if (cOpPrefix > 0)
1158 cOpPrefix++;
1159 break;
1160
1161 case 0x66:
1162 cOpPrefix = 2; /* it's decremented once before it's used. */
1163 fForce = TRUE;
1164 break;
1165
1166 case 0x6a: /* push <byte> */
1167 case 0x3c: /* mov al, imm8 */
1168 pach++;
1169 cb++;
1170 break;
1171
1172 case 0x8b: /* mov /r */
1173 case 0x8c: /* mov r/m16,Sreg (= mov /r) */
1174 case 0x8e: /* mov Sreg, r/m16 (= mov /r) */
1175 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
1176 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
1177 { /* 16-bit displacement */
1178 if (cOpPrefix > 0)
1179 {
1180 pach += 2;
1181 cb += 2;
1182 }
1183 pach += 3;
1184 cb += 3;
1185 }
1186 else
1187 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
1188 { /* 8-bit displacement */
1189 pach += 2;
1190 cb += 2;
1191 }
1192 else
1193 { /* no displacement (only /r byte) */
1194 pach++;
1195 cb++;
1196 }
1197 break;
1198
1199 /* complex sized instruction - "/5 ib" */
1200 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
1201 case 0x83: /* 5: sub r/m16, imm8 7: cmp r/m16, imm8 */
1202 if ((pach[1] & 0x38) == (5<<3)
1203 || (pach[1] & 0x38) == (7<<3)
1204 )
1205 {
1206 cb += cb2 = 1 + ModR_M_16bit(pach[1]); /* 1 is the size of the imm8 */
1207 pach += cb2;
1208 }
1209 else
1210 {
1211 kprintf(("interpretFunctionProlog16: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1212 return -3;
1213 }
1214 break;
1215
1216 case 0x9a: /* call ptr16:16 */
1217 cb += cb2 = 4;
1218 pach += cb2;
1219 break;
1220
1221 default:
1222 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1223 return 0;
1224 }
1225 pach++;
1226 cb++;
1227 if (cOpPrefix > 0)
1228 cOpPrefix--;
1229 }
1230 }
1231 else
1232 kprintf(("interpretFunctionProlog16: unknown prolog 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1233
1234
1235 fOverload = fOverload;
1236 return cb;
1237}
1238
1239
1240/**
1241 * Verifies the aImportTab.
1242 * @returns 16-bit errorcode where the high byte is the procedure number which
1243 * the error occured on and the low byte the error code.
1244 * @remark Called from IOCtl.
1245 * WARNING! This function is called before the initroutine (R0INIT)!
1246 */
1247USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
1248{
1249 USHORT usRc;
1250 int i;
1251 int cb;
1252 int cbmax;
1253
1254 /* VerifyImporTab32 is called before the initroutine! */
1255 pulTKSSBase32 = (PULONG)_TKSSBase16;
1256
1257 /* Check that pKrnlOTE is set */
1258 usRc = GetKernelInfo32(NULL);
1259 if (usRc != NO_ERROR)
1260 return usRc;
1261
1262 /*
1263 * Verify aImportTab.
1264 */
1265 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1266 {
1267 /*
1268 * Debug info
1269 */
1270 kprintf2(("VerifyImportTab32: procedure no.%d is being checked: %s addr=0x%08x iObj=%d offObj=%d\n",
1271 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1272 aImportTab[i].iObject, aImportTab[i].offObject));
1273
1274 /* Verify that it is found */
1275 if (!aImportTab[i].fFound)
1276 {
1277 if (EPTNotReq(aImportTab[i]))
1278 continue;
1279 else
1280 {
1281 kprintf(("VerifyImportTab32: procedure no.%d was not fFound!\n", i));
1282 return (USHORT)(ERROR_D32_PROC_NOT_FOUND | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1283 }
1284 }
1285
1286 /* Verify read/writeable. */
1287 if ( aImportTab[i].iObject >= pKrnlSMTE->smte_objcnt /* object index valid? */
1288 || aImportTab[i].ulAddress < pKrnlOTE[aImportTab[i].iObject].ote_base /* address valid? */
1289 || aImportTab[i].ulAddress + 16 > (pKrnlOTE[aImportTab[i].iObject].ote_base +
1290 pKrnlOTE[aImportTab[i].iObject].ote_size) /* address valid? */
1291 || aImportTab[i].ulAddress - aImportTab[i].offObject
1292 != pKrnlOTE[aImportTab[i].iObject].ote_base /* offObject ok? */
1293 )
1294 {
1295 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address or object number.!\n"
1296 " %s addr=0x%08x iObj=%d offObj=%d\n",
1297 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1298 aImportTab[i].iObject, aImportTab[i].offObject));
1299 return (USHORT)(ERROR_D32_INVALID_OBJ_OR_ADDR | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1300 }
1301
1302
1303 #ifndef R3TST
1304 if (aImportTab[i].ulAddress < 0xff400000UL)
1305 {
1306 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address, %#08x!\n",
1307 i, aImportTab[i].ulAddress));
1308 return (USHORT)(ERROR_D32_INVALID_ADDRESS | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1309 }
1310 #endif
1311
1312 switch (aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ | EPT_WRAPPED | EPT_PROCIMPORTH))
1313 {
1314 case EPT_PROC:
1315 case EPT_PROCIMPORT:
1316 /*
1317 * Verify known function prolog.
1318 */
1319 if (EPT32BitEntry(aImportTab[i]))
1320 {
1321 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1322 cbmax = OVERLOAD32_ENTRY - 5; /* 5 = Size of the jump instruction */
1323 }
1324 else
1325 {
1326 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1327 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1328 }
1329
1330 /*
1331 * Check result of the function prolog interpretations.
1332 */
1333 if (cb <= 0 || cb > cbmax)
1334 { /* failed, too small or too large. */
1335 kprintf(("VerifyImportTab32/16: verify failed for procedure no.%d (cb=%d), %s\n", i, cb, aImportTab[i].achName));
1336 return (USHORT)(ERROR_D32_TOO_INVALID_PROLOG | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1337 }
1338 break;
1339
1340 case EPT_VARIMPORT:
1341 /* do nothing! */
1342 break;
1343
1344 default:
1345 kprintf(("VerifyImportTab32: invalid type/type not implemented. Proc no.%d, %s\n",i, aImportTab[i].achName));
1346 Int3(); /* temporary fix! */
1347 return (USHORT)(ERROR_D32_NOT_IMPLEMENTED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1348 }
1349 }
1350
1351 return NO_ERROR;
1352}
1353
1354
1355/**
1356 * Initiates the overrided functions.
1357 * @returns 16-bit errorcode where the high byte is the procedure number which
1358 * the error occured on and the low byte the error code.
1359 */
1360int importTabInit(void)
1361{
1362 int i;
1363 int cb;
1364 int cbmax;
1365 char * pchCTEntry; /* Pointer to current 32-bit calltab entry. */
1366 char * pchCTEntry16; /* Pointer to current 16-bit calltab entry. */
1367 ULONG flWP; /* CR0 WP flag restore value. */
1368
1369 /*
1370 * Apply build specific changes to the auFuncs table
1371 */
1372 if (options.ulBuild < 14053)
1373 {
1374 #ifdef DEBUG
1375 if (auFuncs[0] != (unsigned)myldrOpenPath)
1376 {
1377 kprintf(("importTabInit: ASSERTION FAILED auFuncs don't point at myldrOpenPath\n"));
1378 Int3();
1379 }
1380 #endif
1381 auFuncs[0] = (unsigned)myldrOpenPath_old;
1382 }
1383
1384#ifdef R3TST
1385 R3TstFixImportTab();
1386#endif
1387
1388 /*
1389 * verify proctable
1390 */
1391 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1392 {
1393 /* EPT_VARIMPORTs are skipped */
1394 if ((aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ)) == EPT_VARIMPORT)
1395 continue;
1396 /* EPT_NOT_REQ which is not found are set pointing to the nop function provided. */
1397 if (!aImportTab[i].fFound && EPTNotReq(aImportTab[i]))
1398 continue;
1399
1400 if (EPT32BitEntry(aImportTab[i]))
1401 {
1402 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1403
1404 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1405 }
1406 else
1407 {
1408 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1409 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1410 }
1411 if (cb <= 0 || cb > cbmax)
1412 {
1413 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1414 return ERROR_D32_VERIFY_FAILED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1415 }
1416 }
1417
1418 /*
1419 * rehook / import
1420 */
1421 pchCTEntry = &callTab[0];
1422 pchCTEntry16 = &callTab16[0];
1423 flWP = x86DisableWriteProtect();
1424 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1425 {
1426 switch (aImportTab[i].fType & ~EPT_WRAPPED)
1427 {
1428 /*
1429 * 32-bit procedure overload.
1430 * The overloading procedure is found in the auFuncs table (at the same index
1431 * as the overloaded procedure has in aImportTab).
1432 * The overloaded procedure is called by issuing a call to the callTab entry.
1433 */
1434 case EPT_PROC32:
1435 {
1436 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, TRUE);
1437 aImportTab[i].cbProlog = (char)cb;
1438 if (cb >= 5 && cb + 5 < OVERLOAD32_ENTRY) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1439 { /* 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. */
1440 /*
1441 * Copy function prolog which will be overwritten by the jmp to calltabl.
1442 */
1443 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1444
1445 /*
1446 * Make jump instruction which jumps from calltab to original function.
1447 * 0xE9 <four bytes displacement>
1448 * Note: the displacement is relative to the next instruction
1449 */
1450 pchCTEntry[cb] = 0xE9; /* jmp */
1451 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].ulAddress + cb - (unsigned long)&pchCTEntry[cb+5];
1452
1453 /*
1454 * Jump from original function to my function - an cli(?) could be needed here
1455 */
1456 *(char*)aImportTab[i].ulAddress = 0xE9; /* jmp */
1457 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i] - (aImportTab[i].ulAddress + 5);
1458 }
1459 else
1460 { /* !fatal! - this could never happen really... */
1461 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1462 Int3(); /* ipe - later! */
1463 x86RestoreWriteProtect(flWP);
1464 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1465 }
1466 pchCTEntry += OVERLOAD32_ENTRY;
1467 break;
1468 }
1469
1470
1471 /*
1472 * 16-bit procedure overload.
1473 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1474 */
1475 case EPT_PROC16:
1476 {
1477 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, TRUE);
1478 aImportTab[i].cbProlog = (char)cb;
1479 if (cb >= 5 && cb + 5 < OVERLOAD16_ENTRY) /* 5: size of a 16:16 jump which jumps to my overloading function */
1480 { /* cb+5: size of a 16:16 jump which is added to the call tab */
1481 /*
1482 * Copy function prolog which is to be overwritten.
1483 */
1484 memcpy(pchCTEntry16, (void*)aImportTab[i].ulAddress, (size_t)cb);
1485
1486 /*
1487 * Create far jump from calltab to original function.
1488 * 0xEA <two byte target address> <two byte target selector>
1489 */
1490 pchCTEntry16[cb] = 0xEA; /* jmp far ptr */
1491 *(unsigned short*)(void*)&pchCTEntry16[cb+1] = (unsigned short)aImportTab[i].offObject + cb;
1492 *(unsigned short*)(void*)&pchCTEntry16[cb+3] = aImportTab[i].usSel;
1493
1494 /*
1495 * We store the far 16:16 pointer to the function in the last four
1496 * bytes of the entry. Set them!
1497 */
1498 *(unsigned short*)(void*)&pchCTEntry16[OVERLOAD16_ENTRY-4] = (unsigned short)aImportTab[i].offObject;
1499 *(unsigned short*)(void*)&pchCTEntry16[OVERLOAD16_ENTRY-2] = aImportTab[i].usSel;
1500
1501 /*
1502 * jump from original function to my function - an cli(?) could be needed here
1503 * 0xEA <two byte target address> <two byte target selector>
1504 */
1505 *(char*)(aImportTab[i].ulAddress) = 0xEA; /* jmp far ptr */
1506 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i]; /* The auFuncs entry is a far pointer. */
1507 }
1508 else
1509 { /* !fatal! - this could never happen really... */
1510 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1511 Int3(); /* ipe - later! */
1512 x86RestoreWriteProtect(flWP);
1513 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1514 }
1515 pchCTEntry16 += OVERLOAD16_ENTRY;
1516 break;
1517 }
1518
1519
1520 /*
1521 * 32-bit imported procedure.
1522 * This is called by issuing a near call to the callTab entry.
1523 */
1524 case EPT_PROCIMPORTNR32: /* Not required */
1525 if (!(pchCTEntry[6] = aImportTab[i].fFound))
1526 aImportTab[i].ulAddress = auFuncs[i];
1527 case EPT_PROCIMPORT32:
1528 {
1529 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, FALSE);
1530 aImportTab[i].cbProlog = (char)cb;
1531 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1532 {
1533 /*
1534 * Make jump instruction which jumps from calltab to original function.
1535 * 0xE9 <four bytes displacement>
1536 * Note: the displacement is relative to the next instruction
1537 */
1538 pchCTEntry[0] = 0xE9; /* jmp */
1539 *(unsigned*)(void*)&pchCTEntry[1] = aImportTab[i].ulAddress - (unsigned)&pchCTEntry[5];
1540 }
1541 else
1542 { /* !fatal! - this should never really happen... */
1543 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1544 Int3(); /* ipe - later! */
1545 x86RestoreWriteProtect(flWP);
1546 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1547 }
1548 pchCTEntry += IMPORT32_ENTRY;
1549 break;
1550 }
1551
1552
1553 /*
1554 * 16-bit imported procedure.
1555 * This is called by issuing a far call to the calltab entry.
1556 */
1557 case EPT_PROCIMPORTNR16: /* Not required */
1558 if (!(pchCTEntry[7] = aImportTab[i].fFound))
1559 {
1560 aImportTab[i].ulAddress = auFuncs[i];
1561 Int3();
1562 break;
1563 }
1564 case EPT_PROCIMPORT16:
1565 {
1566 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1567 aImportTab[i].cbProlog = (char)cb;
1568 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1569 {
1570 /*
1571 * Create far jump from calltab to original function.
1572 * 0xEA <four byte target address> <two byte target selector>
1573 */
1574 pchCTEntry[0] = 0xEA; /* jmp far ptr */
1575 *(unsigned long*)(void*)&pchCTEntry[1] = aImportTab[i].offObject;
1576 *(unsigned short*)(void*)&pchCTEntry[5] = aImportTab[i].usSel;
1577 }
1578 else
1579 { /* !fatal! - this should never really happen... */
1580 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1581 Int3(); /* ipe - later! */
1582 x86RestoreWriteProtect(flWP);
1583 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1584 }
1585 pchCTEntry += IMPORT16_ENTRY;
1586 break;
1587 }
1588
1589
1590 /*
1591 * 16-bit imported hybrid procedure.
1592 * This is called by issuing a far call to the 16-bit calltab entry.
1593 */
1594 case EPT_PROCIMPORTH16:
1595 {
1596 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1597 aImportTab[i].cbProlog = (char)cb;
1598 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1599 {
1600 /*
1601 * Create far jump from calltab to original function.
1602 * 0xEA <four byte target address> <two byte target selector>
1603 */
1604 pchCTEntry16[0] = 0xEA; /* jmp far ptr */
1605 *(unsigned short*)(void*)&pchCTEntry16[1] = aImportTab[i].offObject;
1606 *(unsigned short*)(void*)&pchCTEntry16[3] = aImportTab[i].usSel;
1607 }
1608 else
1609 { /* !fatal! - this should never really happen... */
1610 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1611 Int3(); /* ipe - later! */
1612 x86RestoreWriteProtect(flWP);
1613 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1614 }
1615 pchCTEntry16 += IMPORTH16_ENTRY;
1616 break;
1617 }
1618
1619
1620 /*
1621 * 16/32-bit importe variable.
1622 * This is used by accessing the 32-bit flat address in the callTab.
1623 * callTab-entry + 4 holds the offset of the variable into the object.
1624 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1625 * callTab-entry + a holds the 16-bit offset for the variable.
1626 * callTab-entry + c holds the selector for the object. (These two fields is the 16:16-bit pointer to the variable.)
1627 */
1628 case EPT_VARIMPORTNR32:
1629 case EPT_VARIMPORTNR16:
1630 if (!aImportTab[i].fFound)
1631 {
1632 memset(pchCTEntry, 0, VARIMPORT_ENTRY);
1633 pchCTEntry += VARIMPORT_ENTRY;
1634 break;
1635 }
1636 case EPT_VARIMPORT32:
1637 case EPT_VARIMPORT16:
1638 aImportTab[i].cbProlog = (char)0;
1639 *(unsigned long*)(void*)&pchCTEntry[0] = aImportTab[i].ulAddress;
1640 *(unsigned long*)(void*)&pchCTEntry[4] = aImportTab[i].offObject;
1641 *(unsigned short*)(void*)&pchCTEntry[8] = aImportTab[i].usSel;
1642 *(unsigned short*)(void*)&pchCTEntry[0xa] = (unsigned short)aImportTab[i].offObject;
1643 *(unsigned short*)(void*)&pchCTEntry[0xc] = aImportTab[i].usSel;
1644 pchCTEntry += VARIMPORT_ENTRY;
1645 break;
1646
1647 default:
1648 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1649 Int3(); /* ipe - later! */
1650 x86RestoreWriteProtect(flWP);
1651 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1652 } /* switch - type */
1653 } /* for */
1654
1655 x86RestoreWriteProtect(flWP);
1656
1657 return NO_ERROR;
1658}
1659
1660
1661#ifdef R3TST
1662/**
1663 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1664 * @returns Pointer to the fake kernel MTE.
1665 * @status completely implemented.
1666 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1667 */
1668PMTE GetOS2KrnlMTETst(void)
1669{
1670 static MTE KrnlMTE;
1671 static SMTE KrnlSMTE;
1672
1673 KrnlMTE.mte_swapmte = &KrnlSMTE;
1674 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1675 KrnlSMTE.smte_objcnt = cObjectsFake;
1676
1677 return &KrnlMTE;
1678}
1679
1680/**
1681 * -Ring-3 testing-
1682 * Changes the entries in aImportTab to point to their fake equivalents.
1683 * @returns void
1684 * @param void
1685 * @status completely implemented.
1686 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1687 * @remark Called before the aImportTab array is used/verified.
1688 */
1689VOID R3TstFixImportTab(VOID)
1690{
1691 int i;
1692
1693 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1694 {
1695 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1696 {
1697 case EPT_PROC32:
1698 if (aTstFakers[i].fObj != 1)
1699 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1700 break;
1701 case EPT_PROCIMPORT32:
1702 if (aTstFakers[i].fObj != 1)
1703 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1704 break;
1705 case EPT_PROCIMPORT16:
1706 if (aTstFakers[i].fObj != 2)
1707 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1708 break;
1709 case EPT_VARIMPORT32:
1710 case EPT_VARIMPORT16:
1711 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1712 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1713 break;
1714 } /* switch - type */
1715
1716 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1717 switch (aTstFakers[i].fObj)
1718 {
1719 case 1:
1720 aImportTab[i].usSel = GetSelectorCODE32();
1721 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1722 break;
1723 case 2:
1724 aImportTab[i].usSel = GetSelectorCODE16();
1725 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1726 break;
1727 case 3:
1728 aImportTab[i].usSel = GetSelectorDATA32();
1729 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1730 break;
1731 case 4:
1732 aImportTab[i].usSel = GetSelectorDATA16();
1733 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1734 break;
1735 default:
1736 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1737 }
1738 } /* for */
1739}
1740#endif
1741
1742/**
1743 * Dummy nop function if SecPathFromSFN isn't found.
1744 */
1745PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1746{
1747 NOREF(hFile);
1748 return NULL;
1749}
Note: See TracBrowser for help on using the repository browser.