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

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

Merged in the Grace branch. New Win32k!

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