source: trunk/src/win32k/dev16/probkrnl.c@ 2827

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

g_tkExecPgm is overloaded, so we may change paramerters for a process later.

File size: 29.6 KB
Line 
1/* $Id: probkrnl.c,v 1.10 2000-02-19 08:40:29 bird Exp $
2 *
3 * Description: Autoprobes the os2krnl file and os2krnl[*].sym files.
4 * Another Hack!
5 *
6 * 16-bit inittime code.
7 *
8 * All data has to be initiated because this is 16-bit C code
9 * and is to be linked with 32-bit C/C++ code. Uninitiazlied
10 * data ends up in the BSS segment, and that segment can't
11 * both be 32-bit and 16-bit. I have not found any other way
12 * around this problem that initiating all data.
13 *
14 * How this works:
15 * 1. parses the device-line parameters and collects some "SysInfo".
16 * 2. gets the kernel object table. (elf$)
17 * 3. finds the kernel image and scans it for a build number.
18 * 4. locates and scans the symbol-file(s) for the entrypoints which are wanted.
19 * 5. the entry points are verified. (elf$)
20 * 6. finished.
21 *
22 * Copyright (c) 1998-2000 knut st. osmundsen
23 *
24 * Project Odin Software License can be found in LICENSE.TXT
25 *
26 */
27
28
29/*******************************************************************************
30* Defined Constants And Macros *
31*******************************************************************************/
32#ifdef DEBUGR3
33 #if 1
34 int printf(const char *, ...);
35 #define dprintf(a) printf a
36 #else
37 #define dprintf(a)
38 #endif
39#else
40 #define dprintf(a)
41 #define static
42#endif
43
44#define fclose(a) DosClose(a)
45#define SEEK_SET FILE_BEGIN
46#define SEEK_END FILE_END
47
48#define WORD unsigned short int
49#define DWORD unsigned long int
50
51/* "@#IBM:14.039#@ os2krnl... "*/
52/* "@#IBM:8.264#@ os2krnl... "*/
53#define KERNEL_ID_STRING_LENGTH 42
54#define KERNEL_READ_SIZE 512
55
56#define INCL_BASE
57#define INCL_DOS
58
59
60/*******************************************************************************
61* Header Files *
62*******************************************************************************/
63#include <os2.h>
64
65#include <exe386.h>
66#include <strat2.h>
67#include <reqpkt.h>
68
69#include "os2krnl.h" /* must be included before dev1632.h! */
70#include "sym.h"
71#include "probkrnl.h"
72#include "dev16.h"
73#include "dev1632.h"
74
75
76/*******************************************************************************
77* Global Variables *
78* Note: must be inited or else we'll get BSS segment *
79*******************************************************************************/
80/*
81 * kernel data - !only valid during init!
82 */
83
84/*
85 * aProcTab defines the imported and overloaded OS/2 kernel functions.
86 * IMPORTANT: aProcTab has a sibling array in d32init.c, aulProc, which must
87 * match entry by entry. Adding/removing/shuffling aProcTab, aulProc
88 * has to be updated immediately!
89 */
90PROCS aProcTab[NUMBER_OF_PROCS] =
91{/* iFound cchName offObject fType */
92 /* iObject achName ulAddress */
93 {FALSE, -1, 8, "_ldrRead", -1, -1, EPT_PROC}, /* 0 */
94 {FALSE, -1, 8, "_ldrOpen", -1, -1, EPT_PROC}, /* 1 */
95 {FALSE, -1, 9, "_ldrClose", -1, -1, EPT_PROC}, /* 2 */
96 {FALSE, -1, 12, "_LDRQAppType", -1, -1, EPT_PROCIMPORT}, /* 3 */ /* to be removed? */
97 {FALSE, -1, 20, "_ldrEnum32bitRelRecs", -1, -1, EPT_PROC}, /* 4 */
98 {FALSE, -1, 10, "_IOSftOpen", -1, -1, EPT_PROCIMPORT}, /* 5 */
99 {FALSE, -1, 11, "_IOSftClose", -1, -1, EPT_PROCIMPORT}, /* 6 */
100 {FALSE, -1, 15, "_IOSftTransPath", -1, -1, EPT_PROCIMPORT}, /* 7 */
101 {FALSE, -1, 12, "_IOSftReadAt", -1, -1, EPT_PROCIMPORT}, /* 8 */
102 {FALSE, -1, 13, "_IOSftWriteAt", -1, -1, EPT_PROCIMPORT}, /* 9 */
103 {FALSE, -1, 12, "_SftFileSize", -1, -1, EPT_PROCIMPORT}, /* 10 */
104 {FALSE, -1, 11, "_VMAllocMem", -1, -1, EPT_PROCIMPORT}, /* 11 */
105 {FALSE, -1, 11, "_VMGetOwner", -1, -1, EPT_PROCIMPORT}, /* 12 */
106 {FALSE, -1, 11, "g_tkExecPgm", -1, -1, EPT_PROC} /* 13 */
107};
108
109unsigned long int ulBuild = 0;
110unsigned short usVerMajor = 0;
111unsigned short usVerMinor = 0;
112
113
114/*
115 * privat data
116 */
117static int fQuiet = 0;
118static char szUsrOS2Krnl[50] = {0};
119static char szOS2Krnl[] = {"c:\\os2krnl"};
120
121static char szUsrSym[50] = {0};
122static char * apszSym[] =
123{
124 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
125 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
126 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
127 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
128 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
129 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
130 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
131 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
132 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
133 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
134 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
135 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
136 {"c:\\os2krnlr.sym"}, /* custom */
137 {"c:\\os2krnlh.sym"}, /* custom */
138 {"c:\\os2krnld.sym"}, /* custom */
139 NULL
140};
141
142static KRNLOBJTABLE KrnlOTEs = {0};
143
144/* messages */
145static char szBanner[] = "Win32k - Odin32 support driver.";
146static char szMsg1[] = "\n\r Found kernel: ";
147static char szMsg1a[] = "\n\r Build: ";
148static char szMsg2[] = "\n\r Found symbolfile: ";
149static char szMsg4[] = "\n\r Failed to find symbolfile!\n\r";
150static char szMsgfailed[]= "failed! ";
151
152
153/*******************************************************************************
154* Internal Functions *
155*******************************************************************************/
156static void kmemcpy(char *p1, const char *p2, int len);
157static int kstrcmp(const char *p1, const char *p2);
158static int kstrncmp(const char *p1, const char *p2, int len);
159static int kstrlen(const char *p);
160static HFILE fopen(char * filename, char * ignored);
161static int fread(void * pBuffer, USHORT i1, USHORT i2, HFILE hfile);
162static int fseek(HFILE hfile, signed long off, int org);
163static unsigned long fsize(HFILE hFile);
164static void puts(char *psz);
165static int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
166
167static int VerifyPrologs(void);
168static int ProbeSymFile(char *pszFilename);
169static int VerifyKernelVer(void);
170static int ReadOS2Krnl(char *filename);
171static int ReadOS2Krnl2(HFILE krnl, unsigned long cbKrnl);
172static int GetKernelOTEs(void);
173
174static void ShowDecNumber(unsigned long n);
175static void ShowHexNumber(unsigned long int n);
176static void ShowResult(int rc, int iSym);
177
178
179
180/**
181 * Quick implementation of fopen.
182 * @param filename name of file to open (sz)
183 * @param ignored whatever - it is ignored
184 * @return Handle to file. (not pointer to a FILE stream as in C-library)
185 * @remark binary and readonly is assumed!
186 */
187static HFILE fopen(char * filename, char * ignored)
188{
189 HFILE hFile = 0;
190 USHORT rc;
191 unsigned short Action = 0;
192
193 rc = DosOpen(
194 filename,
195 &hFile,
196 &Action,
197 0,
198 FILE_NORMAL,
199 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
200 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
201 NULL
202 );
203
204 ignored = ignored;
205 return hFile;
206}
207
208
209/**
210 * fread emulation
211 * @returns Number of blocks read.
212 * @param pBuffer Buffer to read into
213 * @param i1 blocksize
214 * @param i2 block count
215 * @param hFile Handle to file (HFILE)
216 */
217static int fread(void * pBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
218{
219 USHORT ulRead;
220 USHORT rc;
221
222 rc = DosRead(hFile, pBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
223 if (rc == 0)
224 rc = (USHORT)cBlock;
225 else
226 rc = 0;
227
228 return rc;
229}
230
231
232/**
233 * fseek emultation
234 * @returns Same as DosChgFilePtr
235 * @param hFile Filehandle
236 * @param off offset into file from origin
237 * @param org origin
238 */
239static int fseek(HFILE hFile, signed long off, int org)
240{
241 USHORT rc;
242 ULONG ole;
243
244 rc = DosChgFilePtr(hFile, off, org, &ole);
245
246 return rc;
247}
248
249
250/**
251 * Get filesize in bytes.
252 * @returns Filesize.
253 * @param hFile Filehandle
254 * @remark This function sets the file position to end of file.
255 */
256static unsigned long fsize(HFILE hFile)
257{
258 USHORT rc;
259 unsigned long cb;
260
261 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
262
263 return cb;
264}
265
266
267/**
268 * puts lookalike
269 */
270static void puts(char * psz)
271{
272 DosPutMessage(0, kstrlen(psz), psz);
273}
274
275
276/**
277 * kmemcpy - memory copy - slow!
278 * @param p1 target
279 * @param p2 source
280 * @param len length
281 */
282static void kmemcpy(char * p1, const char * p2, int len)
283{
284 while (len != 0)
285 {
286 *p1 = *p2;
287 p1++;
288 p2++;
289 len--;
290 }
291}
292
293#if 0 /* not in use */
294/**
295 * kstrcmp - String compare
296 * @returns 0 - equal else !0
297 * @param p1 String 1
298 * @param p2 String 2
299 */
300static int kstrcmp(const char * p1, const char * p2)
301{
302 while (*p1 == *p2 && *p1 != '\0' && *p2 != '\0')
303 {
304 p1++;
305 p2++;
306 }
307 return *p1 - *p2;
308}
309#endif
310
311/**
312 * kstrncmp - String 'n' compare.
313 * @returns
314 * @returns 0 - equal else !0
315 * @param p1 String 1
316 * @param p2 String 2
317 * @param len length
318 */
319static int kstrncmp(const char * p1, const char * p2, int len)
320{
321 int i = 0;
322 while (i < len && *p1 == *p2 && *p1 != '\0' && *p2 != '\0')
323 {
324 p1++;
325 p2++;
326 i++;
327 }
328
329 return i - len;
330}
331
332
333/**
334 * kstrlen - String length.
335 * @returns Length of the string.
336 * @param psz Pointer to string.
337 * @status completely implemented and tested.
338 * @author knut st. osmundsen
339 */
340static int kstrlen(const char * psz)
341{
342 int cch = 0;
343 while (psz[cch] != '\0')
344 cch++;
345 return cch;
346}
347
348
349/**
350 * Copy an argument to a buffer. Ie. "-K[=|:]c:\os2krnl ....". Supports quotes
351 * @returns Number of chars of pszArg that has been processed.
352 * @param pszTarget - pointer to target buffer.
353 * @param pszArg - pointer to source argument string.
354 * @param cchMaxlen - maximum chars to copy.
355 */
356static int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
357{
358 int i = 0;
359 int fQuote = FALSE;
360
361 /* skip option word/letter */
362 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
363 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
364 {
365 pszArg++;
366 i++;
367 }
368
369 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
370 return 0;
371
372
373 do
374 {
375 pszArg++;
376 i++;
377 } while (*pszArg != '\0' && *pszArg == ' ');
378
379 /* copy maxlen or less */
380 /* check for quotes */
381 if (*pszArg == '"')
382 {
383 fQuote = TRUE;
384 pszArg++;
385 i++;
386 }
387 /* copy loop */
388 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
389 {
390 *pszTarget++ = *pszArg++;
391 i++;
392 cchMaxlen--;
393 }
394
395 /* terminate pszTarget */
396 pszTarget = '\0';
397
398 return i;
399}
400
401
402/**
403 * Verifies the that the addresses in aProcTab are valid.
404 * This is done at Ring-0 of course.
405 * @returns 0 if ok, not 0 if not ok.
406 */
407static int VerifyPrologs(void)
408{
409#ifndef DEBUGR3
410 APIRET rc;
411 HFILE hDev0 = 0;
412 USHORT usAction = 0;
413
414 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
415 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
416 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
417 0UL);
418 if (rc == NO_ERROR)
419 {
420 rc = DosDevIOCtl("", "", D16_IOCTL_VERIFYPROCTAB, D16_IOCTL_CAT, hDev0);
421 DosClose(hDev0);
422 }
423
424 return rc;
425#else
426 return 0;
427#endif
428}
429
430
431/**
432 * Check a symbole file. Searches for the wanted entry-point addresses.
433 * @returns 0 on success - something else on failiure.
434 * @param pszFilename Name of file to probe.
435 * @precond Must be called after kernel-file is found and processed.
436 * @remark Error codes starts at -50.
437 */
438static int ProbeSymFile(char * pszFilename)
439{
440 HFILE SymFile;
441 MAPDEF MapDef;
442 SEGDEF SegDef;
443 SYMDEF32 SymDef32;
444 SYMDEF16 SymDef16;
445 char Buffer[256];
446 unsigned long SymNum;
447 unsigned long SegOffset, SymOffset, SymPtrOffset;
448 unsigned long i;
449 unsigned long ulSegments;
450 int LeftToFind;
451 int rc;
452
453 /* open symbole file */
454 SymFile = fopen(pszFilename, "rb");
455 if (SymFile==0)
456 {
457 dprintf(("Error opening file %s\n", pszFilename));
458 return -50;
459 }
460
461 /* read header and display it */
462 rc = fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
463 if (rc)
464 {
465 Buffer[0] = MapDef.achModName[0];
466 fread(&Buffer[1], 1, MapDef.cbModName, SymFile);
467 Buffer[MapDef.cbModName] = '\0';
468 dprintf(("*Module name: %s\n", Buffer));
469 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
470 dprintf(("*ppNextMap: 0x%x\n\n", MapDef.ppNextMap ));
471 }
472 else
473 {
474 fclose(SymFile);
475 return -51;
476 }
477
478 /* verify module name */
479 if (MapDef.cbModName == 7 && kstrncmp(Buffer, "OS2KRNL", 7) != 0)
480 {
481 dprintf(("Modulename verify failed\n"));
482 fclose(SymFile);
483 return -51;
484 }
485
486 /* verify correct number of segments */
487 ulSegments = MapDef.cSegs;
488 if (ulSegments != KrnlOTEs.cObjects)
489 {
490 dprintf(("Segment No. verify failed\n"));
491 fclose(SymFile);
492 return -52;
493 }
494
495 SegOffset= SEGDEFOFFSET(MapDef);
496 /* skip to last segment - ASSUMES all imports located in 32-bit code segment. */
497 for (i = 0; i < ulSegments; i++ )
498 {
499 if (fseek(SymFile, SegOffset, SEEK_SET))
500 {
501 fclose(SymFile);
502 return -53;
503 }
504 rc = fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
505 if (i+1 < ulSegments)
506 SegOffset = NEXTSEGDEFOFFSET(SegDef);
507 }
508
509 Buffer[0] = SegDef.achSegName[0];
510 rc = fread(&Buffer[1], 1, SegDef.cbSegName, SymFile);
511
512 /* verify that this is DOSHIGH32CODE */
513 if (SegDef.cbSegName != 13 && kstrncmp(Buffer, "DOSHIGH32CODE", 13) != 0)
514 {
515 dprintf(("DOSHIGH32CODE verify failed \n"));
516 fclose(SymFile);
517 return -54;
518 }
519
520 for (i = 0; i < NUMBER_OF_PROCS; i++)
521 aProcTab[i].fFound = 0 ;
522
523 /* search for the entry-point names */
524 for (LeftToFind = NUMBER_OF_PROCS, SymNum = 0; SymNum < SegDef.cSymbols && LeftToFind; SymNum++)
525 {
526 SymPtrOffset = SYMDEFOFFSET(SegOffset, SegDef, SymNum);
527 rc = fseek(SymFile, SymPtrOffset, SEEK_SET);
528 rc = fread(&SymOffset, sizeof(unsigned short int), 1, SymFile);
529 SymOffset &=0xffff;
530 rc = fseek(SymFile, SymOffset+SegOffset, SEEK_SET);
531
532 if (SegDef.bFlags & 0x01)
533 {
534 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
535 Buffer[0] = SymDef32.achSymName[0];
536 rc = fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
537 Buffer[SymDef32.cbSymName] = '\0';
538 } else
539 {
540 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
541 Buffer[0] = SymDef16.achSymName[0];
542 rc = fread(&Buffer[1], 1, SymDef16.cbSymName, SymFile);
543 Buffer[SymDef16.cbSymName] = '\0';
544 }
545
546 /* search proctable */
547 for (i = 0; i < NUMBER_OF_PROCS; i++)
548 {
549 if (!aProcTab[i].fFound && aProcTab[i].cchName == (SegDef.bFlags & 0x01 ? SymDef32.cbSymName : SymDef16.cbSymName))
550 {
551 if (kstrncmp(aProcTab[i].achName, Buffer, aProcTab[i].cchName) == 0)
552 {
553 aProcTab[i].offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
554 aProcTab[i].ulAddress= aProcTab[i].offObject + KrnlOTEs.aObjects[KrnlOTEs.cObjects-1].ote_base;
555
556 if (aProcTab[i].offObject < KrnlOTEs.aObjects[KrnlOTEs.cObjects-1].ote_size)
557 {
558 aProcTab[i].fFound = TRUE;
559 LeftToFind--;
560 dprintf(("Found: %s at off 0x%lx addr 0x%lx\n", aProcTab[i].achName, aProcTab[i].offObject, aProcTab[i].ulAddress));
561 break;
562 }
563 else
564 {
565 fclose(SymFile);
566 return -56;
567 }
568 }
569 }
570 }
571 }
572
573 fclose(SymFile);
574 return LeftToFind == 0 ? VerifyPrologs() : -57;
575}
576
577
578/**
579 * Verifies that build no, matches kernel number.
580 * @returns 0 on equal, !0 on error.
581 */
582static int VerifyKernelVer(void)
583{
584 int VerMinor, VerMajor;
585
586 VerMajor = ulBuild < 20000 ? 20 : 30/*?*/;
587 VerMinor = ulBuild < 6600 ? 10 : ulBuild < 8000 ? 11 : ulBuild < 9000 ? 30 :
588 ulBuild < 10000 ? 40 : ulBuild < 15000 ? 45 : 50;
589
590 return VerMajor - (int)usVerMajor | VerMinor - (int)usVerMinor;
591}
592
593
594/**
595 * Reads and verifies OS/2 kernel.
596 * @returns 0 on success, not 0 on failure.
597 * @param filename Filename of the OS/2 kernel.
598 * @result ulBuild is set.
599 */
600static int ReadOS2Krnl(char * filename)
601{
602 HFILE krnl;
603 unsigned long cbKrnl;
604 int rc;
605
606 krnl = fopen(filename, "rb");
607 if (krnl != 0)
608 {
609 cbKrnl = fsize(krnl);
610 if (!fseek(krnl, 0, SEEK_SET))
611 rc = ReadOS2Krnl2(krnl, cbKrnl);
612 else
613 rc = -2;
614 fclose(krnl);
615 }
616 else
617 {
618 dprintf(("Could not open file\n"));
619 rc = -1;
620 }
621 return rc;
622}
623
624/**
625 * Worker function for ReadOS2Krnl
626 * @returns 0 on success.
627 * errorcodes on failure. (-1 >= rc >= -14)
628 * @param
629 * @equiv
630 * @time
631 * @sketch
632 * @status
633 * @author knut st. osmundsen
634 * @remark
635 */
636static int ReadOS2Krnl2(HFILE krnl, unsigned long cbKrnl)
637{
638 int i, j;
639 int rc = 0;
640 char Buffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
641 unsigned long offLXHdr;
642 struct e32_exe *pLXHdr;
643
644
645 /* find bldlevel string - "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F" */
646 cbKrnl = fsize(krnl);
647 if (fseek(krnl, 0, SEEK_SET))
648 return -2;
649
650 if (!fread(&Buffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, krnl))
651 return -3;
652
653 i = KERNEL_ID_STRING_LENGTH;
654 while (cbKrnl > 0)
655 {
656 if (i == KERNEL_READ_SIZE)
657 {
658
659 kmemcpy(Buffer, &Buffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
660 if (!fread(&Buffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, krnl))
661 return -3;
662
663 i = 0;
664 }
665
666 if (kstrncmp("@#IBM:", &Buffer[i], 6) == 0)
667 break;
668
669 /* next */
670 i++;
671 cbKrnl--;
672 }
673
674 if (cbKrnl == 0)
675 {
676 fclose(krnl);
677 return -4;
678 }
679
680 /* displacement */
681 j = 0;
682 while (j < 6 && Buffer[i+10+j] != '#')
683 j++;
684
685 /* verify signature */
686 if (kstrncmp(&Buffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
687 return -5;
688
689 /* read ulBuild */
690 ulBuild = (char)(Buffer[i+6] - '0') * 1000;
691 if (Buffer[i+7] != '.')
692 {
693 /* this code is for Warp5 */
694 ulBuild *= 10;
695 ulBuild += (char)(Buffer[i+7] - '0') * 1000;
696 i++;
697 j--;
698 if (Buffer[i+7] != '.')
699 {
700 ulBuild = ulBuild * 10;
701 ulBuild = ulBuild + (unsigned long)(Buffer[i+7] - '0') * 1000;
702 i++;
703 j--;
704 }
705 }
706
707 if (j == 0)
708 {
709 ulBuild += (Buffer[i+ 8] - '0') * 10;
710 ulBuild += (Buffer[i+ 9] - '0') * 1;
711 } else
712 {
713 if (j == 3)
714 return -9;
715 ulBuild += (Buffer[i+ 8] - '0') * 100;
716 ulBuild += (Buffer[i+ 9] - '0') * 10;
717 ulBuild += (Buffer[i+10] - '0');
718 }
719
720 if (VerifyKernelVer())
721 return -9;
722 dprintf(("ulBuild: %d\n",ulBuild));
723
724 /* get segment number */
725 /* read-MZheader */
726 if (fseek(krnl,0,SEEK_SET))
727 return -2;
728
729 if (!fread(Buffer, 1, 0x40, krnl))
730 return -3;
731
732 offLXHdr = *(unsigned long int *)&Buffer[0x3c];
733
734 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
735 return -6;
736
737 if (fseek(krnl, offLXHdr, SEEK_SET))
738 return -2;
739
740 if (!fread(Buffer, 1, sizeof(struct e32_exe), krnl))
741 return -3;
742
743 /* check LX-magic */
744 if (Buffer[0] != 'L' || Buffer[1] != 'X')
745 return -7;
746
747#ifndef DEBUGR3
748 /* check object count - match it with what we got from the kernel. */
749 pLXHdr = (struct e32_exe *)Buffer;
750 if ((UCHAR)pLXHdr->e32_objcnt != KrnlOTEs.cObjects)
751 return -8;
752
753 if (pLXHdr->e32_objcnt < 10)
754 return -9;
755
756 /* check objects (sizes and flags(?)) */
757 if (!fseek(krnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
758 {
759 struct o32_obj *pObj = (struct o32_obj *)Buffer;
760 for (i = 0; i < (int)KrnlOTEs.cObjects; i++)
761 {
762 if (!fread(Buffer, 1, sizeof(OTE), krnl))
763 return -11;
764 if (pObj->o32_size < KrnlOTEs.aObjects[i].ote_size)
765 return -12;
766
767 #if 0 /* don't work! */
768 if ((pObj->o32_flags & 0xffffUL) != (KrnlOTEs.aObjects[i].ote_flags & 0xffffUL))
769 return -14;
770 #endif
771 }
772 }
773 else
774 return -10;
775#else
776 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
777 * we'll use what we find in the kernel.
778 */
779
780 /* object count */
781 pLXHdr = (struct e32_exe *)Buffer;
782 KrnlOTEs.cObjects = (UCHAR)pLXHdr->e32_objcnt;
783
784 /* get OTEs */
785 if (!fseek(krnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
786 {
787 struct o32_obj *pObj = (struct o32_obj *)Buffer;
788 for (i = 0; i < (int)KrnlOTEs.cObjects; i++)
789 if (!fread(&KrnlOTEs.aObjects[i], 1, sizeof(struct o32_obj), krnl))
790 return -11;
791 }
792 else
793 return -10;
794#endif
795
796 return 0;
797}
798
799
800/**
801 * Gets the os/2 kernel OTE's (object table entries).
802 * @returns 0 on success. Not 0 on error.
803 */
804static int GetKernelOTEs(void)
805{
806#ifndef DEBUGR3
807 APIRET rc;
808 HFILE hDev0 = 0;
809 USHORT usAction = 0;
810
811 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
812 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
813 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
814 0UL);
815 if (rc == NO_ERROR)
816 {
817 rc = DosDevIOCtl(&KrnlOTEs, "", D16_IOCTL_GETKRNLOTES, D16_IOCTL_CAT, hDev0);
818 DosClose(hDev0);
819 }
820
821 if (rc != NO_ERROR)
822 puts("Failed to get kernel OTEs\r\n");
823
824 return rc;
825#else
826 KrnlOTEs.cObjects = 23;
827 return 0;
828#endif
829}
830
831
832/**
833 * Displays an ULONG in decimal notation using DosPutMessage
834 * @param n ULONG to show.
835 */
836static void ShowDecNumber(unsigned long n)
837{
838 int f = 0;
839 unsigned long div;
840 char sif;
841
842 for (div = 1000000; div > 0; div /= 10)
843 {
844 sif = (char)(n/div);
845 n %= div;
846 if (sif != 0 || f)
847 {
848 f = 1;
849 sif += '0';
850 DosPutMessage(0, 1, &sif);
851 }
852 }
853}
854
855
856/**
857 * Displays an ULONG in hexadecimal notation using DosPutMessage
858 * @param n ULONG to show.
859 */
860static void ShowHexNumber(unsigned long int n)
861{
862 signed int div;
863 char sif;
864 DosPutMessage(0, 2, "0x");
865 for (div = 28; div >= 0; div -= 4)
866 {
867 sif = (char)(n >> div) & (char)0xF;
868 sif += (sif < 10 ? '0' : 'a' - 10);
869 DosPutMessage(0, 1, &sif);
870 }
871}
872
873
874
875/**
876 * Shows result of kernelprobing if not quiet or on error.
877 * @param rc Return code.
878 * @param iSym index of .sym-file into static struct.
879 */
880static void ShowResult(int rc, int iSym)
881{
882 int i, j;
883
884 /* complain even if quiet on error */
885 if (!fQuiet || rc != 0)
886 {
887 puts(szBanner);
888
889 /* kernel stuff */
890 puts(szMsg1);
891 if (rc <= -50 || rc == 0)
892 {
893 puts(szOS2Krnl);
894 puts(szMsg1a);
895 ShowDecNumber(ulBuild);
896 puts(" - v");
897 ShowDecNumber(usVerMajor);
898 puts(".");
899 ShowDecNumber(usVerMinor);
900 }
901 else
902 puts(szMsgfailed);
903
904 /* functions */
905 if (rc == 0)
906 {
907 puts(szMsg2);
908 if (szUsrSym[0] == '\0')
909 puts(apszSym[iSym]);
910 else
911 puts(szUsrSym);
912
913 for (i = 0; i < NUMBER_OF_PROCS; i++)
914 {
915 if ((i % 2) == 0)
916 puts("\n\r ");
917 else
918 puts(" ");
919 puts(aProcTab[i].achName);
920 for (j = aProcTab[i].cchName; j < 20; j++)
921 puts(" ");
922
923 puts(" at ");
924 if (aProcTab[i].fFound)
925 ShowHexNumber(aProcTab[i].ulAddress);
926 else
927 puts(szMsgfailed);
928 }
929 }
930 else
931 puts(szMsg4);
932 puts("\n\r");
933 }
934
935 /* if error: write rc */
936 if (rc != 0)
937 {
938 puts("rc = ");
939 ShowHexNumber((unsigned long)rc);
940 puts("\n\r");
941 }
942}
943
944
945
946/**
947 * "main" function.
948 * Note that the option -Noloader causes nothing to be done.
949 * @returns 0 on success, something else on error.
950 * @param pReqPack Pointer to init request packet
951 * @remark
952 */
953int ProbeKernel(PRPINITIN pReqPack)
954{
955 int rc;
956 int i;
957 int n;
958 SEL GDT;
959 SEL LDT;
960 PGINFOSEG pInfoSeg;
961 USHORT usBootDrive;
962
963 /*----------------*/
964 /* parse InitArgs */
965 /*----------------*/
966 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
967 {
968 n = kstrlen(pReqPack->InitArgs);
969 for (i = 0; i < n; i++)
970 {
971 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
972 {
973 i++;
974 switch (pReqPack->InitArgs[i])
975 {
976 case 'k':
977 case 'K': /* Kernel file */
978 i++;
979 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
980 break;
981
982 case 'n':
983 case 'N': /* NoLoader */
984 return 0;
985
986 case 'q':
987 case 'Q': /* Quiet */
988 fQuiet = 1;
989 break;
990
991 case 's':
992 case 'S': /* Symbol file */
993 i++;
994 i += kargncpy(szUsrSym, &pReqPack->InitArgs[i], sizeof(szUsrSym));
995 break;
996
997 case 'v':
998 case 'V': /* Verbose */
999 fQuiet = 0;
1000 break;
1001 }
1002 }
1003 }
1004 }
1005
1006 /*---------------------*/
1007 /* determin boot drive */
1008 /*---------------------*/
1009 rc = DosGetInfoSeg(&GDT, &LDT);
1010 if (rc != NO_ERROR)
1011 return rc;
1012
1013 pInfoSeg = MAKEPGINFOSEG(GDT);
1014 usBootDrive = pInfoSeg->bootdrive;
1015 usVerMajor = pInfoSeg->uchMajorVersion;
1016 usVerMinor = pInfoSeg->uchMinorVersion;
1017 dprintf(("BootDrive: %d\n", usBootDrive));
1018
1019 /* set driveletter in constants strings */
1020 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1021 szOS2Krnl[0] = (char)usBootDrive;
1022 for (i = 0; apszSym[i] != NULL; i++)
1023 apszSym[i][0] = (char)usBootDrive;
1024
1025 /*-----------------*/
1026 /* get kernel OTEs */
1027 /*-----------------*/
1028 rc = GetKernelOTEs();
1029 if (rc != NO_ERROR)
1030 return rc;
1031
1032 /*--------------*/
1033 /* read kernel */
1034 /*--------------*/
1035 if (szUsrOS2Krnl[0] != '\0')
1036 {
1037 rc = ReadOS2Krnl(szUsrOS2Krnl);
1038 if (rc != 0)
1039 {
1040 puts("Warning: Invalid kernel file specified. Tries defaults.\n\r");
1041 szUsrOS2Krnl[0] = '\0';
1042 rc = ReadOS2Krnl(szOS2Krnl);
1043 }
1044 }
1045 else
1046 rc = ReadOS2Krnl(szOS2Krnl);
1047
1048 /*--------------*/
1049 /* read symfile */
1050 /*--------------*/
1051 if (!rc)
1052 {
1053 rc = 1;
1054 if (szUsrSym[0] != '\0')
1055 {
1056 rc = ProbeSymFile(szUsrSym);
1057 if (rc)
1058 {
1059 puts("Warning: Invalid symbol file specified. Tries defaults.\n\r");
1060 szUsrSym[0] = '\0';
1061 }
1062 }
1063 if (rc != 0) /* if user sym failed or don't exists */
1064 {
1065 i = 0;
1066 while (apszSym[i] != NULL && (rc = ProbeSymFile(apszSym[i])) != 0)
1067 i++;
1068 }
1069 }
1070
1071 /* show the result and set return-value */
1072 dprintf(("rc=%d; i=%d\n", rc, i));
1073 ShowResult(rc, i);
1074
1075 return rc;
1076}
1077
1078
1079
1080#ifdef DEBUGR3
1081/**
1082 * Debug - Main procedure for standalone testing.
1083 */
1084void main(int argc, char **argv)
1085{
1086 char szParm[512];
1087 RPINITIN ReqPack;
1088 int j;
1089 int i = 0;
1090 int argi = 0;
1091
1092 while (argi < argc)
1093 {
1094 j = 0;
1095 while (argv[argi][j] != '\0')
1096 szParm[i++] = argv[argi][j++];
1097 szParm[i++] = ' ';
1098
1099 /* next */
1100 argi++;
1101 }
1102 szParm[i++] = '\0';
1103
1104 ReqPack.InitArgs = szParm;
1105
1106 ProbeKernel(&ReqPack);
1107}
1108
1109#endif
1110
Note: See TracBrowser for help on using the repository browser.