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

Last change on this file since 4185 was 4185, checked in by bird, 25 years ago

Corrected FATAL error in k32QueryOptionsStatus.cpp. (Forgot SSToDS...)
Improved error messages during init.

File size: 58.7 KB
Line 
1/* $Id: probkrnl.c,v 1.22 2000-09-04 16:40:48 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 and kernel info like build no. (elf$)
17 * 3. if non-debug kernel the symbol database is scanned to get the syms
18 * 4. if Syms not found THEN locates and scans the symbol-file(s) for the
19 * entrypoints which are wanted.
20 * 5. the entry points are verified. (elf$)
21 * 6. finished.
22 *
23 * Copyright (c) 1998-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
24 *
25 * Project Odin Software License can be found in LICENSE.TXT
26 *
27 */
28
29
30/*******************************************************************************
31* Defined Constants And Macros *
32*******************************************************************************/
33/* Disable logging when doing extracts */
34#if defined(EXTRACT) || defined(RING0)
35 #define NOLOGGING 1
36#endif
37
38#define fclose(a) DosClose(a)
39#define SEEK_SET FILE_BEGIN
40#define SEEK_END FILE_END
41
42#define WORD unsigned short int
43#define DWORD unsigned long int
44
45/* "@#IBM:14.039#@ os2krnl... "*/
46/* "@#IBM:8.264#@ os2krnl... "*/
47#define KERNEL_ID_STRING_LENGTH 42
48#define KERNEL_READ_SIZE 512
49
50#define INCL_BASE
51#define INCL_DOS
52#define INCL_NOPMAPI
53
54/*******************************************************************************
55* Header Files *
56*******************************************************************************/
57#include <os2.h>
58
59#include <exe386.h>
60#include <strat2.h>
61#include <reqpkt.h>
62
63#include "devSegDf.h"
64#undef DATA16_INIT
65#define DATA16_INIT
66#undef CODE16_INIT
67#define CODE16_INIT
68#include "os2krnl.h" /* must be included before dev1632.h! */
69#include "sym.h"
70#include "probkrnl.h"
71#include "dev16.h"
72#include "dev1632.h"
73#include "vprntf16.h"
74#include "log.h"
75#include "options.h"
76#include "errors.h"
77
78/*******************************************************************************
79* Global Variables *
80* Note: must be inited or else we'll get BSS segment *
81*******************************************************************************/
82
83
84/*
85 * aImportTab defines the imported and overloaded OS/2 kernel functions.
86 * IMPORTANT: aImportTab has two sibling arrays, one in d32init.c, aulProc, and
87 * the calltab.asm, which must match entry by entry.
88 * When adding/removing/shuffling items in aImportTab, aulProc and
89 * calltab.asm has to be updated immediately!
90 */
91IMPORTKRNLSYM DATA16_GLOBAL aImportTab[NBR_OF_KRNLIMPORTS] =
92{/* iFound cchName offObject usSel fType */
93 /* iObject achName ulAddress cProlog */
94 {FALSE, -1, 8, "_ldrRead", -1, -1, -1, -1, EPT_PROC32}, /* 0 */
95 {FALSE, -1, 8, "_ldrOpen", -1, -1, -1, -1, EPT_PROC32}, /* 1 */
96 {FALSE, -1, 9, "_ldrClose", -1, -1, -1, -1, EPT_PROC32}, /* 2 */
97 {FALSE, -1, 12, "_LDRQAppType", -1, -1, -1, -1, EPT_PROC32}, /* 3 */
98 {FALSE, -1, 20, "_ldrEnum32bitRelRecs", -1, -1, -1, -1, EPT_PROC32}, /* 4 */
99 {FALSE, -1, 10, "_IOSftOpen", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 5 */
100 {FALSE, -1, 11, "_IOSftClose", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 6 */
101 {FALSE, -1, 15, "_IOSftTransPath", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 7 */
102 {FALSE, -1, 12, "_IOSftReadAt", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 8 */
103 {FALSE, -1, 13, "_IOSftWriteAt", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 9 */
104 {FALSE, -1, 12, "_SftFileSize", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 10 */
105 {FALSE, -1, 11, "_VMAllocMem", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 11 */
106 {FALSE, -1, 11, "_VMGetOwner", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 12 */
107 {FALSE, -1, 11, "g_tkExecPgm", -1, -1, -1, -1, EPT_PROC32}, /* 13 */
108 {FALSE, -1, 15, "_tkStartProcess", -1, -1, -1, -1, EPT_PROC32}, /* 14 */
109 {FALSE, -1, 11, "f_FuStrLenZ", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 15 */
110 {FALSE, -1, 10, "f_FuStrLen", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 16 */
111 {FALSE, -1, 8, "f_FuBuff", -1, -1, -1, -1, EPT_PROCIMPORT16}, /* 17 */
112 {FALSE, -1, 16, "_VMObjHandleInfo", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 18 */
113 {FALSE, -1, 21, "_ldrASMpMTEFromHandle",-1, -1, -1, -1, EPT_PROCIMPORT32}, /* 19 */
114 {FALSE, -1, 12, "_ldrOpenPath", -1, -1, -1, -1, EPT_PROC32}, /* 20 */
115 {FALSE, -1, 12, "_LDRClearSem", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 21 */
116 {FALSE, -1, 14, "_ldrFindModule", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 22 */
117 {FALSE, -1, 17, "_KSEMRequestMutex", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 23 */
118 {FALSE, -1, 17, "_KSEMReleaseMutex", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 24 */
119 {FALSE, -1, 15, "_KSEMQueryMutex", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 25 */
120 {FALSE, -1, 9, "_KSEMInit", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 26 */
121 {FALSE, -1, 7, "_LdrSem", -1, -1, -1, -1, EPT_VARIMPORT32}, /* 27 */
122 {FALSE, -1, 11, "_LDRLibPath", -1, -1, -1, -1, EPT_VARIMPORT32}, /* 28 */
123 {FALSE, -1, 9, "_TKSuBuff", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 29 */
124 {FALSE, -1, 9, "_TKFuBuff", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 30 */
125 {FALSE, -1, 11, "_TKFuBufLen", -1, -1, -1, -1, EPT_PROCIMPORT32}, /* 31 */
126 {FALSE, -1, 21, "_ldrValidateMteHandle",-1, -1, -1, -1, EPT_PROCIMPORT32}, /* 32 */
127 {FALSE, -1, 8, "_pTCBCur", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 33 */
128 {FALSE, -1, 9, "_pPTDACur", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 34 */
129 {FALSE, -1, 10, "ptda_start", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 35 */
130 {FALSE, -1, 12, "ptda_environ", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 36 */
131 {FALSE, -1, 12, "ptda_ptdasem", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 37 */
132 {FALSE, -1, 11, "ptda_module", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 38 */
133 {FALSE, -1, 18, "ptda_pBeginLIBPATH", -1, -1, -1, -1, EPT_VARIMPORT16}, /* 39 */
134 {FALSE, -1, 16, "_ldrpFileNameBuf", -1, -1, -1, -1, EPT_VARIMPORT32}, /* 40 */
135 {FALSE, -1, 14, "SecPathFromSFN", -1, -1, -1, -1, EPT_PROCIMPORTNR32},/* 41 */
136
137};
138
139/**
140 * szSymbolFile holds the name of the symbol file used.
141 *
142 */
143char DATA16_GLOBAL szSymbolFile[60] = {0};
144
145/**
146 * iProc holds the number of the procedure which failed during verify.
147 */
148int DATA16_GLOBAL iProc = -1; /* The procedure number which failed Verify. */
149
150
151
152/*
153 * privat data
154 */
155#if defined(DEBUGR3)
156static char DATA16_INIT szUsrOS2Krnl[50] = {0};
157static char DATA16_INIT szOS2Krnl[] = {"c:\\os2krnl"};
158#endif
159static char * DATA16_INIT apszSym[] =
160{
161 {"c:\\os2krnl.sym"}, /* usual for debugkernel */
162 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlr.sym"}, /* warp 4 */
163 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnld.sym"}, /* warp 4 */
164 {"c:\\os2\\pdpsi\\pmdf\\warp4\\os2krnlb.sym"}, /* warp 4 */
165 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlr.sym"}, /* warp 45 */
166 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnld.sym"}, /* warp 45 */
167 {"c:\\os2\\pdpsi\\pmdf\\warp45_u\\os2krnlb.sym"}, /* warp 45 */
168 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlr.sym"}, /* warp 45 */
169 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnld.sym"}, /* warp 45 */
170 {"c:\\os2\\pdpsi\\pmdf\\warp45_s\\os2krnlb.sym"}, /* warp 45 */
171 {"c:\\os2\\system\\trace\\os2krnl.sym"}, /* warp 3 ?*/
172 {"c:\\os2\\system\\pmdf\\os2krnlr.sym"}, /* warp 3 ?*/
173 {"c:\\os2krnlr.sym"}, /* custom */
174 {"c:\\os2krnlh.sym"}, /* custom */
175 {"c:\\os2krnld.sym"}, /* custom */
176 NULL
177};
178
179/* Result from GetKernelInfo/ReadOS2Krnl. */
180static unsigned char DATA16_INIT cObjects = 0;
181static POTE DATA16_INIT paKrnlOTEs = NULL;
182
183
184/*
185 *
186 */
187static struct
188{
189 short sErr;
190 const char *pszMsg;
191} DATA16_INIT aErrorMsgs[] =
192{
193 {ERROR_PROB_KRNL_OPEN_FAILED, "Krnl: Failed to open kernel file."},
194 {ERROR_PROB_KRNL_SEEK_SIZE, "Krnl: Failed to seek to end to of file."},
195 {ERROR_PROB_KRNL_SEEK_FIRST, "Krnl: Failed to start of file."},
196 {ERROR_PROB_KRNL_READ_FIRST, "Krnl: Failed to read (first)."},
197 {ERROR_PROB_KRNL_READ_NEXT, "Krnl: Failed to read."},
198 {ERROR_PROB_KRNL_TAG_NOT_FOUND, "Krnl: Build level tag was not found."},
199 {ERROR_PROB_KRNL_INV_SIGANTURE, "Krnl: Invalid build level signature."},
200 {ERROR_PROB_KRNL_INV_BUILD_NBR, "Krnl: Invalid build level number."},
201 {ERROR_PROB_KRNL_BUILD_VERSION, "Krnl: Invalid build level version."},
202 {ERROR_PROB_KRNL_MZ_SEEK, "Krnl: Failed to seek to start of file. (MZ)"},
203 {ERROR_PROB_KRNL_MZ_READ, "Krnl: Failed to read MZ header."},
204 {ERROR_PROB_KRNL_NEOFF_INVALID, "Krnl: Invalid new-header offset in MZ header."},
205 {ERROR_PROB_KRNL_NEOFF_SEEK, "Krnl: Failed to seek to new-header offset."},
206 {ERROR_PROB_KRNL_LX_READ, "Krnl: Failed to read LX header."},
207 {ERROR_PROB_KRNL_LX_SIGNATURE, "Krnl: Invalid LX header signature."},
208 {ERROR_PROB_KRNL_OBJECT_CNT, "Krnl: Object count don't match the running kernel."},
209 {ERROR_PROB_KRNL_OBJECT_CNR_10, "Krnl: Less than 10 objects - not a valid kernel file!"},
210 {ERROR_PROB_KRNL_OTE_SEEK, "Krnl: Failed to seek to OTEs."},
211 {ERROR_PROB_KRNL_OTE_READ, "Krnl: Failed to read OTEs."},
212 {ERROR_PROB_KRNL_OTE_SIZE_MIS, "Krnl: Size of a OTE didn't match the running kernel."},
213
214 /*
215 * ProbeSymFile error messages + some extra ones.
216 */
217 {ERROR_PROB_SYM_FILE_NOT_FOUND, "Sym: Symbol file was not found."},
218 {ERROR_PROB_SYM_READERROR, "Sym: Read failed."},
219 {ERROR_PROB_SYM_INVALID_MOD_NAME, "Sym: Invalid module name (not OS2KRNL)."},
220 {ERROR_PROB_SYM_SEGS_NE_OBJS, "Sym: Number of segments don't match the object count of the kernel."},
221 {ERROR_PROB_SYM_SEG_DEF_SEEK, "Sym: Failed to seek to a segment definition."},
222 {ERROR_PROB_SYM_SEG_DEF_READ, "Sym: Failed to read a segment definition."},
223 {ERROR_PROB_SYM_IMPORTS_NOTFOUND, "Sym: Some of the imports wasn't found."},
224 {ERROR_PROB_SYM_V_PROC_NOT_FND, "Sym: Verify failed: Procedure not found."},
225 {ERROR_PROB_SYM_V_OBJ_OR_ADDR, "Sym: Verify failed: Invalid object or address."},
226 {ERROR_PROB_SYM_V_ADDRESS, "Sym: Verify failed: Invalid address."},
227 {ERROR_PROB_SYM_V_PROLOG, "Sym: Verify failed: Invalid prolog."},
228 {ERROR_PROB_SYM_V_NOT_IMPL, "Sym: Verify failed: Not implemented."},
229 {ERROR_PROB_SYM_V_GETOS2KRNL, "GetOs2Krnl: failed."},
230 {ERROR_PROB_SYM_V_NO_SWAPMTE, "GetOs2Krnl: No Swap MTE."},
231 {ERROR_PROB_SYM_V_OBJECTS, "GetOs2Krnl: Too many objects."},
232 {ERROR_PROB_SYM_V_OBJECT_TABLE, "GetOs2Krnl: No object table."},
233 {ERROR_PROB_SYM_V_BUILD_INFO, "GetOs2Krnl: Build info not found."},
234 {ERROR_PROB_SYM_V_INVALID_BUILD, "GetOs2Krnl: Unsupported build."},
235 {ERROR_PROB_SYM_V_VERIFY, "importTabInit: Import failed."},
236 {ERROR_PROB_SYM_V_IPE, "importTabInit: Internal-Processing-Error."},
237 {ERROR_PROB_SYM_V_HEAPINIT, "R0Init32: HeapInit Failed."},
238 {ERROR_PROB_SYM_V_D32_LDR_INIT, "R0Init32: ldrInit Failed."},
239
240 {ERROR_PROB_SYMDB_KRNL_NOT_FOUND, "SymDB: Kernel was not found."}
241};
242
243/*
244 * Fake data for Ring-3 testing.
245 */
246#ifdef R3TST
247USHORT DATA16_INIT usFakeVerMajor = 0;
248USHORT DATA16_INIT usFakeVerMinor = 0;
249#ifdef R3TST
250static DATA16_INIT ach[11] = {0}; /* works around compiler/linker bug */
251#endif
252#endif
253
254
255/*******************************************************************************
256* Internal Functions *
257*******************************************************************************/
258/* File an output replacements */
259static HFILE fopen(const char * pszFilename, const char * pszIgnored);
260static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile);
261static int fseek(HFILE hfile, signed long off, int iOrg);
262static unsigned long fsize(HFILE hFile);
263
264/* C-library replacements and additions. */
265static void kmemcpy(char *psz1, const char *psz2, int cch);
266static char * kstrstr(const char *psz1, const char *psz2);
267static int kstrcmp(const char *psz1, const char *psz2);
268static int kstrncmp(const char *psz1, const char *psz2, int cch);
269static int kstrnicmp(const char *psz1, const char *psz2, int cch);
270static int kstrlen(const char *psz);
271static char * kstrcpy(char * pszTarget, const char * pszSource);
272static int kargncpy(char *pszTarget, const char *pszArg, unsigned cchMaxlen);
273
274/* Workers */
275static int LookupKrnlEntry(unsigned short usBuild, unsigned short fKernel, unsigned char cObjects);
276static int VerifyPrologs(void);
277static int ProbeSymFile(const char *pszFilename);
278static int GetKernelInfo(void);
279
280/* Ouput */
281static void ShowResult(int rc);
282
283/* Others used while debugging in R3. */
284static int VerifyKernelVer(void);
285static int ReadOS2Krnl(char *pszFilename);
286static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl);
287static int processFile(const char *pszFilename);
288
289#if 0 /*ndef CODE16_INIT*/
290#pragma alloc_text(CODE16_INIT, fopen, fread, fseek, fsize)
291#pragma alloc_text(CODE16_INIT, kmemcpy, kstrstr, kstrcmp, kstrncmp, kstrnicmp, kstrlen, kstrcpy, kargncpy)
292#pragma alloc_text(CODE16_INIT, GetErrorMsg)
293#pragma alloc_text(CODE16_INIT, LookupKrnlEntry, VerifyPrologs, ProbeSymFile, GetKernelInfo)
294#pragma alloc_text(CODE16_INIT, ShowResult)
295#pragma alloc_text(CODE16_INIT, VerifyKernelVer, ReadOS2Krnl, ReadOS2Krnl2, processFile)
296#endif
297
298
299
300/*******************************************************************************
301* Implementation of Internal Helper Functions *
302*******************************************************************************/
303
304/**
305 * Quick implementation of fopen.
306 * @param pszFilename name of file to open (sz)
307 * @param pszIgnored whatever - it is ignored
308 * @return Handle to file. (not pointer to a FILE stream as in C-library)
309 * @remark binary and readonly is assumed!
310 */
311static HFILE fopen(const char * pszFilename, const char * pszIgnored)
312{
313 HFILE hFile = 0;
314 USHORT rc;
315 unsigned short Action = 0;
316
317 rc = DosOpen(
318 (char*)pszFilename,
319 &hFile,
320 &Action,
321 0,
322 FILE_NORMAL,
323 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
324 OPEN_SHARE_DENYNONE + OPEN_ACCESS_READONLY,
325 NULL);
326
327 pszIgnored = pszIgnored;
328 return hFile;
329}
330
331
332/**
333 * fread emulation
334 * @returns Number of blocks read.
335 * @param pvBuffer Buffer to read into
336 * @param cbBlock Blocksize
337 * @param cBlock Block count
338 * @param hFile Handle to file (HFILE)
339 */
340static int fread(void * pvBuffer, USHORT cbBlock, USHORT cBlock, HFILE hFile)
341{
342 USHORT ulRead;
343 USHORT rc;
344
345 rc = DosRead(hFile, pvBuffer, (USHORT)(cbBlock*cBlock), &ulRead);
346 if (rc == 0)
347 rc = (USHORT)cBlock;
348 else
349 rc = 0;
350
351 return rc;
352}
353
354
355/**
356 * fseek emultation
357 * @returns Same as DosChgFilePtr
358 * @param hFile Filehandle
359 * @param off offset into file from origin
360 * @param org origin
361 */
362static int fseek(HFILE hFile, signed long off, int iOrg)
363{
364 ULONG ul;
365 return (int)DosChgFilePtr(hFile, off, iOrg, &ul);
366}
367
368
369/**
370 * Get filesize in bytes.
371 * @returns Filesize.
372 * @param hFile Filehandle
373 * @remark This function sets the file position to end of file.
374 */
375static unsigned long fsize(HFILE hFile)
376{
377 USHORT rc;
378 unsigned long cb;
379
380 rc = DosChgFilePtr(hFile, 0, FILE_END, &cb);
381
382 return cb;
383}
384
385
386/**
387 * kmemcpy - memory copy - slow!
388 * @param psz1 target
389 * @param psz2 source
390 * @param cch length
391 */
392static void kmemcpy(char *psz1, const char *psz2, int cch)
393{
394 while (cch-- != 0)
395 *psz1++ = *psz2++;
396}
397
398
399/**
400 * Finds psz2 in psz2.
401 * @returns Pointer to occurence of psz2 in psz1.
402 * @param psz1 String to be search.
403 * @param psz2 Substring to search for.
404 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
405 */
406static char *kstrstr(const char *psz1, const char *psz2)
407{
408 while (*psz1 != '\0')
409 {
410 register int i = 0;
411 while (psz2[i] != '\0' && psz1[i] == psz2[i])
412 i++;
413
414 /* found it? */
415 if (psz2[i] == '\0')
416 return (char*)psz1;
417 if (psz1[i] == '\0' )
418 break;
419 psz1++;
420 }
421
422 return NULL;
423}
424
425
426#if 0 /* not in use */
427/**
428 * kstrcmp - String compare
429 * @returns 0 - equal else !0
430 * @param psz1 String 1
431 * @param psz2 String 2
432 */
433static int kstrcmp(const char *psz1, const char *psz2);
434{
435 while (*psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
436 {
437 psz1++;
438 psz2++;
439 }
440 return *psz1 - *psz2;
441}
442#endif
443
444
445/**
446 * kstrncmp - String 'n' compare.
447 * @returns 0 - equal else !0
448 * @param p1 String 1
449 * @param p2 String 2
450 * @param len length
451 */
452static int kstrncmp(register const char *psz1, register const char *psz2, int cch)
453{
454 int i = 0;
455 while (i < cch && *psz1 == *psz2 && *psz1 != '\0' && *psz2 != '\0')
456 {
457 psz1++;
458 psz2++;
459 i++;
460 }
461
462 return i - cch;
463}
464
465
466#if 0 /* not in use */
467/**
468 * kstrnicmp - String 'n' compare, case-insensitive.
469 * @returns 0 - equal else !0
470 * @param p1 String 1
471 * @param p2 String 2
472 * @param len length
473 */
474static int kstrnicmp(const char *psz1, const char *psz2, int cch)
475{
476 register char ch1, ch2;
477
478 do
479 {
480 ch1 = *psz1++;
481 if (ch1 >= 'A' && ch1 <= 'Z')
482 ch1 += 'a' - 'A'; /* to lower case */
483 ch2 = *psz2++;
484 if (ch2 >= 'A' && ch2 <= 'Z')
485 ch2 += 'a' - 'A'; /* to lower case */
486 } while (--cch > 0 && ch1 == ch2 && ch1 != '\0' && ch2 != '\0');
487
488 return ch1 - ch2;
489}
490#endif
491
492
493/**
494 * kstrlen - String length.
495 * @returns Length of the string.
496 * @param psz Pointer to string.
497 * @status completely implemented and tested.
498 * @author knut st. osmundsen
499 */
500static int kstrlen(register const char * psz)
501{
502 register int cch = 0;
503 while (*psz++ != '\0')
504 cch++;
505 return cch;
506}
507
508
509/**
510 * String copy (strcpy).
511 * @returns Pointer to target string.
512 * @param pszTarget Target string.
513 * @param pszSource Source string.
514 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
515 */
516static char * kstrcpy(char * pszTarget, register const char * pszSource)
517{
518 register char *psz = pszTarget;
519
520 while (*pszSource != '\0')
521 *psz++ = *pszSource++;
522 *psz = '\0';
523 return pszTarget;
524}
525
526
527
528
529/**
530 * Copy an argument to a buffer. Ie. "-K[=|:]c:\os2krnl ....". Supports quotes
531 * @returns Number of chars of pszArg that has been processed.
532 * @param pszTarget - pointer to target buffer.
533 * @param pszArg - pointer to source argument string.
534 * @param cchMaxlen - maximum chars to copy.
535 */
536static int kargncpy(char * pszTarget, const char * pszArg, unsigned cchMaxlen)
537{
538 int i = 0;
539 int fQuote = FALSE;
540
541 /* skip option word/letter */
542 while (*pszArg != '\0' && *pszArg != ' ' && *pszArg != ':' &&
543 *pszArg != '=' && *pszArg != '-' && *pszArg != '/')
544 {
545 pszArg++;
546 i++;
547 }
548
549 if (*pszArg == ' ' || *pszArg == '-' || *pszArg == '/' || *pszArg == '\0')
550 return 0;
551
552
553 do
554 {
555 pszArg++;
556 i++;
557 } while (*pszArg != '\0' && *pszArg == ' ');
558
559 /* copy maxlen or less */
560 /* check for quotes */
561 if (*pszArg == '"')
562 {
563 fQuote = TRUE;
564 pszArg++;
565 i++;
566 }
567 /* copy loop */
568 while (cchMaxlen > 1 && (fQuote ? *pszArg != '"' : *pszArg != ' ') && *pszArg != '\0')
569 {
570 *pszTarget++ = *pszArg++;
571 i++;
572 cchMaxlen--;
573 }
574
575 /* terminate pszTarget */
576 pszTarget = '\0';
577
578 return i;
579}
580
581
582/**
583 * Get the message text for an error message.
584 * @returns Pointer to error text. NULL if not found.
585 * @param sErr Error code id.
586 * @status completely implemented.
587 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
588 */
589const char * GetErrorMsg(short sErr)
590{
591 int i;
592 for (i = 0; i < sizeof(aErrorMsgs) / sizeof(aErrorMsgs[0]); i++)
593 {
594 if (aErrorMsgs[i].sErr == sErr)
595 return aErrorMsgs[i].pszMsg;
596 }
597 return NULL;
598}
599
600
601
602/*******************************************************************************
603* Implementation Of The Important Functions *
604*******************************************************************************/
605#ifndef EXTRACT
606/**
607 * Checks if this kernel is within the kernel symbol database.
608 * If an entry for the kernel is found, the data is copied from the
609 * database entry to aImportTab.
610 * @returns NO_ERROR on succes (0)
611 * 1 if not found.
612 * Error code on error.
613 * @param usBuild Build level.
614 * @param fKernel Kernel (type) flags. (KF_* from options.h)
615 * @param cObjects Count of object in the running kernel.
616 * @sketch Loop thru the table.
617 * @status completely implemented.
618 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
619 */
620static int LookupKrnlEntry(unsigned short usBuild, unsigned short fKernel, unsigned char cObjects)
621{
622 int i;
623
624 /*
625 * Loop tru the DB entries until a NULL pointer is found.
626 */
627 for (i = 0; aKrnlSymDB[i].usBuild != 0; i++)
628 {
629 if ( aKrnlSymDB[i].usBuild == usBuild
630 && aKrnlSymDB[i].fKernel == fKernel
631 && aKrnlSymDB[i].cObjects == cObjects)
632 { /* found matching entry! */
633 int j;
634 int rc;
635 register PKRNLDBENTRY pEntry = &aKrnlSymDB[i];
636
637 dprintf(("LookUpKrnlEntry - found entry for this kernel!\n"));
638
639 /*
640 * Copy symbol data from the DB to aImportTab.
641 */
642 for (j = 0; j < NBR_OF_KRNLIMPORTS; j++)
643 {
644 aImportTab[j].offObject = pEntry->aSyms[j].offObject;
645 aImportTab[j].iObject = pEntry->aSyms[j].iObject;
646 aImportTab[j].ulAddress = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_base
647 + pEntry->aSyms[j].offObject;
648 aImportTab[j].usSel = paKrnlOTEs[pEntry->aSyms[j].iObject].ote_sel;
649 aImportTab[j].fFound = (char)((aImportTab[j].offObject != 0xFFFFFFFFUL) ? 1 : 0);
650 dprintf((" %-3d addr=0x%08lx off=0x%08lx %s\n",
651 j, aImportTab[j].ulAddress, aImportTab[j].offObject,
652 aImportTab[j].achName));
653 }
654
655 /* Verify prologs*/
656 rc = VerifyPrologs();
657
658 /* set sym name on success or complain on error */
659 if (rc == 0)
660 kstrcpy(szSymbolFile, "Win32k Symbol Database");
661 else
662 {
663 printf16("Warning: The Win32k Symbol Database entry found.\n"
664 " But, VerifyPrologs() returned rc=0x%x and iProc=%d\n", rc, iProc);
665 DosSleep(3000);
666 }
667
668 return rc;
669 }
670 }
671
672 /* not found */
673 return ERROR_PROB_SYMDB_KRNL_NOT_FOUND;
674}
675#endif /* !EXTRACT */
676
677
678/**
679 * Verifies the that the addresses in aImportTab are valid.
680 * This is done at Ring-0 of course.
681 * @returns NO_ERROR (ie. 0) on success. iProc = -1
682 * The appropriate OS/2 or Win32k return code on success. iProc
683 * is set to the failing procedure (if appliable).
684 */
685static int VerifyPrologs(void)
686{
687#if !defined(DEBUGR3) && !defined(EXTRACT)
688 APIRET rc;
689 HFILE hDev0 = 0;
690 USHORT usAction = 0;
691
692 /* Set the failing procedure number to -1. */
693 iProc = -1;
694
695 /* Open the elf device driver. */
696 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
697 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
698 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
699 0UL);
700 if (rc == NO_ERROR)
701 {
702 D16VERIFYIMPORTTABDATA Data = {0};
703
704 /* Issue the VerifyImportTab IOCtl call. */
705 rc = DosDevIOCtl(&Data, "", D16_IOCTL_VERIFYIMPORTTAB, D16_IOCTL_CAT, hDev0);
706 DosClose(hDev0);
707 if (rc == NO_ERROR)
708 {
709 if (Data.usRc != NO_ERROR)
710 {
711 /* set the appropriate return values. */
712 rc = (Data.usRc & ERROR_D32_ERROR_MASK) + ERROR_PROB_SYM_D32_FIRST;
713 if (Data.usRc & ERROR_D32_PROC_FLAG)
714 iProc = (Data.usRc & ERROR_D32_PROC_MASK) >> ERROR_D32_PROC_SHIFT;
715 }/* else success */
716 }
717 else
718 {
719 dprintf(("DosDevIOCtl failed with rc=%d\n", rc));
720 DosSleep(3000);
721 }
722 }
723 else
724 {
725 dprintf(("DosOpen Failed with rc=%d\n", rc));
726 DosSleep(3000);
727 }
728
729 return rc;
730#else
731 return 0;
732#endif
733}
734
735
736/**
737 * Check a symbol file. Searches for the wanted entry-point addresses.
738 * @returns 0 on success - something else on failiure.
739 * @param pszFilename Name of file to probe.
740 * @precond Must be called after kernel-file is found and processed.
741 * @remark Error codes starts at -50.
742 */
743static int ProbeSymFile(const char * pszFilename)
744{
745 HFILE hSym; /* Filehandle */
746 int cLeftToFind; /* Symbols left to find */
747 unsigned long iSeg; /* Outer search loop: Segment number */
748 unsigned iSym; /* Middle search loop: Symbol number */
749 unsigned i; /* Inner search loop: ProcTab index */
750 int rc;
751
752 MAPDEF MapDef; /* Mapfile header */
753 SEGDEF SegDef; /* Segment header */
754 SYMDEF32 SymDef32; /* Symbol definition 32-bit */
755 SYMDEF16 SymDef16; /* Symbol definition 16-bit */
756 char achBuffer[256]; /* Name buffer */
757 unsigned long offSegment; /* Segment definition offset */
758 unsigned long offSymPtr; /* Symbol pointer(offset) offset */
759 unsigned short offSym; /* Symbol definition offset */
760
761
762 /*
763 * Open the symbol file
764 */
765 hSym = fopen(pszFilename, "rb");
766 if (hSym==0)
767 {
768 dprintf(("Error opening file %s\n", pszFilename));
769 return ERROR_PROB_SYM_FILE_NOT_FOUND;
770 }
771 dprintf(("\nSuccessfully opened symbolfile: %s\n", pszFilename));
772
773
774 /*
775 * (Open were successfully.)
776 * Now read header and display it.
777 */
778 rc = fread(&MapDef, sizeof(MAPDEF), 1, hSym);
779 if (!rc)
780 { /* oops! read failed, close file and fail. */
781 fclose(hSym);
782 return ERROR_PROB_SYM_READERROR;
783 }
784 achBuffer[0] = MapDef.achModName[0];
785 fread(&achBuffer[1], 1, MapDef.cbModName, hSym);
786 achBuffer[MapDef.cbModName] = '\0';
787 dprintf(("*Module name: %s\n", achBuffer));
788 dprintf(("*Segments: %d\n*MaxSymbolLength: %d\n", MapDef.cSegs, MapDef.cbMaxSym));
789 dprintf(("*ppNextMap: 0x%x\n", MapDef.ppNextMap ));
790
791
792 /*
793 * Verify that the modulename of the symbol file is OS2KRNL.
794 */
795 if (MapDef.cbModName == 7 && kstrncmp(achBuffer, "OS2KRNL", 7) != 0)
796 { /* modulename was not OS2KRNL, fail. */
797 dprintf(("Modulename verify failed\n"));
798 fclose(hSym);
799 return ERROR_PROB_SYM_INVALID_MOD_NAME;
800 }
801
802
803 /*
804 * Verify that the number of segments is equal to the number objects in OS2KRNL.
805 */
806 #ifndef EXTRACT
807 if (MapDef.cSegs != cObjects)
808 { /* incorrect count of segments. */
809 dprintf(("Segment No. verify failed\n"));
810 fclose(hSym);
811 return ERROR_PROB_SYM_SEGS_NE_OBJS;
812 }
813 #endif /* !EXTRACT */
814
815
816 /*
817 * Reset ProcTab
818 */
819 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
820 {
821 aImportTab[i].fFound = 0;
822 #ifdef DEBUG
823 aImportTab[i].offObject = 0;
824 aImportTab[i].ulAddress = 0;
825 aImportTab[i].usSel = 0;
826 #endif
827 }
828
829
830 /*
831 * Fileoffset of the first segment.
832 * And set cLeftToFind.
833 */
834 offSegment = SEGDEFOFFSET(MapDef);
835 cLeftToFind = NBR_OF_KRNLIMPORTS;
836
837 /*
838 * Search thru the entire file, segment by segment.
839 *
840 * ASSUME: last segment is the only 32-bit code segment.
841 *
842 */
843 for (iSeg = 0; iSeg < MapDef.cSegs; iSeg++, offSegment = NEXTSEGDEFOFFSET(SegDef))
844 {
845 int fSegEPTBitType; /* Type of segment, 16 or 32 bit, expressed in EPT_XXBIT flags */
846 int fCode; /* Set if this is a code segment, else clear. */
847
848 /*
849 * Read the segment definition.
850 */
851 if (fseek(hSym, offSegment, SEEK_SET))
852 { /* Failed to seek to the segment definition, fail! */
853 fclose(hSym);
854 return ERROR_PROB_SYM_SEG_DEF_SEEK;
855 }
856 rc = fread(&SegDef, sizeof(SEGDEF), 1, hSym);
857 if (!rc)
858 { /* Failed to read the segment definition, fail! */
859 fclose(hSym);
860 return ERROR_PROB_SYM_SEG_DEF_READ;
861 }
862
863 /*
864 * Some debugging info.
865 */
866 achBuffer[0] = SegDef.achSegName[0];
867 fread(&achBuffer[1], 1, SegDef.cbSegName, hSym);
868 achBuffer[SegDef.cbSegName] = '\0';
869 dprintf(("Segment %.2li Flags=0x%02x cSymbols=0x%04x Name=%s\n",
870 iSeg, SegDef.bFlags, SegDef.cSymbols, &achBuffer[0]));
871
872 /*
873 * Determin segment bit type.
874 */
875 fSegEPTBitType = SEG32BitSegment(SegDef) ? EPT_32BIT : EPT_16BIT;
876 fCode = kstrstr(achBuffer, "CODE") != NULL;
877
878 /*
879 * Search thru all the symbols in this segment
880 * while we look for the requested symbols in aImportTab.
881 */
882 for (iSym = 0; iSym < SegDef.cSymbols && cLeftToFind; iSym++)
883 {
884 IMPORTKRNLSYM * pImport;
885 unsigned cchName;
886
887 /*
888 * Fileoffset of the current symbol.
889 * Set filepointer to that position.
890 * Read word (which is the offset of the symbol).
891 */
892 offSymPtr = SYMDEFOFFSET(offSegment, SegDef, iSym);
893 rc = fseek(hSym, offSymPtr, SEEK_SET);
894 if (rc)
895 { /* Symboloffset seek failed, try read next symbol. */
896 dprintf(("Warning: Seek failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
897 continue;
898 }
899 rc = fread(&offSym, sizeof(unsigned short int), 1, hSym);
900 if (!rc)
901 { /* Symboloffset read failed, try read next symbol. */
902 dprintf(("Warning: read failed (offSymPtr=%d, rc=%d)\n", offSymPtr, rc));
903 continue;
904 }
905 rc = fseek(hSym, offSym + offSegment, SEEK_SET);
906 if (rc)
907 { /* Symbol Seek failed, try read next symbol. */
908 dprintf(("Warning: Seek failed (offSym=%d, rc=%d)\n", offSym, rc));
909 continue;
910 }
911
912
913 /*
914 * Read symbol and symbolname.
915 */
916 if (SegDef.bFlags & 0x01)
917 rc = fread(&SymDef32, sizeof(SYMDEF32), 1, hSym);
918 else
919 rc = fread(&SymDef16, sizeof(SYMDEF16), 1, hSym);
920 if (!rc)
921 { /* Symbol read failed, try read next symbol */
922 dprintf(("Warning: Read(1) failed (offSym=%d, rc=%d)\n", offSym, rc));
923 continue;
924 }
925 achBuffer[0] = (SegDef.bFlags & 0x01) ? SymDef32.achSymName[0] : SymDef16.achSymName[0];
926 cchName = (SegDef.bFlags & 0x01) ? SymDef32.cbSymName : SymDef16.cbSymName;
927 rc = fread(&achBuffer[1], 1, cchName, hSym);
928 if (!rc)
929 { /* Symbol read failed, try read next symbol */
930 dprintf(("Warning: Read(2) failed (offSym=%d, rc=%d)\n", offSym, rc));
931 continue;
932 }
933 achBuffer[cchName] = '\0';
934
935
936 /*
937 * Search proctable.
938 */
939 for (i = 0, pImport = &aImportTab[0]; i < NBR_OF_KRNLIMPORTS; i++, pImport++)
940 {
941 if (!pImport->fFound /* Not allready found */
942 && (pImport->fType & EPT_VARIMPORT ? !fCode : fCode) /* Don't look for code in a data segment */
943 && pImport->cchName == cchName /* Equal name length */
944 && kstrncmp(pImport->achName, achBuffer, cchName) == 0 /* Equal name */
945 )
946 { /* Symbol was found */
947 pImport->offObject = (SegDef.bFlags & 0x01 ? SymDef32.wSymVal : SymDef16.wSymVal);
948 pImport->ulAddress = pImport->offObject + paKrnlOTEs[iSeg].ote_base;
949 pImport->iObject = (unsigned char)iSeg;
950 pImport->usSel = paKrnlOTEs[iSeg].ote_sel;
951 dprintf(("debug: base=%lx, size=%lx iSeg=%d\n", paKrnlOTEs[iSeg].ote_base, paKrnlOTEs[iSeg].ote_size, iSeg));
952
953 /* Paranoia test! */
954 #ifndef EXTRACT
955 if (pImport->offObject < paKrnlOTEs[iSeg].ote_size)
956 {
957 pImport->fFound = TRUE;
958 cLeftToFind--;
959 dprintf(("Found: %s at off 0x%lx addr 0x%lx, sel=0x%x\n",
960 pImport->achName, pImport->offObject,
961 pImport->ulAddress, pImport->usSel));
962 }
963 else/* test failed, continue on next symbol*/
964 dprintf(("Error: Paranoia test failed for %s\n", pImport->achName));;
965 #else
966 pImport->fFound = TRUE;
967 cLeftToFind--;
968 #endif /* !EXTRACT */
969 break;
970 }
971
972 } /* aImportTab for-loop */
973
974 } /* Symbol for-loop */
975
976 } /* Segment for-loop */
977
978 /*
979 * Close symbol file.
980 */
981 fclose(hSym);
982
983 /*
984 * If not all procedures were found fail.
985 */
986 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
987 if (!aImportTab[i].fFound && !(aImportTab[i].fType & EPT_NOT_REQ))
988 return ERROR_PROB_SYM_IMPORTS_NOTFOUND;
989
990 /*
991 * Verify function prologs and return.
992 */
993 return VerifyPrologs();
994}
995
996
997/**
998 * Get kernelinformation (OTEs (object table entries), build, type, debug...)
999 * @returns 0 on success.
1000 * options.ulBuild, fchType, fDebug, cObjects and paKrnlOTEs is set on successful return.
1001 * Not 0 on error.
1002 */
1003static int GetKernelInfo(void)
1004{
1005#if !defined(DEBUGR3) && !defined(EXTRACT) /* This IOCtl is not available after inittime! */
1006 static KRNLINFO DATA16_INIT KrnlInfo = {0};
1007 APIRET rc;
1008 HFILE hDev0 = 0;
1009 USHORT usAction = 0;
1010
1011 /*
1012 * Issue an IOCtl to elf$ to query kernel information.
1013 */
1014 rc = DosOpen("\\dev\\elf$", &hDev0, &usAction, 0UL, FILE_NORMAL,
1015 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
1016 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
1017 0UL);
1018 if (rc == NO_ERROR)
1019 {
1020 rc = DosDevIOCtl(&KrnlInfo, "", D16_IOCTL_GETKRNLINFO, D16_IOCTL_CAT, hDev0);
1021 if (rc == NO_ERROR)
1022 {
1023 #ifdef DEBUG
1024 unsigned i;
1025 #endif
1026
1027 /*
1028 * Set the exported parameters
1029 */
1030 options.ulBuild = KrnlInfo.ulBuild;
1031 options.fKernel = KrnlInfo.fKernel;
1032 cObjects = KrnlInfo.cObjects;
1033 paKrnlOTEs = &KrnlInfo.aObjects[0];
1034
1035 /*
1036 * If debugging probkrnl dump kernel OTEs.
1037 */
1038 #ifdef DEBUG
1039 dprintf(("debug: kernel OTE:\n"));
1040 for (i = 0; i < cObjects; i++)
1041 dprintf(("debug: no.%2d base=%lx size=%lx sel=%x\n",
1042 i,
1043 paKrnlOTEs[i].ote_base,
1044 paKrnlOTEs[i].ote_size,
1045 paKrnlOTEs[i].ote_sel));
1046 #endif
1047 }
1048 DosClose(hDev0);
1049 }
1050
1051 if (rc != NO_ERROR)
1052 printf16("Failed to get kernel OTEs. rc=%d\n", rc);
1053
1054 return rc;
1055
1056#else
1057 #ifndef EXTRACT
1058 APIRET rc;
1059
1060 /*--------------*/
1061 /* read kernel */
1062 /*--------------*/
1063 if (szUsrOS2Krnl[0] != '\0')
1064 {
1065 rc = ReadOS2Krnl(szUsrOS2Krnl);
1066 if (rc != NO_ERROR)
1067 {
1068 printf16("Warning: Invalid kernel file specified. Tries defaults.\n");
1069 szUsrOS2Krnl[0] = '\0';
1070 rc = ReadOS2Krnl(szOS2Krnl);
1071 }
1072 }
1073 else
1074 rc = ReadOS2Krnl(szOS2Krnl);
1075 return rc;
1076 #else
1077 return 0;
1078 #endif
1079#endif
1080}
1081
1082
1083/**
1084 * Shows result of kernelprobing if not quiet or on error.
1085 * @param rc Return code.
1086 */
1087#ifndef EXTRACT
1088static void ShowResult(int rc)
1089{
1090 int i;
1091
1092 /*
1093 * Complain even if quiet on error
1094 */
1095 if (!options.fQuiet || rc != NO_ERROR)
1096 {
1097 printf16("Win32k - Odin32 support driver.\n");
1098
1099 /*
1100 * kernel stuff
1101 */
1102 if (rc == NO_ERROR || rc > ERROR_PROB_KRNL_LAST)
1103 {
1104 #ifdef DEBUGR3
1105 printf16(" Found kernel: %s\n", szOS2Krnl);
1106 #endif
1107 printf16(" Build: %ld - v%d.%d\n",
1108 options.ulBuild, options.usVerMajor, options.usVerMinor);
1109 }
1110 else if (rc >= ERROR_PROB_KRNL_FIRST)
1111 printf16(" Kernel probing failed with rc=%d.\n", rc);
1112 else
1113 printf16(" Failed before probing kernel.\n");
1114
1115 /*
1116 * symbol-file
1117 */
1118 if (rc == NO_ERROR || (rc > ERROR_PROB_SYM_LAST && szSymbolFile[0] != '\0'))
1119 printf16(" Found symbolfile: %s\n", (NPSZ)szSymbolFile);
1120 else if (rc >= ERROR_PROB_SYM_FIRST)
1121 printf16(" Failed to find symbolfile!\n");
1122 else
1123 printf16(" Failed before searching for symbolfile.\n");
1124
1125 /*
1126 * function listing
1127 */
1128 if (options.fLogging)/* || rc != NO_ERROR)*/
1129 {
1130 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1131 {
1132 printf16(" %-21s at ", aImportTab[i].achName);
1133 if (aImportTab[i].fFound)
1134 printf16("0x%08lx%s", aImportTab[i].ulAddress, (i % 2) == 0 ? "" : "\n");
1135 else
1136 printf16("not found!%s", (i % 2) == 0 ? "" : "\n");
1137 }
1138 if (i % 2) printf16("\n");
1139 }
1140
1141 /*
1142 * Display error code.
1143 */
1144 if (rc != NO_ERROR)
1145 {
1146 const char *psz = GetErrorMsg(rc);
1147 printf16("ProbeKernel failed with rc=%d. iProc=%x\n", rc, iProc);
1148 if (psz) printf16("%s\n", psz);
1149 }
1150 }
1151}
1152
1153
1154/**
1155 * "main" function.
1156 * Note that the option -Noloader causes nothing to be done.
1157 * @returns 0 on success, something else on error.
1158 * @param pReqPack Pointer to init request packet
1159 * @remark
1160 */
1161int ProbeKernel(PRPINITIN pReqPack)
1162{
1163 int rc;
1164 int i;
1165 int n;
1166 SEL selGIS;
1167 SEL selLIS;
1168 PGINFOSEG pGIS;
1169 PLINFOSEG pLIS;
1170 USHORT usBootDrive;
1171
1172 /*----------------*/
1173 /* parse InitArgs */
1174 /*----------------*/
1175 if (pReqPack != NULL && pReqPack->InitArgs != NULL)
1176 {
1177 n = kstrlen(pReqPack->InitArgs);
1178 for (i = 0; i < n; i++)
1179 {
1180 if ((pReqPack->InitArgs[i] == '/' || pReqPack->InitArgs[i] == '-') && (i+1) < n)
1181 {
1182 i++;
1183 switch (pReqPack->InitArgs[i])
1184 {
1185 #if defined(DEBUGR3)
1186 case 'k':
1187 case 'K': /* Kernel file */
1188 i++;
1189 i += kargncpy(szUsrOS2Krnl, &pReqPack->InitArgs[i], sizeof(szUsrOS2Krnl));
1190 break;
1191 #endif
1192
1193 case 'n':
1194 case 'N': /* NoLoader */
1195 options.fNoLoader = TRUE;
1196 return 0;
1197
1198 case 'q':
1199 case 'Q': /* Quiet */
1200 options.fQuiet = TRUE;
1201 break;
1202
1203 case 's':
1204 case 'S': /* Symbol file */
1205 i++;
1206 if ( pReqPack->InitArgs[i] != 'c' && pReqPack->InitArgs[i] != 'C'
1207 && pReqPack->InitArgs[i] != 'm' && pReqPack->InitArgs[i] != 'M'
1208 ) /* -script and -smp is ignored */
1209 i += kargncpy(szSymbolFile, &pReqPack->InitArgs[i], sizeof(szSymbolFile));
1210 break;
1211
1212 case 'v':
1213 case 'V': /* Verbose */
1214 options.fQuiet = FALSE;
1215 break;
1216 }
1217 }
1218 }
1219 }
1220
1221 /*---------------------*/
1222 /* determin boot drive */
1223 /*---------------------*/
1224 rc = DosGetInfoSeg(&selGIS, &selLIS);
1225 if (rc != NO_ERROR)
1226 return rc;
1227
1228 pLIS = MAKEPLINFOSEG(selLIS);
1229 pGIS = MAKEPGINFOSEG(selGIS);
1230 usBootDrive = pGIS->bootdrive;
1231#ifndef R3TST
1232 options.usVerMajor = pGIS->uchMajorVersion;
1233 options.usVerMinor = pGIS->uchMinorVersion;
1234#else
1235 if (usFakeVerMajor == 0)
1236 {
1237 usFakeVerMajor = pGIS->uchMajorVersion;
1238 usFakeVerMinor = pGIS->uchMinorVersion;
1239 }
1240 options.usVerMajor = usFakeVerMajor;
1241 options.usVerMinor = usFakeVerMinor;
1242#endif
1243 dprintf(("BootDrive: %d\n", usBootDrive));
1244
1245 /* set driveletter in constants strings */
1246 usBootDrive = (char)usBootDrive + (char)'a' - 1;
1247 #if defined(DEBUGR3)
1248 szOS2Krnl[0] = (char)usBootDrive;
1249 #endif
1250 for (i = 0; apszSym[i] != NULL; i++)
1251 apszSym[i][0] = (char)usBootDrive;
1252
1253 /*-----------------*/
1254 /* get kernel info */
1255 /*-----------------*/
1256 rc = GetKernelInfo();
1257
1258 /*--------------*/
1259 /* read symfile */
1260 /*--------------*/
1261 if (!rc)
1262 {
1263 rc = 1;
1264 if (szSymbolFile[0] != '\0')
1265 {
1266 rc = ProbeSymFile(szSymbolFile);
1267 if (rc)
1268 {
1269 printf16("Warning: Invalid symbol file specified. rc=%x iProc=%d\n"
1270 " Tries defaults.\n", rc, iProc);
1271 szSymbolFile[0] = '\0';
1272 DosSleep(3000);
1273 }
1274 }
1275 if (rc != NO_ERROR) /* if user sym failed or don't exists. */
1276 {
1277 /*
1278 * Check database - only if not a debug kernel!
1279 * You usually have a .sym-file when using a debug kernel.
1280 * (This is because I am unable to distinguish between half and
1281 * all strict kernels...)
1282 */
1283 if ((options.fKernel & KF_DEBUG) ||
1284 (rc = LookupKrnlEntry((unsigned short)options.ulBuild,
1285 (unsigned short)options.fKernel,
1286 cObjects)
1287 ) != NO_ERROR
1288 )
1289 {
1290 #if 1 /* ndef R3TST */
1291 APIRET rc2;
1292 /* search on disk */
1293 i = 0;
1294 while (apszSym[i] != NULL
1295 && (rc2 = ProbeSymFile(apszSym[i])) != NO_ERROR
1296 )
1297 {
1298 i++;
1299 if (rc2 >= ERROR_PROB_SYM_D32_FIRST)
1300 rc = rc2;
1301 }
1302 if (rc == NO_ERROR)
1303 kstrcpy(szSymbolFile, apszSym[i]);
1304 else if (rc == 1 || rc2 == NO_ERROR)
1305 rc = rc2;
1306 #endif
1307 }
1308 }
1309 }
1310
1311 /* Show the result and set return-value */
1312 dprintf(("rc=%d(0x%x); i=%d; iProc=%d\n", rc, rc, i, iProc));
1313 ShowResult(rc);
1314
1315 return rc;
1316}
1317#endif
1318
1319
1320#ifdef DEBUGR3
1321/**
1322 * Verifies that build no, matches kernel number.
1323 * @returns 0 on equal, !0 on error.
1324 */
1325static int VerifyKernelVer(void)
1326{
1327 int VerMinor, VerMajor;
1328
1329 VerMajor = options.ulBuild < 20000 ? 20 : 30/*?*/;
1330 VerMinor = options.ulBuild < 6600 ? 10 : options.ulBuild < 8000 ? 11 : options.ulBuild < 9000 ? 30 :
1331 options.ulBuild < 10000 ? 40 : options.ulBuild < 15000 ? 45 : 50;
1332
1333 return VerMajor - (int)options.usVerMajor | VerMinor - (int)options.usVerMinor;
1334}
1335
1336
1337/**
1338 * Reads and verifies OS/2 kernel.
1339 * @returns 0 on success.
1340 * One of the ERROR_PROB_KRNL_* defines on error.
1341 * @param pszFilename Filename of the OS/2 kernel.
1342 * @result options.ulBuild is set.
1343 * @remark This step will be eliminated by searching thru the DOSGROUP datasegment
1344 * in the kernel memory. This segment have a string "Internal revision 9.034[smp|uni]"
1345 * This would be much faster than reading the kernel file. It will also give us a more precise
1346 * answer to the question! This is currently a TODO issue. !FIXME!
1347 */
1348static int ReadOS2Krnl(char * pszFilename)
1349{
1350 HFILE hKrnl;
1351 unsigned long cbKrnl;
1352 int rc;
1353
1354 hKrnl = fopen(pszFilename, "rb");
1355 if (hKrnl != 0)
1356 {
1357 /*
1358 * Get size of kernel file.
1359 */
1360 cbKrnl = fsize(hKrnl);
1361 if (!fseek(hKrnl, 0, SEEK_SET))
1362 {
1363 /*
1364 * Call worker with filehandle and size.
1365 */
1366 rc = ReadOS2Krnl2(hKrnl, cbKrnl);
1367 }
1368 else
1369 rc = ERROR_PROB_KRNL_SEEK_SIZE;
1370 fclose(hKrnl);
1371 }
1372 else
1373 {
1374 dprintf(("Could not open file\n"));
1375 rc = ERROR_PROB_KRNL_OPEN_FAILED;
1376 }
1377 return rc;
1378}
1379
1380
1381/**
1382 * Worker function for ReadOS2Krnl
1383 * @returns 0 on success.
1384 * One of the ERROR_PROB_KRNL_* defines on error.
1385 * @param hKrnl Handle to the kernel file.
1386 * @param cbKrnl Size of the kernel file.
1387 * @author knut st. osmundsen
1388 */
1389static int ReadOS2Krnl2(HFILE hKrnl, unsigned long cbKrnl)
1390{
1391 #if defined(DEBUGR3) || !defined(EXTRACT)
1392 static KRNLINFO DATA16_INIT KrnlInfo = {0};
1393 #endif
1394 int i, j;
1395 int rc = 0;
1396 char achBuffer[KERNEL_ID_STRING_LENGTH + KERNEL_READ_SIZE];
1397 unsigned long offLXHdr;
1398 struct e32_exe *pLXHdr;
1399
1400
1401 /*
1402 * Find bldlevel string - for example: "@#IBM:14.020#@ IBM OS/2 Kernel - 14.020F"
1403 * Searching the entire file lineary from the start.
1404 */
1405 if (fseek(hKrnl, 0, SEEK_SET))
1406 return ERROR_PROB_KRNL_SEEK_FIRST;
1407
1408 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, KERNEL_READ_SIZE, hKrnl))
1409 return ERROR_PROB_KRNL_READ_FIRST;
1410
1411 i = KERNEL_ID_STRING_LENGTH;
1412 while (cbKrnl > 0)
1413 {
1414 if (i == KERNEL_READ_SIZE)
1415 {
1416
1417 kmemcpy(achBuffer, &achBuffer[KERNEL_READ_SIZE], KERNEL_ID_STRING_LENGTH);
1418 if (!fread(&achBuffer[KERNEL_ID_STRING_LENGTH], 1, cbKrnl > KERNEL_READ_SIZE ? KERNEL_READ_SIZE : (int)cbKrnl, hKrnl))
1419 return ERROR_PROB_KRNL_READ_NEXT;
1420
1421 i = 0;
1422 }
1423
1424 if (kstrncmp("@#IBM:", &achBuffer[i], 6) == 0)
1425 break;
1426
1427 /* next */
1428 i++;
1429 cbKrnl--;
1430 }
1431
1432 /* found it? */
1433 if (cbKrnl == 0)
1434 {
1435 fclose(hKrnl);
1436 return ERROR_PROB_KRNL_TAG_NOT_FOUND;
1437 }
1438
1439
1440 /*
1441 * We've found the @#IBM: tag. So now we'll try read it.
1442 */
1443
1444 /* displacement */
1445 j = 0;
1446 while (j < 6 && achBuffer[i+10+j] != '#')
1447 j++;
1448
1449 /* verify signature */
1450 if (kstrncmp(&achBuffer[i+10+j], "#@ IBM OS/2 Kernel", 19) != 0)
1451 return ERROR_PROB_KRNL_INV_SIGANTURE;
1452
1453 /*
1454 * read options.ulBuild
1455 */
1456 options.ulBuild = (char)(achBuffer[i+6] - '0') * 1000;
1457 if (achBuffer[i+7] != '.')
1458 {
1459 /* this code is for Warp5 */
1460 options.ulBuild *= 10;
1461 options.ulBuild += (char)(achBuffer[i+7] - '0') * 1000;
1462 i++;
1463 j--;
1464 if (achBuffer[i+7] != '.')
1465 {
1466 options.ulBuild *= 10;
1467 options.ulBuild += (unsigned long)(achBuffer[i+7] - '0') * 1000;
1468 i++;
1469 j--;
1470 }
1471 }
1472
1473 if (j == 0)
1474 {
1475 options.ulBuild += (achBuffer[i+ 8] - '0') * 10;
1476 options.ulBuild += (achBuffer[i+ 9] - '0') * 1;
1477 }
1478 else
1479 {
1480 if (j == 3)
1481 return ERROR_PROB_KRNL_INV_BUILD_NBR;
1482 options.ulBuild += (achBuffer[i+ 8] - '0') * 100;
1483 options.ulBuild += (achBuffer[i+ 9] - '0') * 10;
1484 options.ulBuild += (achBuffer[i+10] - '0');
1485 }
1486
1487 /*
1488 * We've read the build number. Let's check that it matches the OS/2
1489 * version reported by DosGetInfoSeg.
1490 */
1491 if (VerifyKernelVer())
1492 return ERROR_PROB_KRNL_BUILD_VERSION;
1493 dprintf(("options.ulBuild: %d\n", options.ulBuild));
1494
1495 /* get segment number */
1496 /* read-MZheader */
1497 if (fseek(hKrnl,0,SEEK_SET))
1498 return ERROR_PROB_KRNL_MZ_SEEK;
1499
1500 if (!fread(achBuffer, 1, 0x40, hKrnl))
1501 return ERROR_PROB_KRNL_MZ_READ;
1502
1503 offLXHdr = *(unsigned long int *)&achBuffer[0x3c];
1504
1505 if (offLXHdr > 0x2000 && offLXHdr < 0x80) /* just to detect garbage */
1506 return ERROR_PROB_KRNL_NEOFF_INVALID;
1507
1508 if (fseek(hKrnl, offLXHdr, SEEK_SET))
1509 return ERROR_PROB_KRNL_NEOFF_SEEK;
1510
1511 if (!fread(achBuffer, 1, sizeof(struct e32_exe), hKrnl))
1512 return ERROR_PROB_KRNL_LX_READ;
1513
1514 /* check LX-magic */
1515 if (achBuffer[0] != 'L' || achBuffer[1] != 'X')
1516 return ERROR_PROB_KRNL_LX_SIGNATURE;
1517
1518#if !defined(DEBUGR3) && !defined(EXTRACT)
1519 /* check object count - match it with what we got from the kernel. */
1520 pLXHdr = (struct e32_exe *)achBuffer;
1521 if ((UCHAR)pLXHdr->e32_objcnt != cObjects)
1522 return ERROR_PROB_KRNL_OBJECT_CNT;
1523
1524 if (pLXHdr->e32_objcnt < 10)
1525 return ERROR_PROB_KRNL_OBJECT_CNR_10;
1526
1527 /* check objects sizes. */
1528 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1529 {
1530 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1531 for (i = 0; i < (int)cObjects; i++)
1532 {
1533 if (!fread(achBuffer, 1, sizeof(OTE), hKrnl))
1534 return ERROR_PROB_KRNL_OTE_READ;
1535 if (pObj->o32_size < paKrnlOTEs[i].ote_size)
1536 return ERROR_PROB_KRNL_OTE_SIZE_MIS;
1537 }
1538 }
1539 else
1540 return ERROR_PROB_KRNL_OTE_SEEK;
1541#else
1542 /* Since we can't get the OTEs from the kernel when debugging in RING-3,
1543 * we'll use what we find in the kernel.
1544 */
1545
1546 /* object count */
1547 pLXHdr = (struct e32_exe *)achBuffer;
1548 cObjects = (UCHAR)pLXHdr->e32_objcnt;
1549 paKrnlOTEs = &KrnlInfo.aObjects[0];
1550
1551 /* get OTEs */
1552 if (!fseek(hKrnl, (LONG)offLXHdr + (LONG)pLXHdr->e32_objtab, SEEK_SET))
1553 {
1554 struct o32_obj *pObj = (struct o32_obj *)achBuffer;
1555 for (i = 0; i < (int)cObjects; i++)
1556 if (!fread(&paKrnlOTEs[i], 1, sizeof(struct o32_obj), hKrnl))
1557 return ERROR_PROB_KRNL_OTE_READ;
1558 }
1559 else
1560 return ERROR_PROB_KRNL_OTE_SEEK;
1561#endif
1562
1563 return NO_ERROR;
1564}
1565
1566
1567
1568/**
1569 * Debug - Main procedure for standalone testing.
1570 */
1571void main(int argc, char **argv)
1572{
1573 char szParm[512];
1574 RPINITIN ReqPack;
1575 int j;
1576 int i = 0;
1577 int argi = 0;
1578
1579 while (argi < argc)
1580 {
1581 j = 0;
1582 while (argv[argi][j] != '\0')
1583 szParm[i++] = argv[argi][j++];
1584 szParm[i++] = ' ';
1585
1586 /* next */
1587 argi++;
1588 }
1589 szParm[i++] = '\0';
1590
1591 ReqPack.InitArgs = szParm;
1592
1593 ProbeKernel(&ReqPack);
1594}
1595#endif
1596
1597
1598#ifdef EXTRACT
1599/**
1600 * Dumps writes a KRNLDBENTRY struct to stderr for the given .sym-file.
1601 * The filesnames are on this format:
1602 * nnnn[n]tm.SYM
1603 * Where: n - are the build number 4 or 5 digits.
1604 * t - kernel type. R = retail, H = half strict, A = all strict.
1605 * m - UNI or SMP. U = UNI processor kernel. S = SMP processor kernel. 4 = Warp 4 FP13+
1606 * @returns NO_ERROR on success. Untracable error code on error.
1607 * @param pszFilename Pointer to read only filename of the .sym-file.
1608 * @status completely implemented.
1609 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1610 * @remark Currently only retail kernels are processed. See note below.
1611 */
1612static int processFile(const char *pszFilename)
1613{
1614 APIRET rc;
1615 int cch = kstrlen(pszFilename);
1616
1617 DosWrite(2, (char*)pszFilename, cch, &rc);
1618 DosWrite(2, "\r\n", 2, &rc);
1619
1620 /* Filename check */
1621 if (cch < 10 || cch > 11
1622 || !(pszFilename[0] >= '0' && pszFilename[0] <= '9')
1623 || !(pszFilename[1] >= '0' && pszFilename[1] <= '9')
1624 || !(pszFilename[2] >= '0' && pszFilename[2] <= '9')
1625 || !(pszFilename[3] >= '0' && pszFilename[3] <= '9')
1626 || !(pszFilename[cch-7] >= '0' && pszFilename[cch-7] <= '9')
1627 || !(pszFilename[cch-6] == 'A' || pszFilename[cch-6] == 'H' || pszFilename[cch-6] == 'R')
1628 || !(pszFilename[cch-5] == 'S' || pszFilename[cch-5] == 'U' || pszFilename[cch-5] == '4')
1629 )
1630 {
1631 printf16("invalid filename: %s\n", pszFilename);
1632 return 2;
1633 }
1634
1635 /*
1636 * Probe kernelfile
1637 */
1638 rc = ProbeSymFile(pszFilename);
1639
1640
1641 /*
1642 * on success dump a struct for this kernel
1643 */
1644 if (rc == 0)
1645 {
1646 int i;
1647
1648 /** @remark
1649 * Currently information for retail kernels are usable, but we'll
1650 * generate it for the debug kernels too, but this information
1651 * is enclaved within an "#ifdef ALLKERNELS ... #endif".
1652 */
1653 if (pszFilename[cch-6] != 'R')
1654 printf16("#ifdef ALLKERNELS\n");
1655
1656 printf16(" { /* %s */\n"
1657 " %.*s, ",
1658 pszFilename,
1659 cch - 6, &pszFilename[0] /* build number */
1660 );
1661
1662 switch (pszFilename[cch - 5])
1663 {
1664 case 'S': printf16("KF_SMP"); break;
1665 case '4': printf16("KF_UNI | KF_W4"); break;
1666 case 'U': printf16("KF_UNI"); break;
1667 }
1668 switch (pszFilename[cch - 6])
1669 {
1670 case 'A': printf16(" | KF_ALLSTRICT"); break;
1671 case 'H': printf16(" | KF_HALFSTRICT"); break;
1672 }
1673 printf16(", %d,\n"
1674 " {\n",
1675 aImportTab[0].iObject + 1); /* ASSUMES that DOSCODE32 is the last object. */
1676
1677 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1678 {
1679 char *psz = aImportTab[i].achName;
1680 printf16(" {%-2d, 0x%08lx}, /* %s */\n",
1681 aImportTab[i].iObject,
1682 aImportTab[i].fFound ? aImportTab[i].offObject : 0xFFFFFFFFUL,
1683 (char *)&aImportTab[i].achName[0]
1684 );
1685 }
1686 printf16(" }\n"
1687 " },\n");
1688
1689 /** @remark
1690 * Currently information for retail kernels are usable, but we'll
1691 * generate it for the debug kernels too, but this information
1692 * is enclaved within an "#ifdef ALLKERNELS ... #endif".
1693 */
1694 if (pszFilename[cch-6] != 'R')
1695 printf16("#endif\n");
1696 }
1697 else
1698 printf16("ProbeSymFile failed with rc=%d\n", rc);
1699
1700 return rc;
1701}
1702
1703
1704/**
1705 * Extract program.
1706 *
1707 * This is some initial trial-and-error for creating an "database" of
1708 * kernel entrypoints.
1709 *
1710 * Output to stderr the structs generated for the passed in *.sym file.
1711 *
1712 */
1713int main(int argc, char **argv)
1714{
1715 APIRET rc;
1716 const char * psz;
1717
1718 /*
1719 * Set paKrnlOTEs to point to an zeroed array of OTEs.
1720 */
1721 static KRNLINFO DATA16_INIT KrnlInfo = {0};
1722 paKrnlOTEs = &KrnlInfo.aObjects[0];
1723
1724 if (argc > 1)
1725 {
1726 /*
1727 * Arguments: extract.exe <symfiles...>
1728 */
1729 int i;
1730 for (i = 1; i < argc; i++)
1731 {
1732 rc = processFile(argv[i]);
1733 if (rc != NO_ERROR)
1734 {
1735 printf16("processFile failed with rc=%d for file %s\n",
1736 rc, argv[i]);
1737 if (psz = GetErrorMsg(rc))
1738 printf16("%s\n", psz);
1739 return rc;
1740 }
1741 }
1742 }
1743 else
1744 {
1745 /*
1746 * Arguments: extract.exe
1747 *
1748 * Action: Scan current directory for *.sym files.
1749 *
1750 */
1751 USHORT usSearch = 1;
1752 HDIR hDir = HDIR_CREATE;
1753 FILEFINDBUF ffb;
1754 int i;
1755
1756 printf16("/* $Id: probkrnl.c,v 1.22 2000-09-04 16:40:48 bird Exp $\n"
1757 "*\n"
1758 "* Autogenerated kernel symbol database.\n"
1759 "*\n"
1760 "* Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)\n"
1761 "*\n"
1762 "* Project Odin Software License can be found in LICENSE.TXT\n"
1763 "*\n"
1764 "*/\n");
1765
1766 printf16("\n"
1767 "#define INCL_NOPMAPI\n"
1768 "#define INCL_NOBASEAPI\n"
1769 "#include <os2.h>\n"
1770 "#include \"DevSegDf.h\"\n"
1771 "#include \"probkrnl.h\"\n"
1772 "#include \"options.h\"\n"
1773 "\n");
1774
1775 printf16("KRNLDBENTRY DATA16_INIT aKrnlSymDB[] = \n"
1776 "{\n");
1777
1778 rc = DosFindFirst("*.sym", &hDir, FILE_NORMAL,
1779 &ffb, sizeof(ffb),
1780 &usSearch, 0UL);
1781 while (rc == NO_ERROR & usSearch > 0)
1782 {
1783 rc = processFile(&ffb.achName[0]);
1784 if (rc != NO_ERROR)
1785 {
1786 printf16("processFile failed with rc=%d for file %s\n",
1787 rc, &ffb.achName[0]);
1788 if (psz = GetErrorMsg(rc))
1789 printf16("%s\n", psz);
1790 return rc;
1791 }
1792
1793 /* next file */
1794 rc = DosFindNext(hDir, &ffb, sizeof(ffb), &usSearch);
1795 }
1796 DosFindClose(hDir);
1797
1798 printf16(" { /* Terminating entry */\n"
1799 " 0,0,0,\n"
1800 " {\n");
1801 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1802 printf16(" {0,0},\n");
1803 printf16(" }\n"
1804 " }\n"
1805 "}; /* end of aKrnlSymDB[] */\n"
1806 );
1807 }
1808
1809
1810 return rc;
1811}
1812#endif /* EXTRACT */
1813
Note: See TracBrowser for help on using the repository browser.