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

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

Temporary backup checkin.

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