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

Last change on this file since 9473 was 9473, checked in by bird, 23 years ago

Workaround weird compiler behaviour.

File size: 68.0 KB
Line 
1/* $Id: d32init.c,v 1.43 2002-12-06 02:57:49 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(a)
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
760 /*
761 * Something else must be wrong, but this is where we crash.
762 * TODO: make a real fix for this!
763 */
764 if ((unsigned)pach >= 0xffff0000 || (unsigned)pach <= 0x10000)
765 {
766 kprintf(("interpretFunctionProlog32: Bad address! pach=0x%08x\n", pach));
767 return 0;
768 }
769 kprintf2(("interpretFunctionProlog32(0x%08x, %d):\n"
770 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
771 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
772 pach, fOverload,
773 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
774 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
775
776 /*
777 * check for the well known prolog (the only that is supported now)
778 * which is:
779 * push ebp
780 * mov ebp,esp
781 * or
782 * push ebp
783 * mov eax, dword ptr [xxxxxxxx]
784 * or
785 * sub esp, imm8
786 * push ebx
787 * push edi
788 *
789 * These are allowed when not overloading:
790 * mov eax, imm32
791 * jmp short
792 * or
793 * mov eax, imm32
794 * push ebp
795 * or
796 * mov ecx, r/m32
797 * or
798 * jmp dword
799 * or
800 * sub esp, imm8
801 * or
802 * call ptr16:32
803 * or
804 * enter imm16, imm8 (2.1x)
805 * or
806 * mov eax, imm32 (2.1x)
807 * <anything>
808 * or
809 * xor r32, r/m32
810 * or
811 * mov eax, msoff32
812 * or
813 * push edi
814 * mov eax, dword ptr [xxxxxxxx]
815 * or
816 * movzx esp, sp
817 * or
818 * call rel32
819 * popf
820 */
821 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* the two first prologs */
822 ||
823 (pach[0] == 0x83 && pach[3] == 0x53 && pach[4] == 0x57) /* the third prolog */
824 ||
825 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55) && !fOverload) /* the two next prologs */
826 ||
827 (pach[0] == 0x8B && !fOverload) /* the next prolog */
828 ||
829 (pach[0] == 0xFF && !fOverload) /* the next prolog */
830 ||
831 (pach[0] == 0x83 && !fOverload) /* the next prolog */
832 ||
833 (pach[0] == 0x9a && !fOverload) /* the next prolog */
834 ||
835 (pach[0] == 0xc8) /* the next prolog */
836 ||
837 (pach[0] == 0xB8 && !fOverload) /* the next prolog */
838 ||
839 (pach[0] == 0x33 && !fOverload) /* the next prolog */
840 ||
841 (pach[0] == 0xa1 && !fOverload) /* the next prolog */
842 ||
843 (pach[0] == 0x57 && pach[1] == 0x8b && !fOverload) /* the next prolog */
844 ||
845 (pach[0] == 0x0f && pach[1] == 0xb7 && pach[2] == 0xe4 && !fOverload) /* the next prolog */
846 ||
847 (pach[0] == 0xe8 && pach[5] == 0x9d && !fOverload) /* the next prolog */
848 /* push ebx
849 * push edi
850 * push imm32
851 */
852 || (pach[0] == 0x53 && pach[1] == 0x57 && pach[2] == 0x68 && !fOverload)
853 /* push ebx
854 * push edi
855 * push esi
856 * mov /r
857 */
858 || (pach[0] == 0x53 && pach[1] == 0xe8 && !fOverload)
859 /* push ebx
860 * push edi
861 * push esi
862 * mov /r
863 */
864 || (pach[0] == 0x53 && pach[1] == 0x57 && pach[2] == 0x56 && pach[3] == 0x8b && !fOverload)
865 /* pop eax
866 * push imm8
867 * push eax
868 * jmp imm32
869 */
870 || (pach[0] == 0x58 && pach[1] == 0x6a && pach[3] == 0x50 && pach[4] == 0xe9 && !fOverload)
871 /* push imm32
872 * call imm32
873 */
874 || (pach[0] == 0x68 && pach[5] == 0xe8 && !fOverload)
875 )
876 {
877 BOOL fForce = FALSE;
878 int cbWord = 4;
879 cb = 0;
880 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
881 {
882 int cb2;
883 if (!fForce && cbWord != 4)
884 cbWord = 4;
885 fForce = FALSE;
886 switch (*pach)
887 {
888 case 0x0f:
889 if (pach[1] != 0xb7 && pach[2] != 0xe4) /* movzx esp, sp */
890 {
891 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
892 return -11;
893 }
894 pach += 2;
895 cb += 2;
896 break;
897
898
899 /* simple one byte prefixes */
900 case 0x2e: /* cs segment override */
901 case 0x36: /* ss segment override */
902 case 0x3e: /* ds segment override */
903 case 0x26: /* es segment override */
904 case 0x64: /* fs segment override */
905 case 0x65: /* gs segment override */
906 fForce = TRUE;
907 break;
908
909 case 0x66: /* 16 bit */
910 fForce = TRUE;
911 cbWord = 2;
912 break;
913
914 /* simple one byte instructions e*/
915 case 0x50: /* push eax */
916 case 0x51: /* push ecx */
917 case 0x52: /* push edx */
918 case 0x53: /* push ebx */
919 case 0x54: /* push esp */
920 case 0x55: /* push ebp */
921 case 0x56: /* push esi */
922 case 0x57: /* push edi */
923 case 0x58: /* pop eax */
924 case 0x59: /* pop ecx */
925 case 0x5a: /* pop edx */
926 case 0x5b: /* pop ebx */
927 case 0x06: /* push es */
928 case 0x0e: /* push cs */
929 case 0x1e: /* push ds */
930 case 0x16: /* push ss */
931 break;
932
933 /* simple two byte instructions */
934 case 0xb0: /* mov al, imm8 */
935 case 0xb1: /* mov cl, imm8 */
936 case 0xb2: /* mov dl, imm8 */
937 case 0xb3: /* mov bl, imm8 */
938 case 0xb4: /* mov ah, imm8 */
939 case 0xb5: /* mov ch, imm8 */
940 case 0xb6: /* mov dh, imm8 */
941 case 0xb7: /* mov bh, imm8 */
942 case 0x2c: /* sub al, imm8 */
943 case 0x34: /* xor al, imm8 */
944 case 0x3c: /* cmp al, imm8 */
945 case 0x6a: /* push <byte> */
946 case 0xa0: /* mov al, moffs8 */
947 case 0xa2: /* mov moffs8, al */
948 pach++;
949 cb++;
950 break;
951
952 /* simple five byte instructions */
953 case 0xb8: /* mov eax, imm32 */
954 case 0xb9: /* mov ecx, imm32 */
955 case 0xba: /* mov edx, imm32 */
956 case 0xbb: /* mov ebx, imm32 */
957 case 0xbc: /* mov esx, imm32 */
958 case 0xbd: /* mov ebx, imm32 */
959 case 0xbe: /* mov esi, imm32 */
960 case 0xbf: /* mov edi, imm32 */
961 case 0xe9: /* jmp rel32 */
962 case 0x2d: /* sub eax, imm32 */
963 case 0x35: /* xor eax, imm32 */
964 case 0x3d: /* cmp eax, imm32 */
965 case 0x68: /* push <dword> */
966 case 0xa1: /* mov eax, moffs16 */
967 case 0xa3: /* mov moffs16, eax */
968 pach += cbWord;
969 cb += cbWord;
970 break;
971
972 /* fixed five byte instructions */
973 case 0xe8: /* call imm32 */
974 pach += 4;
975 cb += 4;
976 break;
977
978 /* complex sized instructions - "/r" */
979 case 0x30: /* xor r/m8, r8 */
980 case 0x31: /* xor r/m32, r32 */
981 case 0x32: /* xor r8, r/m8 */
982 case 0x33: /* xor r32, r/m32 */
983 case 0x38: /* cmp r/m8, r8 */
984 case 0x39: /* cmp r/m32, r32 */
985 case 0x3a: /* cmp r8, r/m8 */
986 case 0x3b: /* cmp r32, r/m32 */
987 case 0x28: /* sub r/m8, r8 */
988 case 0x29: /* sub r/m32, r32 */
989 case 0x2a: /* sub r8, r/m8 */
990 case 0x2b: /* sub r32, r/m32 */
991 case 0x8b: /* mov /r */
992 case 0x8d: /* lea /r */
993 cb += cb2 = ModR_M_32bit(pach[1]);
994 pach += cb2;
995 break;
996
997 /* complex sized instruction - "/5 ib" */
998 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
999 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
1000 if ((pach[1] & 0x38) == (5<<3)
1001 || (pach[1] & 0x38) == (7<<3)
1002 )
1003 {
1004 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
1005 pach += cb2;
1006 }
1007 else
1008 {
1009 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1010 return -3;
1011 }
1012 break;
1013
1014 /* complex sized instruction - "/digit id" */
1015 case 0x81: /* sub r/m32, imm32 + more instructions! */
1016 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
1017 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
1018 )
1019 {
1020 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
1021 pach += cb2;
1022 }
1023 else
1024 {
1025 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1026 return -2;
1027 }
1028 break;
1029
1030 case 0x9a: /* call ptr16:32 */
1031 cb += cb2 = 6;
1032 pach += cb2;
1033 break;
1034
1035 case 0xc8: /* enter imm16, imm8 */
1036 cb += cb = 3;
1037 pach += cb2;
1038 break;
1039
1040 /*
1041 * jmp /digit
1042 */
1043 case 0xff:
1044 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
1045 pach += cb2;
1046 break;
1047
1048 default:
1049 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1050 return 0;
1051 }
1052 pach++;
1053 cb++;
1054 }
1055 }
1056 else
1057 {
1058 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1059 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5]));
1060 cb = 0;
1061 }
1062 return cb;
1063}
1064
1065
1066/**
1067 * 16-bit! Interpret function prolog to find where to jmp back.
1068 * @returns Length of prolog need to be copied - which is also the offset of
1069 * where the jmp instr should be placed.
1070 * On error it returns 0.
1071 * @param pach Pointer to prolog.
1072 * @param fOverload TRUE: Function is to be overloaded.
1073 * FALSE: Function is to be imported.
1074 */
1075int interpretFunctionProlog16(char *pach, BOOL fOverload)
1076{
1077 int cb = -7;
1078
1079 kprintf2(("interpretFunctionProlog16(0x%08x, %d):\n"
1080 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
1081 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
1082 pach, fOverload,
1083 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
1084 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
1085 /*
1086 * Check for the well known prolog (the only that is supported now)
1087 * which is:
1088 */
1089 if ((*pach == 0x6A && !fOverload) /* push 2 (don't check for the 2) */
1090 ||
1091 *pach == 0x60 /* pushf */
1092 ||
1093 (*pach == 0x53 && pach[1] == 0x51) /* push bx, push cx */
1094 ||
1095 (*pach == 0x8c && pach[1] == 0xd8) /* mov ax, ds */
1096 ||
1097 (*pach == 0xb8) /* mov ax, imm16 */
1098 )
1099 {
1100 BOOL fForce;
1101 int cOpPrefix = 0;
1102 cb = 0;
1103 while (cb < 5 || fForce) /* 5 is the size of a 16:16 far jump instruction. */
1104 {
1105 int cb2;
1106 fForce = FALSE;
1107 switch (*pach)
1108 {
1109 case 0x06: /* push es */
1110 case 0x0e: /* push cs */
1111 case 0x1e: /* push ds */
1112 case 0x16: /* push ss */
1113 break;
1114
1115 case 0x0f: /* push gs and push fs */
1116 if (pach[1] != 0xA0 && pach[1] != 0xA8)
1117 {
1118 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1119 return -11;
1120 }
1121 pach++;
1122 cb++;
1123 break;
1124
1125 case 0x50: /* push ax */
1126 case 0x51: /* push cx */
1127 case 0x52: /* push dx */
1128 case 0x53: /* push bx */
1129 case 0x54: /* push sp */
1130 case 0x55: /* push bp */
1131 case 0x56: /* push si */
1132 case 0x57: /* push di */
1133 case 0x60: /* pusha */
1134 break;
1135
1136 /* simple three byte instructions */
1137 case 0xb8: /* mov eax, imm16 */
1138 case 0xb9: /* mov ecx, imm16 */
1139 case 0xba: /* mov edx, imm16 */
1140 case 0xbb: /* mov ebx, imm16 */
1141 case 0xbc: /* mov esx, imm16 */
1142 case 0xbd: /* mov ebx, imm16 */
1143 case 0xbe: /* mov esi, imm16 */
1144 case 0xbf: /* mov edi, imm16 */
1145 case 0x2d: /* sub eax, imm16 */
1146 case 0x35: /* xor eax, imm16 */
1147 case 0x3d: /* cmp eax, imm16 */
1148 case 0x68: /* push <dword> */
1149 case 0xa1: /* mov eax, moffs16 */
1150 case 0xa3: /* mov moffs16, eax */
1151 if (cOpPrefix > 0) /* FIXME see 32-bit interpreter. */
1152 {
1153 pach += 2;
1154 cb += 2;
1155 }
1156 pach += 2;
1157 cb += 2;
1158 break;
1159
1160 case 0x2e: /* cs segment override */
1161 case 0x36: /* ss segment override */
1162 case 0x3e: /* ds segment override */
1163 case 0x26: /* es segment override */
1164 case 0x64: /* fs segment override */
1165 case 0x65: /* gs segment override */
1166 fForce = TRUE;
1167 if (cOpPrefix > 0)
1168 cOpPrefix++;
1169 break;
1170
1171 case 0x66:
1172 cOpPrefix = 2; /* it's decremented once before it's used. */
1173 fForce = TRUE;
1174 break;
1175
1176 case 0x6a: /* push <byte> */
1177 case 0x3c: /* mov al, imm8 */
1178 pach++;
1179 cb++;
1180 break;
1181
1182 case 0x8b: /* mov /r */
1183 case 0x8c: /* mov r/m16,Sreg (= mov /r) */
1184 case 0x8e: /* mov Sreg, r/m16 (= mov /r) */
1185 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
1186 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
1187 { /* 16-bit displacement */
1188 if (cOpPrefix > 0)
1189 {
1190 pach += 2;
1191 cb += 2;
1192 }
1193 pach += 3;
1194 cb += 3;
1195 }
1196 else
1197 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
1198 { /* 8-bit displacement */
1199 pach += 2;
1200 cb += 2;
1201 }
1202 else
1203 { /* no displacement (only /r byte) */
1204 pach++;
1205 cb++;
1206 }
1207 break;
1208
1209 /* complex sized instruction - "/5 ib" */
1210 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
1211 case 0x83: /* 5: sub r/m16, imm8 7: cmp r/m16, imm8 */
1212 if ((pach[1] & 0x38) == (5<<3)
1213 || (pach[1] & 0x38) == (7<<3)
1214 )
1215 {
1216 cb += cb2 = 1 + ModR_M_16bit(pach[1]); /* 1 is the size of the imm8 */
1217 pach += cb2;
1218 }
1219 else
1220 {
1221 kprintf(("interpretFunctionProlog16: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1222 return -3;
1223 }
1224 break;
1225
1226 case 0x9a: /* call ptr16:16 */
1227 cb += cb2 = 4;
1228 pach += cb2;
1229 break;
1230
1231 default:
1232 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1233 return 0;
1234 }
1235 pach++;
1236 cb++;
1237 if (cOpPrefix > 0)
1238 cOpPrefix--;
1239 }
1240 }
1241 else
1242 kprintf(("interpretFunctionProlog16: unknown prolog 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1243
1244
1245 fOverload = fOverload;
1246 return cb;
1247}
1248
1249
1250/**
1251 * Verifies the aImportTab.
1252 * @returns 16-bit errorcode where the high byte is the procedure number which
1253 * the error occured on and the low byte the error code.
1254 * @remark Called from IOCtl.
1255 * WARNING! This function is called before the initroutine (R0INIT)!
1256 */
1257USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
1258{
1259 USHORT usRc;
1260 int i;
1261 int cb;
1262 int cbmax;
1263
1264 /* VerifyImporTab32 is called before the initroutine! */
1265 pulTKSSBase32 = (PULONG)_TKSSBase16;
1266
1267 /* Check that pKrnlOTE is set */
1268 usRc = GetKernelInfo32(NULL);
1269 if (usRc != NO_ERROR)
1270 return usRc;
1271
1272 /*
1273 * Verify aImportTab.
1274 */
1275 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1276 {
1277 /*
1278 * Debug info
1279 */
1280 kprintf2(("VerifyImportTab32: procedure no.%d is being checked: %s addr=0x%08x iObj=%d offObj=%d\n",
1281 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1282 aImportTab[i].iObject, aImportTab[i].offObject));
1283
1284 /* Verify that it is found */
1285 if (!aImportTab[i].fFound)
1286 {
1287 if (EPTNotReq(aImportTab[i]))
1288 continue;
1289 else
1290 {
1291 kprintf(("VerifyImportTab32: procedure no.%d was not fFound!\n", i));
1292 return (USHORT)(ERROR_D32_PROC_NOT_FOUND | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1293 }
1294 }
1295
1296 /* Verify read/writeable. */
1297 if ( aImportTab[i].iObject >= pKrnlSMTE->smte_objcnt /* object index valid? */
1298 || aImportTab[i].ulAddress < pKrnlOTE[aImportTab[i].iObject].ote_base /* address valid? */
1299 || aImportTab[i].ulAddress + 16 > (pKrnlOTE[aImportTab[i].iObject].ote_base +
1300 pKrnlOTE[aImportTab[i].iObject].ote_size) /* address valid? */
1301 || aImportTab[i].ulAddress - aImportTab[i].offObject
1302 != pKrnlOTE[aImportTab[i].iObject].ote_base /* offObject ok? */
1303 )
1304 {
1305 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address or object number.!\n"
1306 " %s addr=0x%08x iObj=%d offObj=%d\n",
1307 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1308 aImportTab[i].iObject, aImportTab[i].offObject));
1309 return (USHORT)(ERROR_D32_INVALID_OBJ_OR_ADDR | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1310 }
1311
1312
1313 #ifndef R3TST
1314 if (aImportTab[i].ulAddress < 0xff400000UL)
1315 {
1316 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address, %#08x!\n",
1317 i, aImportTab[i].ulAddress));
1318 return (USHORT)(ERROR_D32_INVALID_ADDRESS | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1319 }
1320 #endif
1321
1322 switch (aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ | EPT_WRAPPED | EPT_PROCIMPORTH))
1323 {
1324 case EPT_PROC:
1325 case EPT_PROCIMPORT:
1326 /*
1327 * Verify known function prolog.
1328 */
1329 if (EPT32BitEntry(aImportTab[i]))
1330 {
1331 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1332 cbmax = OVERLOAD32_ENTRY - 5; /* 5 = Size of the jump instruction */
1333 }
1334 else
1335 {
1336 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1337 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1338 }
1339
1340 /*
1341 * Check result of the function prolog interpretations.
1342 */
1343 if (cb <= 0 || cb > cbmax)
1344 { /* failed, too small or too large. */
1345 kprintf(("VerifyImportTab32/16: verify failed for procedure no.%d (cb=%d), %s\n", i, cb, aImportTab[i].achName));
1346 return (USHORT)(ERROR_D32_TOO_INVALID_PROLOG | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1347 }
1348 break;
1349
1350 case EPT_VARIMPORT:
1351 /* do nothing! */
1352 break;
1353
1354 default:
1355 kprintf(("VerifyImportTab32: invalid type/type not implemented. Proc no.%d, %s\n",i, aImportTab[i].achName));
1356 Int3(); /* temporary fix! */
1357 return (USHORT)(ERROR_D32_NOT_IMPLEMENTED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1358 }
1359 }
1360
1361 return NO_ERROR;
1362}
1363
1364
1365/**
1366 * Initiates the overrided functions.
1367 * @returns 16-bit errorcode where the high byte is the procedure number which
1368 * the error occured on and the low byte the error code.
1369 */
1370int importTabInit(void)
1371{
1372 int i;
1373 int cb;
1374 int cbmax;
1375 char * pchCTEntry; /* Pointer to current 32-bit calltab entry. */
1376 char * pchCTEntry16; /* Pointer to current 16-bit calltab entry. */
1377 ULONG flWP; /* CR0 WP flag restore value. */
1378
1379 /*
1380 * Apply build specific changes to the auFuncs table
1381 */
1382 if (options.ulBuild < 14053)
1383 {
1384 #ifdef DEBUG
1385 if (auFuncs[0] != (unsigned)myldrOpenPath)
1386 {
1387 kprintf(("importTabInit: ASSERTION FAILED auFuncs don't point at myldrOpenPath\n"));
1388 Int3();
1389 }
1390 #endif
1391 auFuncs[0] = (unsigned)myldrOpenPath_old;
1392 }
1393
1394#ifdef R3TST
1395 R3TstFixImportTab();
1396#endif
1397
1398 /*
1399 * verify proctable
1400 */
1401 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1402 {
1403 /* EPT_VARIMPORTs are skipped */
1404 if ((aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ)) == EPT_VARIMPORT)
1405 continue;
1406 /* EPT_NOT_REQ which is not found are set pointing to the nop function provided. */
1407 if (!aImportTab[i].fFound && EPTNotReq(aImportTab[i]))
1408 continue;
1409
1410 if (EPT32BitEntry(aImportTab[i]))
1411 {
1412 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1413
1414 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1415 }
1416 else
1417 {
1418 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1419 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1420 }
1421 if (cb <= 0 || cb > cbmax)
1422 {
1423 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1424 return ERROR_D32_VERIFY_FAILED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1425 }
1426 }
1427
1428 /*
1429 * rehook / import
1430 */
1431 pchCTEntry = &callTab[0];
1432 pchCTEntry16 = &callTab16[0];
1433 flWP = x86DisableWriteProtect();
1434 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1435 {
1436 switch (aImportTab[i].fType & ~EPT_WRAPPED)
1437 {
1438 /*
1439 * 32-bit procedure overload.
1440 * The overloading procedure is found in the auFuncs table (at the same index
1441 * as the overloaded procedure has in aImportTab).
1442 * The overloaded procedure is called by issuing a call to the callTab entry.
1443 */
1444 case EPT_PROC32:
1445 {
1446 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, TRUE);
1447 aImportTab[i].cbProlog = (char)cb;
1448 if (cb >= 5 && cb + 5 < OVERLOAD32_ENTRY) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1449 { /* 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. */
1450 /*
1451 * Copy function prolog which will be overwritten by the jmp to calltabl.
1452 */
1453 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1454
1455 /*
1456 * Make jump instruction which jumps from calltab to original function.
1457 * 0xE9 <four bytes displacement>
1458 * Note: the displacement is relative to the next instruction
1459 */
1460 pchCTEntry[cb] = 0xE9; /* jmp */
1461 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].ulAddress + cb - (unsigned long)&pchCTEntry[cb+5];
1462
1463 /*
1464 * Jump from original function to my function - an cli(?) could be needed here
1465 */
1466 *(char*)aImportTab[i].ulAddress = 0xE9; /* jmp */
1467 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i] - (aImportTab[i].ulAddress + 5);
1468 }
1469 else
1470 { /* !fatal! - this could never happen really... */
1471 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1472 Int3(); /* ipe - later! */
1473 x86RestoreWriteProtect(flWP);
1474 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1475 }
1476 pchCTEntry += OVERLOAD32_ENTRY;
1477 break;
1478 }
1479
1480
1481 /*
1482 * 16-bit procedure overload.
1483 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1484 */
1485 case EPT_PROC16:
1486 {
1487 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, TRUE);
1488 aImportTab[i].cbProlog = (char)cb;
1489 if (cb >= 5 && cb + 5 < OVERLOAD16_ENTRY) /* 5: size of a 16:16 jump which jumps to my overloading function */
1490 { /* cb+5: size of a 16:16 jump which is added to the call tab */
1491 /*
1492 * Copy function prolog which is to be overwritten.
1493 */
1494 memcpy(pchCTEntry16, (void*)aImportTab[i].ulAddress, (size_t)cb);
1495
1496 /*
1497 * Create far jump from calltab to original function.
1498 * 0xEA <two byte target address> <two byte target selector>
1499 */
1500 pchCTEntry16[cb] = 0xEA; /* jmp far ptr */
1501 *(unsigned short*)(void*)&pchCTEntry16[cb+1] = (unsigned short)aImportTab[i].offObject + cb;
1502 *(unsigned short*)(void*)&pchCTEntry16[cb+3] = aImportTab[i].usSel;
1503
1504 /*
1505 * We store the far 16:16 pointer to the function in the last four
1506 * bytes of the entry. Set them!
1507 */
1508 *(unsigned short*)(void*)&pchCTEntry16[OVERLOAD16_ENTRY-4] = (unsigned short)aImportTab[i].offObject;
1509 *(unsigned short*)(void*)&pchCTEntry16[OVERLOAD16_ENTRY-2] = aImportTab[i].usSel;
1510
1511 /*
1512 * jump from original function to my function - an cli(?) could be needed here
1513 * 0xEA <two byte target address> <two byte target selector>
1514 */
1515 *(char*)(aImportTab[i].ulAddress) = 0xEA; /* jmp far ptr */
1516 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i]; /* The auFuncs entry is a far pointer. */
1517 }
1518 else
1519 { /* !fatal! - this could never happen really... */
1520 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1521 Int3(); /* ipe - later! */
1522 x86RestoreWriteProtect(flWP);
1523 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1524 }
1525 pchCTEntry16 += OVERLOAD16_ENTRY;
1526 break;
1527 }
1528
1529
1530 /*
1531 * 32-bit imported procedure.
1532 * This is called by issuing a near call to the callTab entry.
1533 */
1534 case EPT_PROCIMPORTNR32: /* Not required */
1535 if (!(pchCTEntry[6] = aImportTab[i].fFound))
1536 aImportTab[i].ulAddress = auFuncs[i];
1537 case EPT_PROCIMPORT32:
1538 {
1539 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, FALSE);
1540 aImportTab[i].cbProlog = (char)cb;
1541 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1542 {
1543 /*
1544 * Make jump instruction which jumps from calltab to original function.
1545 * 0xE9 <four bytes displacement>
1546 * Note: the displacement is relative to the next instruction
1547 */
1548 pchCTEntry[0] = 0xE9; /* jmp */
1549 *(unsigned*)(void*)&pchCTEntry[1] = aImportTab[i].ulAddress - (unsigned)&pchCTEntry[5];
1550 }
1551 else
1552 { /* !fatal! - this should never really happen... */
1553 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1554 Int3(); /* ipe - later! */
1555 x86RestoreWriteProtect(flWP);
1556 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1557 }
1558 pchCTEntry += IMPORT32_ENTRY;
1559 break;
1560 }
1561
1562
1563 /*
1564 * 16-bit imported procedure.
1565 * This is called by issuing a far call to the calltab entry.
1566 */
1567 case EPT_PROCIMPORTNR16: /* Not required */
1568 if (!(pchCTEntry[7] = aImportTab[i].fFound))
1569 {
1570 aImportTab[i].ulAddress = auFuncs[i];
1571 Int3();
1572 break;
1573 }
1574 case EPT_PROCIMPORT16:
1575 {
1576 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1577 aImportTab[i].cbProlog = (char)cb;
1578 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1579 {
1580 /*
1581 * Create far jump from calltab to original function.
1582 * 0xEA <four byte target address> <two byte target selector>
1583 */
1584 pchCTEntry[0] = 0xEA; /* jmp far ptr */
1585 *(unsigned long*)(void*)&pchCTEntry[1] = aImportTab[i].offObject;
1586 *(unsigned short*)(void*)&pchCTEntry[5] = aImportTab[i].usSel;
1587 }
1588 else
1589 { /* !fatal! - this should never really happen... */
1590 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1591 Int3(); /* ipe - later! */
1592 x86RestoreWriteProtect(flWP);
1593 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1594 }
1595 pchCTEntry += IMPORT16_ENTRY;
1596 break;
1597 }
1598
1599
1600 /*
1601 * 16-bit imported hybrid procedure.
1602 * This is called by issuing a far call to the 16-bit calltab entry.
1603 */
1604 case EPT_PROCIMPORTH16:
1605 {
1606 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1607 aImportTab[i].cbProlog = (char)cb;
1608 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1609 {
1610 /*
1611 * Create far jump from calltab to original function.
1612 * 0xEA <four byte target address> <two byte target selector>
1613 */
1614 pchCTEntry16[0] = 0xEA; /* jmp far ptr */
1615 *(unsigned short*)(void*)&pchCTEntry16[1] = aImportTab[i].offObject;
1616 *(unsigned short*)(void*)&pchCTEntry16[3] = aImportTab[i].usSel;
1617 }
1618 else
1619 { /* !fatal! - this should never really happen... */
1620 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1621 Int3(); /* ipe - later! */
1622 x86RestoreWriteProtect(flWP);
1623 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1624 }
1625 pchCTEntry16 += IMPORTH16_ENTRY;
1626 break;
1627 }
1628
1629
1630 /*
1631 * 16/32-bit importe variable.
1632 * This is used by accessing the 32-bit flat address in the callTab.
1633 * callTab-entry + 4 holds the offset of the variable into the object.
1634 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1635 * callTab-entry + a holds the 16-bit offset for the variable.
1636 * callTab-entry + c holds the selector for the object. (These two fields is the 16:16-bit pointer to the variable.)
1637 */
1638 case EPT_VARIMPORTNR32:
1639 case EPT_VARIMPORTNR16:
1640 if (!aImportTab[i].fFound)
1641 {
1642 memset(pchCTEntry, 0, VARIMPORT_ENTRY);
1643 pchCTEntry += VARIMPORT_ENTRY;
1644 break;
1645 }
1646 case EPT_VARIMPORT32:
1647 case EPT_VARIMPORT16:
1648 aImportTab[i].cbProlog = (char)0;
1649 *(unsigned long*)(void*)&pchCTEntry[0] = aImportTab[i].ulAddress;
1650 *(unsigned long*)(void*)&pchCTEntry[4] = aImportTab[i].offObject;
1651 *(unsigned short*)(void*)&pchCTEntry[8] = aImportTab[i].usSel;
1652 *(unsigned short*)(void*)&pchCTEntry[0xa] = (unsigned short)aImportTab[i].offObject;
1653 *(unsigned short*)(void*)&pchCTEntry[0xc] = aImportTab[i].usSel;
1654 pchCTEntry += VARIMPORT_ENTRY;
1655 break;
1656
1657 default:
1658 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1659 Int3(); /* ipe - later! */
1660 x86RestoreWriteProtect(flWP);
1661 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1662 } /* switch - type */
1663 } /* for */
1664
1665 x86RestoreWriteProtect(flWP);
1666
1667 return NO_ERROR;
1668}
1669
1670
1671#ifdef R3TST
1672/**
1673 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1674 * @returns Pointer to the fake kernel MTE.
1675 * @status completely implemented.
1676 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1677 */
1678PMTE GetOS2KrnlMTETst(void)
1679{
1680 static MTE KrnlMTE;
1681 static SMTE KrnlSMTE;
1682
1683 KrnlMTE.mte_swapmte = &KrnlSMTE;
1684 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1685 KrnlSMTE.smte_objcnt = cObjectsFake;
1686
1687 return &KrnlMTE;
1688}
1689
1690/**
1691 * -Ring-3 testing-
1692 * Changes the entries in aImportTab to point to their fake equivalents.
1693 * @returns void
1694 * @param void
1695 * @status completely implemented.
1696 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1697 * @remark Called before the aImportTab array is used/verified.
1698 */
1699VOID R3TstFixImportTab(VOID)
1700{
1701 int i;
1702
1703 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1704 {
1705 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1706 {
1707 case EPT_PROC32:
1708 if (aTstFakers[i].fObj != 1)
1709 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1710 break;
1711 case EPT_PROCIMPORT32:
1712 if (aTstFakers[i].fObj != 1)
1713 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1714 break;
1715 case EPT_PROCIMPORT16:
1716 if (aTstFakers[i].fObj != 2)
1717 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1718 break;
1719 case EPT_VARIMPORT32:
1720 case EPT_VARIMPORT16:
1721 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1722 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1723 break;
1724 } /* switch - type */
1725
1726 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1727 switch (aTstFakers[i].fObj)
1728 {
1729 case 1:
1730 aImportTab[i].usSel = GetSelectorCODE32();
1731 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1732 break;
1733 case 2:
1734 aImportTab[i].usSel = GetSelectorCODE16();
1735 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1736 break;
1737 case 3:
1738 aImportTab[i].usSel = GetSelectorDATA32();
1739 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1740 break;
1741 case 4:
1742 aImportTab[i].usSel = GetSelectorDATA16();
1743 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1744 break;
1745 default:
1746 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1747 }
1748 } /* for */
1749}
1750#endif
1751
1752/**
1753 * Dummy nop function if SecPathFromSFN isn't found.
1754 */
1755PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1756{
1757 NOREF(hFile);
1758 return NULL;
1759}
Note: See TracBrowser for help on using the repository browser.