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

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

Unfinised stuff! Don't work. Don't even compile!

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