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

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

Some bugsfixes - Yield is disabled.
Added parameters.
Correcte moduleheaders.
Introduced a new base class for virtual lx modules + some elf sketches.

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