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

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

16-bit imports and import of global variables.
(But there are some problems left)

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