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

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

Unix styled scripts is working!

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