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

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

Partly finished 16-bit import code++.

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