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

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

Corrected kargncpy to match new argument style.

File size: 28.2 KB
Line 
1/* $Id: probkrnl.c,v 1.5 1999-12-06 16:18:25 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 option word/letter */
344 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
345 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
346 {
347 pszArg++;
348 i++;
349 }
350
351 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
352 return 0;
353
354
355 do
356 {
357 pszArg++;
358 i++;
359 } while (*pszArg != '\0' && *pszArg == ' ');
360
361 /* copy maxlen or less */
362 /* check for quotes */
363 if (*pszArg == '"')
364 {
365 fQuote = TRUE;
366 pszArg++;
367 i++;
368 }
369 /* copy loop */
370 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
371 {
372 *pszTarget++ = *pszArg++;
373 i++;
374 cchMaxlen--;
375 }
376
377 /* terminate pszTarget */
378 pszTarget = '\0';
379
380 return i;
381}
382
383
384/**
385 * Verifies the that the addresses in aProcTab are valid.
386 * This is done at Ring-0 of course.
387 * @returns 0 if ok, not 0 if not ok.
388 */
389static int VerifyPrologs(void)
390{
391#ifndef DEBUGR3
392 APIRET rc;
393 HFILE hDev0 = 0;
394 USHORT usAction = 0;
395
396 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
397 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
398 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
399 0UL);
400 if (rc == NO_ERROR)
401 {
402 rc = DosDevIOCtl("", "", D16_IOCTL_VERIFYPROCTAB, D16_IOCTL_CAT, hDev0);
403 DosClose(hDev0);
404 }
405
406 return rc;
407#else
408 return 0;
409#endif
410}
411
412
413/**
414 * Check a symbole file. Searches for the wanted entry-point addresses.
415 * @returns 0 on success - something else on failiure.
416 * @param pszFilename Name of file to probe.
417 * @precond Must be called after kernel-file is found and processed.
418 * @remark Error codes starts at -50.
419 */
420static int ProbeSymFile(char * pszFilename)
421{
422 HFILE SymFile;
423 MAPDEF MapDef;
424 SEGDEF SegDef;
425 SYMDEF32 SymDef32;
426 SYMDEF16 SymDef16;
427 char Buffer[256];
428 unsigned long SymNum;
429 unsigned long SegOffset, SymOffset, SymPtrOffset;
430 unsigned long i;
431 unsigned long ulSegments;
432 int LeftToFind;
433 int rc;
434
435 /* open symbole file */
436 SymFile = fopen(pszFilename, "rb");
437 if (SymFile==0)
438 {
439 dprintf(("Error opening file %s\n", pszFilename));
440 return -50;
441 }
442
443 /* read header and display it */
444 rc = fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
445 if (rc)
446 {
447 Buffer[0] = MapDef.achModName[0];
448 fread(&Buffer[1], 1, MapDef.cbModName, SymFile);
449 Buffer[MapDef.cbModName] = '\0';
450 dprintf(("*Module name: %s\n", Buffer));
451 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
452 dprintf(("*ppNextMap: 0x%x\n\n", MapDef.ppNextMap ));
453 }
454 else
455 {
456 fclose(SymFile);
457 return -51;
458 }
459
460 /* verify module name */
461 if (MapDef.cbModName == 7 && kstrncmp(Buffer, "OS2KRNL", 7) != 0)
462 {
463 dprintf(("Modulename verify failed\n"));
464 fclose(SymFile);
465 return -51;
466 }
467
468 /* verify correct number of segments */
469 ulSegments = MapDef.cSegs;
470 if (ulSegments != KrnlOTEs.cObjects)
471 {
472 dprintf(("Segment No. verify failed\n"));
473 fclose(SymFile);
474 return -52;
475 }
476
477 SegOffset= SEGDEFOFFSET(MapDef);
478 /* skip to last segment - ASSUMES all imports located in 32-bit code segment. */
479 for (i = 0; i < ulSegments; i++ )
480 {
481 if (fseek(SymFile, SegOffset, SEEK_SET))
482 {
483 fclose(SymFile);
484 return -53;
485 }
486 rc = fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
487 if (i+1 < ulSegments)
488 SegOffset = NEXTSEGDEFOFFSET(SegDef);
489 }
490
491 Buffer[0] = SegDef.achSegName[0];
492 rc = fread(&Buffer[1], 1, SegDef.cbSegName, SymFile);
493
494 /* verify that this is DOSHIGH32CODE */
495 if (SegDef.cbSegName != 13 && kstrncmp(Buffer, "DOSHIGH32CODE", 13) != 0)
496 {
497 dprintf(("DOSHIGH32CODE verify failed \n"));
498 fclose(SymFile);
499 return -54;
500 }
501
502 for (i = 0; i < NUMBER_OF_PROCS; i++)
503 aProcTab[i].fFound = 0 ;
504
505 /* search for the entry-point names */
506 for (LeftToFind = NUMBER_OF_PROCS, SymNum = 0; SymNum < SegDef.cSymbols && LeftToFind; SymNum++)
507 {
508 SymPtrOffset = SYMDEFOFFSET(SegOffset, SegDef, SymNum);
509 rc = fseek(SymFile, SymPtrOffset, SEEK_SET);
510 rc = fread(&SymOffset, sizeof(unsigned short int), 1, SymFile);
511 SymOffset &=0xffff;
512 rc = fseek(SymFile, SymOffset+SegOffset, SEEK_SET);
513
514 if (SegDef.bFlags & 0x01)
515 {
516 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
517 Buffer[0] = SymDef32.achSymName[0];
518 rc = fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
519 Buffer[SymDef32.cbSymName] = '\0';
520 } else
521 {
522 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
523 Buffer[0] = SymDef16.achSymName[0];
524 rc = fread(&Buffer[1], 1, SymDef16.cbSymName, SymFile);
525 Buffer[SymDef16.cbSymName] = '\0';
526 }
527
528 /* search proctable */
529 for (i = 0; i < NUMBER_OF_PROCS; i++)
530 {
531 if (!aProcTab[i].fFound && aProcTab[i].cchName == (SegDef.bFlags & 0x01 ? SymDef32.cbSymName : SymDef16.cbSymName))
532 {
533 if (kstrncmp(aProcTab[i].achName, Buffer, aProcTab[i].cchName) == 0)
534 {
535 aProcTab[i].offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
536 aProcTab[i].ulAddress= aProcTab[i].offObject + KrnlOTEs.aObjects[KrnlOTEs.cObjects-1].ote_base;
537
538 if (aProcTab[i].offObject < KrnlOTEs.aObjects[KrnlOTEs.cObjects-1].ote_size)
539 {
540 aProcTab[i].fFound = TRUE;
541 LeftToFind--;
542 dprintf(("Found: %s at off 0x%lx addr 0x%lx\n", aProcTab[i].achName, aProcTab[i].offObject, aProcTab[i].ulAddress));
543 break;
544 }
545 else
546 {
547 fclose(SymFile);
548 return -56;
549 }
550 }
551 }
552 }
553 }
554
555 fclose(SymFile);
556 return LeftToFind == 0 ? VerifyPrologs() : -57;
557}
558
559
560/**
561 * Verifies that build no, matches kernel number.
562 * @returns 0 on equal, !0 on error.
563 */
564static int VerifyKernelVer(void)
565{
566 int VerMinor, VerMajor;
567
568 VerMajor = ulBuild < 20000 ? 20 : 30/*?*/;
569 VerMinor = ulBuild < 6600 ? 10 : ulBuild < 8000 ? 11 : ulBuild < 9000 ? 30 :
570 ulBuild < 10000 ? 40 : ulBuild < 15000 ? 45 : 50;
571
572 return VerMajor - (int)usVerMajor | VerMinor - (int)usVerMinor;
573}
574
575
576/**
577 * Reads and verifies OS/2 kernel.
578 * @returns 0 on success, not 0 on failure.
579 * @param filename Filename of the OS/2 kernel.
580 * @result ulBuild is set.
581 */
582static int ReadOS2Krnl(char * filename)
583{
584 HFILE krnl;
585 unsigned long cbKrnl;
586 int rc;
587
588 krnl = fopen(filename, "rb");
589 if (krnl != 0)
590 {
591 cbKrnl = fsize(krnl);
592 if (!fseek(krnl, 0, SEEK_SET))
593 rc = ReadOS2Krnl2(krnl, cbKrnl);
594 else
595 rc = -2;
596 fclose(krnl);
597 }
598 else
599 {
600 dprintf(("Could not open file\n"));
601 rc = -1;
602 }
603 return rc;
604}
605
606/**
607 * Worker function for ReadOS2Krnl
608 * @returns 0 on success.
609 * errorcodes on failure. (-1 >= rc >= -14)
610 * @param
611 * @equiv
612 * @time
613 * @sketch
614 * @status
615 * @author knut st. osmundsen
616 * @remark
617 */
618static int ReadOS2Krnl2(HFILE krnl, unsigned long cbKrnl)
619{
620 int i, j;
621 int rc = 0;
622 char Buffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
623 unsigned long offLXHdr;
624 struct e32_exe *pLXHdr;
625
626
627 /* find bldlevel string - "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F" */
628 cbKrnl = fsize(krnl);
629 if (fseek(krnl, 0, SEEK_SET))
630 return -2;
631
632 if (!fread(&Buffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, krnl))
633 return -3;
634
635 i = KERNEL_ID_STRING_LENGTH;
636 while (cbKrnl > 0)
637 {
638 if (i == KERNEL_READ_SIZE)
639 {
640
641 kmemcpy(Buffer, &Buffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
642 if (!fread(&Buffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, krnl))
643 return -3;
644
645 i = 0;
646 }
647
648 if (kstrncmp("@#IBM:", &Buffer[i], 6) == 0)
649 break;
650
651 /* next */
652 i++;
653 cbKrnl--;
654 }
655
656 if (cbKrnl == 0)
657 {
658 fclose(krnl);
659 return -4;
660 }
661
662 /* displacement */
663 j = 0;
664 while (j < 6 && Buffer[i+10+j] != '#')
665 j++;
666
667 /* verify signature */
668 if (kstrncmp(&Buffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
669 return -5;
670
671 /* read ulBuild */
672 ulBuild = (char)(Buffer[i+6] - '0') * 1000;
673 if (Buffer[i+7] != '.')
674 {
675 /* this code is for Warp5 */
676 ulBuild *= 10;
677 ulBuild += (char)(Buffer[i+7] - '0') * 1000;
678 i++;
679 j--;
680 if (Buffer[i+7] != '.')
681 {
682 ulBuild = ulBuild * 10;
683 ulBuild = ulBuild + (unsigned long)(Buffer[i+7] - '0') * 1000;
684 i++;
685 j--;
686 }
687 }
688
689 if (j == 0)
690 {
691 ulBuild += (Buffer[i+ 8] - '0') * 10;
692 ulBuild += (Buffer[i+ 9] - '0') * 1;
693 } else
694 {
695 if (j == 3)
696 return -9;
697 ulBuild += (Buffer[i+ 8] - '0') * 100;
698 ulBuild += (Buffer[i+ 9] - '0') * 10;
699 ulBuild += (Buffer[i+10] - '0');
700 }
701
702 if (VerifyKernelVer())
703 return -9;
704 dprintf(("ulBuild: %d\n",ulBuild));
705
706 /* get segment number */
707 /* read-MZheader */
708 if (fseek(krnl,0,SEEK_SET))
709 return -2;
710
711 if (!fread(Buffer, 1, 0x40, krnl))
712 return -3;
713
714 offLXHdr = *(unsigned long int *)&Buffer[0x3c];
715
716 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
717 return -6;
718
719 if (fseek(krnl, offLXHdr, SEEK_SET))
720 return -2;
721
722 if (!fread(Buffer, 1, sizeof(struct e32_exe), krnl))
723 return -3;
724
725 /* check LX-magic */
726 if (Buffer[0] != 'L' || Buffer[1] != 'X')
727 return -7;
728
729#ifndef DEBUGR3
730 /* check object count - match it with what we got from the kernel. */
731 pLXHdr = (struct e32_exe *)Buffer;
732 if ((UCHAR)pLXHdr->e32_objcnt != KrnlOTEs.cObjects)
733 return -8;
734
735 if (pLXHdr->e32_objcnt < 10)
736 return -9;
737
738 /* check objects (sizes and flags(?)) */
739 if (!fseek(krnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
740 {
741 struct o32_obj *pObj = (struct o32_obj *)Buffer;
742 for (i = 0; i < (int)KrnlOTEs.cObjects; i++)
743 {
744 if (!fread(Buffer, 1, sizeof(OTE), krnl))
745 return -11;
746 if (pObj->o32_size < KrnlOTEs.aObjects[i].ote_size)
747 return -12;
748
749 #if 0 /* don't work! */
750 if ((pObj->o32_flags & 0xffffUL) != (KrnlOTEs.aObjects[i].ote_flags & 0xffffUL))
751 return -14;
752 #endif
753 }
754 }
755 else
756 return -10;
757#else
758 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
759 * we'll use what we find in the kernel.
760 */
761
762 /* object count */
763 pLXHdr = (struct e32_exe *)Buffer;
764 KrnlOTEs.cObjects = (UCHAR)pLXHdr->e32_objcnt;
765
766 /* get OTEs */
767 if (!fseek(krnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
768 {
769 struct o32_obj *pObj = (struct o32_obj *)Buffer;
770 for (i = 0; i < (int)KrnlOTEs.cObjects; i++)
771 if (!fread(&KrnlOTEs.aObjects[i], 1, sizeof(struct o32_obj), krnl))
772 return -11;
773 }
774 else
775 return -10;
776#endif
777
778 return 0;
779}
780
781
782/**
783 * Gets the os/2 kernel OTE's (object table entries).
784 * @returns 0 on success. Not 0 on error.
785 */
786static int GetKernelOTEs(void)
787{
788#ifndef DEBUGR3
789 APIRET rc;
790 HFILE hDev0 = 0;
791 USHORT usAction = 0;
792
793 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
794 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
795 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
796 0UL);
797 if (rc == NO_ERROR)
798 {
799 rc = DosDevIOCtl(&KrnlOTEs, "", D16_IOCTL_GETKRNLOTES, D16_IOCTL_CAT, hDev0);
800 DosClose(hDev0);
801 }
802
803 if (rc != NO_ERROR)
804 puts("Failed to get kernel OTEs\r\n");
805
806 return rc;
807#else
808 KrnlOTEs.cObjects = 23;
809 return 0;
810#endif
811}
812
813
814/**
815 * Displays an ULONG in decimal notation using DosPutMessage
816 * @param n ULONG to show.
817 */
818static void ShowDecNumber(unsigned long n)
819{
820 int f = 0;
821 unsigned long div;
822 char sif;
823
824 for (div = 1000000; div > 0; div /= 10)
825 {
826 sif = (char)(n/div);
827 n %= div;
828 if (sif != 0 || f)
829 {
830 f = 1;
831 sif += '0';
832 DosPutMessage(0, 1, &sif);
833 }
834 }
835}
836
837
838/**
839 * Displays an ULONG in hexadecimal notation using DosPutMessage
840 * @param n ULONG to show.
841 */
842static void ShowHexNumber(unsigned long int n)
843{
844 signed int div;
845 char sif;
846 DosPutMessage(0, 2, "0x");
847 for (div = 28; div >= 0; div -= 4)
848 {
849 sif = (char)(n >> div) & (char)0xF;
850 sif += (sif < 10 ? '0' : 'a' - 10);
851 DosPutMessage(0, 1, &sif);
852 }
853}
854
855
856
857/**
858 * Shows result of kernelprobing if not quiet or on error.
859 * @param rc Return code.
860 * @param iSym index of .sym-file into static struct.
861 */
862static void ShowResult(int rc, int iSym)
863{
864 int i, j;
865
866 /* complain even if quiet on error */
867 if (!fQuiet || rc != 0)
868 {
869 puts(szBanner);
870
871 /* kernel stuff */
872 puts(szMsg1);
873 if (rc <= -50 || rc == 0)
874 {
875 puts(szOS2Krnl);
876 puts(szMsg1a);
877 ShowDecNumber(ulBuild);
878 puts(" - v");
879 ShowDecNumber(usVerMajor);
880 puts(".");
881 ShowDecNumber(usVerMinor);
882 }
883 else
884 puts(szMsgfailed);
885
886 /* functions */
887 if (rc == 0)
888 {
889 puts(szMsg2);
890 if (szUsrSym[0] == '\0')
891 puts(apszSym[iSym]);
892 else
893 puts(szUsrSym);
894
895 for (i = 0; i < NUMBER_OF_PROCS; i++)
896 {
897 puts("\n\r\t");
898 puts(aProcTab[i].achName);
899 for (j = aProcTab[i].cchName; j < 17; j++)
900 puts(" ");
901
902 puts(" at ");
903 if (aProcTab[i].fFound)
904 ShowHexNumber(aProcTab[i].ulAddress);
905 else
906 puts(szMsgfailed);
907 }
908 }
909 else
910 puts(szMsg4);
911 puts("\n\r");
912 }
913
914 /* if error: write rc */
915 if (rc != 0)
916 {
917 puts("rc = ");
918 ShowHexNumber((unsigned long)rc);
919 puts("\n\r");
920 }
921}
922
923
924
925/**
926 * "main" function.
927 * Note that the option -Noloader causes nothing to be done.
928 * @returns 0 on success, something else on error.
929 * @param pReqPack Pointer to init request packet
930 * @remark
931 */
932int ProbeKernel(PRPINITIN pReqPack)
933{
934 int rc;
935 int i;
936 int n;
937 SEL GDT;
938 SEL LDT;
939 PGINFOSEG pInfoSeg;
940 USHORT usBootDrive;
941
942 /*----------------*/
943 /* parse InitArgs */
944 /*----------------*/
945 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
946 {
947 n = kstrlen(pReqPack->InitArgs);
948 for (i = 0; i < n; i++)
949 {
950 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
951 {
952 i++;
953 switch (pReqPack->InitArgs[i])
954 {
955 case 'k':
956 case 'K': /* Kernel file */
957 i++;
958 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
959 break;
960
961 case 'n':
962 case 'N': /* NoLoader */
963 return 0;
964
965 case 'q':
966 case 'Q': /* Quiet */
967 fQuiet = 1;
968 break;
969
970 case 's':
971 case 'S': /* Symbol file */
972 i++;
973 i += kargncpy(szUsrSym, &pReqPack->InitArgs[i], sizeof(szUsrSym));
974 break;
975
976 case 'v':
977 case 'V': /* Verbose */
978 fQuiet = 0;
979 break;
980 }
981 }
982 }
983 }
984
985 /*---------------------*/
986 /* determin boot drive */
987 /*---------------------*/
988 rc = DosGetInfoSeg(&GDT, &LDT);
989 if (rc != NO_ERROR)
990 return rc;
991
992 pInfoSeg = MAKEPGINFOSEG(GDT);
993 usBootDrive = pInfoSeg->bootdrive;
994 usVerMajor = pInfoSeg->uchMajorVersion;
995 usVerMinor = pInfoSeg->uchMinorVersion;
996 dprintf(("BootDrive: %d\n", usBootDrive));
997
998 /* set driveletter in constants strings */
999 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1000 szOS2Krnl[0] = (char)usBootDrive;
1001 for (i = 0; apszSym[i] != NULL; i++)
1002 apszSym[i][0] = (char)usBootDrive;
1003
1004 /*-----------------*/
1005 /* get kernel OTEs */
1006 /*-----------------*/
1007 rc = GetKernelOTEs();
1008 if (rc != NO_ERROR)
1009 return rc;
1010
1011 /*--------------*/
1012 /* read kernel */
1013 /*--------------*/
1014 if (szUsrOS2Krnl[0] != '\0')
1015 {
1016 rc = ReadOS2Krnl(szUsrOS2Krnl);
1017 if (rc != 0)
1018 {
1019 puts("Warning: Invalid kernel file specified. Tries defaults.\n\r");
1020 szUsrOS2Krnl[0] = '\0';
1021 rc = ReadOS2Krnl(szOS2Krnl);
1022 }
1023 }
1024 else
1025 rc = ReadOS2Krnl(szOS2Krnl);
1026
1027 /*--------------*/
1028 /* read symfile */
1029 /*--------------*/
1030 if (!rc)
1031 {
1032 rc = 1;
1033 if (szUsrSym[0] != '\0')
1034 {
1035 rc = ProbeSymFile(szUsrSym);
1036 if (rc)
1037 {
1038 puts("Warning: Invalid symbol file specified. Tries defaults.\n\r");
1039 szUsrSym[0] = '\0';
1040 }
1041 }
1042 if (rc != 0) /* if user sym failed or don't exists */
1043 {
1044 i = 0;
1045 while (apszSym[i] != NULL && (rc = ProbeSymFile(apszSym[i])) != 0)
1046 i++;
1047 }
1048 }
1049
1050 /* show the result and set return-value */
1051 dprintf(("rc=%d; i=%d\n", rc, i));
1052 ShowResult(rc, i);
1053
1054 return rc;
1055}
1056
1057
1058
1059#ifdef DEBUGR3
1060/**
1061 * Debug - Main procedure for standalone testing.
1062 */
1063void main(int argc, char **argv)
1064{
1065 char szParm[512];
1066 RPINITIN ReqPack;
1067 int j;
1068 int i = 0;
1069 int argi = 0;
1070
1071 while (argi < argc)
1072 {
1073 j = 0;
1074 while (argv[argi][j] != '\0')
1075 szParm[i++] = argv[argi][j++];
1076 szParm[i++] = ' ';
1077
1078 /* next */
1079 argi++;
1080 }
1081 szParm[i++] = '\0';
1082
1083 ReqPack.InitArgs = szParm;
1084
1085 ProbeKernel(&ReqPack);
1086}
1087
1088#endif
1089
Note: See TracBrowser for help on using the repository browser.