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

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

Corrections to make win32k work.
(And now it does work, at least at my test machine...)

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