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

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

Cosmetical changes in messages displayed during boot.

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