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

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

Updated option/argument handling.
Corrected a few bugs.

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