1#ifndef _XTRACE_H_
2#define	_XTRACE_H_
3
4#ifdef KERNEL
5#include <IOKit/IOService.h>
6#include <IOKit/IOUserClient.h>
7#endif // KERNEL
8
9
10#define XTRACE_HELPER(global, id, x, y, msg)                    					\
11do {													\
12    if (global) {											\
13	static char *__xtrace = 0;              							\
14	    if (__xtrace)   global->LogAdd((UInt32)id, (UInt32)(x), (UInt32)(y), __xtrace);     	\
15		else __xtrace = global->LogAdd((UInt32)id, (UInt32)(x), (UInt32)(y), msg, false);	\
16    }													\
17} while(0)
18
19#define kXTraceKextName 	"com_apple_iokit_XTrace"
20
21typedef struct {			// Each log entry in the circular buffer looks like this
22    UInt32	id;			// unique id or 'this' or whatever the client wants to put here
23    UInt32	data1;			// two 32 bit numbers for the log
24    UInt32	data2;
25    UInt32	timeStamp;		// timestamp of the log entry - in microseconds
26    char	*msg;			// pointer to cached copy of the event msg
27} EventDesc;
28
29enum {					// command codes for the user-client to send in
30    cmdXTrace_GetLog = 201,		// get the big buffers
31    cmdXTrace_GetLogSizes,		// get the buffer sizes
32    XTRACE_Magic_Key = 'JDG!'		// code for connect
33};
34
35
36typedef struct  {				// structure of info returned to userclient
37    EventDesc	*eventLog;			// address of the eventlog (in the kernel)
38    UInt32	eventLogSize;			// number of bytes in the eventLog
39    char	*msgBuffer;			// address of the msg buffer (in the kernel)
40    UInt32	msgBufferSize;			// number of bytes in above
41    char	*fNextMsg;			// pointer to next avail byte in msgBuffer
42
43    UInt32	fNumEntries;			// number of entries in eventLog (kEntryCount)
44    UInt32	fEventIndex;			// index of next available event entry in fBuffer
45    UInt32	fPrintIndex;			// set by dcmd to keep track of what's pretty printed already
46    Boolean	fTracingOn;			// true if allowing adds
47    Boolean	fWrapped;			// true if adding log entries wrapped past the printing ptr
48    Boolean	fWrappingEnabled;		// true if wrapping allowed (else stops before dropping data)
49} XTraceLogInfo;
50
51typedef struct {
52    UInt32	fBufferSize;			// sizeof(fBuffer)
53    UInt32	fMsgBufSize;			// sizeof(fMsgBuf)
54} XTraceLogSizes;
55
56#ifdef KERNEL
57
58enum {					// todo - make these plist or userclient changeable
59    kEntryCount = (200*1024),		// number of log entries before wrap (16 bytes per entry)
60    kMsgBufSize = (20*1024)		// buffer for message texts
61};
62
63class com_apple_iokit_XTrace : public IOService
64{
65    OSDeclareDefaultStructors(com_apple_iokit_XTrace)
66
67private:
68    XTraceLogInfo	fInfo;			// indexes and pointers.  passed to remote clients and userclient
69    IOLock		*fMyLock;		// protect self
70    UInt32		fId;			// simple id counter for callers use
71
72    char	*fErrorMsg;			// first msg is reserved for an overflow error msg
73    char	*GetCachedMsg(char *msg, bool compress);
74    char	*CopyMsg(char *msg);
75    void	dumpbuffers();			// temp debugging to iolog
76
77public:
78    virtual bool init(OSDictionary *dictionary);
79    virtual void free(void);
80    virtual bool start(IOService *provider);
81    virtual void stop(IOService *provider);
82    virtual IOService *probe(IOService *provider, SInt32 *score);
83    virtual IOReturn newUserClient( task_t owningTask, void * securityID, UInt32 type, IOUserClient ** handler );
84
85    // this is optional - call to get a simple "unique" id for LogAdd (or just use 'this' from C++)
86    virtual UInt32	GetNewId(void);			// simple counter of xtrace clients
87
88    // call this one first, it adds the msg to the cache and returns a pointer to the cached copy
89    // pass 'true' to compress if you want to search the cache for an old(er) copy of the same msg
90    virtual char *	LogAdd(UInt32 id, UInt32 data1, UInt32 data2, char *msg, Boolean compress);
91
92    // call this one after the first time with the cache value.
93    virtual void	LogAdd(UInt32 id, UInt32 data1, UInt32 data2, char *cachedtext);
94
95    virtual void	LogTracingOn(void);		// default is on
96    virtual void	LogTracingOff(void);
97    virtual void	LogWrappingOn(void);		// default is on
98    virtual void	LogWrappingOff(void);
99
100    // for userclient
101    virtual XTraceLogInfo *LogGetInfo(void);
102    virtual void	   LogReset(UInt32 printIndex);
103    virtual void	   LogLock();
104    virtual void	   LogUnlock();
105
106};
107
108void inline com_apple_iokit_XTrace::LogTracingOn(void) { fInfo.fTracingOn = true; }
109void inline com_apple_iokit_XTrace::LogTracingOff(void) { fInfo.fTracingOn = false; }
110void inline com_apple_iokit_XTrace::LogWrappingOn(void) { fInfo.fWrappingEnabled = true; }
111void inline com_apple_iokit_XTrace::LogWrappingOff(void) { fInfo.fWrappingEnabled = false; }
112UInt32 inline com_apple_iokit_XTrace::GetNewId(void) { return ++fId; }		// lock this
113
114void inline com_apple_iokit_XTrace::LogLock(void)	{ IOLockLock(fMyLock); }
115void inline com_apple_iokit_XTrace::LogUnlock(void)	{ IOLockUnlock(fMyLock); }
116
117/****************************************************************************************************/
118/***************************************** UserClient ***********************************************/
119/****************************************************************************************************/
120
121class com_apple_iokit_XTrace;
122
123class com_apple_iokit_XTraceUserClient : public IOUserClient
124{
125    OSDeclareDefaultStructors(com_apple_iokit_XTraceUserClient)
126
127private:
128    com_apple_iokit_XTrace	*fProvider;
129    IOExternalMethod		fMethods[1];		// just one method
130    task_t			fTask;
131
132public:
133    static com_apple_iokit_XTraceUserClient *withTask(task_t owningTask);	// Factory Constructor
134    IOReturn		clientClose();
135    IOReturn		clientDied();
136
137    bool		start(IOService *provider);
138    IOReturn		connectClient(IOUserClient *client);
139    IOExternalMethod*	getExternalMethodForIndex(UInt32 index);
140
141    IOReturn doRequest(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize);
142
143private:
144    IOReturn getLog(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize);
145    IOReturn getLogSizes(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize);
146    IOReturn copyLogEntries (IOMemoryDescriptor *md,	// path to client memory
147			     EventDesc	*eventLog,	// source buffer
148			     UInt32	first,		// index of first entry to copy over
149			     UInt32	next);		// index of last+1 entry to copy over
150};
151
152
153#endif		// KERNEL
154
155
156
157#endif // _XTRACE_H_
158