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