|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IOKernelDebugger.cpp ! 26: * ! 27: * Kernel debugger nub. This object interfaces with the KDP module and ! 28: * dispatches KDP requests to its provider. The provider, named the ! 29: * debugger device, must implement a pair of handler functions that are ! 30: * called to handle KDP transmit and receive requests. A debugger lock, ! 31: * allocated by the IOKernelDebugger, can be used by the debugger device ! 32: * to block calls to its handler functions during critical sections. ! 33: * ! 34: * The debugger device is usually a subclass of IOEthernetController. ! 35: * However, any IOService can attach an IOKernelDebugger client, ! 36: * implement the two polled mode handlers, and transport the KDP ! 37: * packets through a data channel. Having said this, the KDP assumes ! 38: * that the debugger device is an Ethernet interface and therefore ! 39: * it will always send, and expect to receive, an Ethernet frame. ! 40: * ! 41: * HISTORY ! 42: */ ! 43: ! 44: #include <IOKit/assert.h> ! 45: #include <IOKit/IOLib.h> ! 46: #include <IOKit/IOMessage.h> ! 47: #include <IOKit/network/IONetworkController.h> ! 48: #include <IOKit/network/IOKernelDebugger.h> ! 49: ! 50: extern "C" { ! 51: ! 52: // Defined in osfmk/kdp/kdp_en_debugger.h, ! 53: // but the header file is not exported, ! 54: // thus the definition is replicated here. ! 55: ! 56: typedef void (*kdp_send_t)(void * pkt, UInt pkt_len); ! 57: typedef void (*kdp_receive_t)(void * pkt, UInt * pkt_len, UInt timeout); ! 58: void kdp_register_send_receive(kdp_send_t send, kdp_receive_t receive); ! 59: } ! 60: ! 61: #define super IOService ! 62: OSDefineMetaClassAndStructorsWithInit(IOKernelDebugger, ! 63: IOService, ! 64: IOKernelDebugger::initialize()) ! 65: ! 66: // Debugger global variables. ! 67: // ! 68: IOSimpleLock * gIODebuggerLock = 0; ! 69: UInt32 gIODebuggerFlag = 0; ! 70: IOService * gIODebuggerDevice = 0; ! 71: IOKernelDebugger * gIODebuggerNub = 0; ! 72: IODebuggerTxHandler gIODebuggerTxHandler = 0; ! 73: IODebuggerRxHandler gIODebuggerRxHandler = 0; ! 74: UInt32 gIODebuggerTxBytes = 0; ! 75: UInt32 gIODebuggerRxBytes = 0; ! 76: UInt32 gIODebuggerSemaphore = 0; // deprecated ! 77: IOInterruptState gIODebuggerInterruptState; ! 78: ! 79: // Flags to indicate debugger state. ! 80: // ! 81: enum { ! 82: kIODebuggerFlagEnabled = 0x01, ! 83: kIODebuggerFlagRegistered = 0x02, ! 84: }; ! 85: ! 86: #define KDP_GRAB_LOCK IOSimpleLockLock(gIODebuggerLock) ! 87: #define KDP_RELEASE_LOCK IOSimpleLockUnlock(gIODebuggerLock) ! 88: ! 89: #define IOTakeDebuggerLock(s) \ ! 90: ((s) = IOSimpleLockLockDisableInterrupt(gIODebuggerLock)) ! 91: ! 92: #define IOReleaseDebuggerLock(s) \ ! 93: IOSimpleLockUnlockEnableInterrupt(gIODebuggerLock, (s)) ! 94: ! 95: //--------------------------------------------------------------------------- ! 96: // The KDP receive dispatch function. Handles KDP receive requests during ! 97: // a debugging session, then dispatches the call to the registered handler. ! 98: // This function is registered with KDP via kdp_register_send_receive(). ! 99: // ! 100: // pkt: KDP receive buffer. The buffer allocated has room for 1518 bytes. ! 101: // Never overflow the buffer! ! 102: // ! 103: // pkt_len: The amount of data placed into the receive buffer. Set to ! 104: // 0 if no frame was received during the timeout interval. ! 105: // ! 106: // timeout: The registered handler must poll for a maximum period of ! 107: // �timeout� milliseconds while waiting for a frame to arrive. ! 108: ! 109: void IOKernelDebugger::kdpReceiveDispatcher(void * pkt, ! 110: UInt * pkt_len, ! 111: UInt timeout) ! 112: { ! 113: *pkt_len = 0; // return length field is zero by default. ! 114: ! 115: #ifdef __USE_DEBUGGER_LOCK ! 116: KDP_GRAB_LOCK; ! 117: ! 118: // Warning: We are holding a simple_lock, the handler must not block. ! 119: ! 120: (*gIODebuggerRxHandler)(gIODebuggerDevice, pkt, pkt_len, timeout); ! 121: gIODebuggerRxBytes += *pkt_len; ! 122: ! 123: KDP_RELEASE_LOCK; ! 124: #else ! 125: if (gIODebuggerSemaphore) ! 126: return; ! 127: ! 128: (*gIODebuggerRxHandler)(gIODebuggerDevice, pkt, pkt_len, timeout); ! 129: gIODebuggerRxBytes += *pkt_len; ! 130: #endif ! 131: } ! 132: ! 133: //--------------------------------------------------------------------------- ! 134: // The KDP transmit dispatch function. Handles KDP transmit requests during ! 135: // a debugging session, then dispatches the call to the registered handler. ! 136: // This function is registered with KDP via kdp_register_send_receive(). ! 137: // ! 138: // pkt: KDP transmit buffer. This buffer contains a KDP frame to be sent ! 139: // on the wire. ! 140: // ! 141: // pkt_len: The number of bytes in the transmit buffer. ! 142: ! 143: void IOKernelDebugger::kdpTransmitDispatcher(void * pkt, UInt pkt_len) ! 144: { ! 145: #ifdef __USE_DEBUGGER_LOCK ! 146: KDP_GRAB_LOCK; ! 147: ! 148: // Warning: We are holding a simple_lock, the handler must not block. ! 149: ! 150: (*gIODebuggerTxHandler)(gIODebuggerDevice, pkt, pkt_len); ! 151: gIODebuggerTxBytes += pkt_len; ! 152: ! 153: KDP_RELEASE_LOCK; ! 154: #else ! 155: if (gIODebuggerSemaphore) ! 156: return; ! 157: ! 158: (*gIODebuggerTxHandler)(gIODebuggerDevice, pkt, pkt_len); ! 159: gIODebuggerTxBytes += pkt_len; ! 160: #endif ! 161: } ! 162: ! 163: //--------------------------------------------------------------------------- ! 164: // Null request handlers. Those gets registered when an IOKernelDebugger ! 165: // instance becomes detached from its debugger device, and before a new ! 166: // debugger device takes over the debugging responsibilities. ! 167: ! 168: void IOKernelDebugger::nullTxHandler(IOService * provider, ! 169: void * buffer, ! 170: UInt length) ! 171: { ! 172: IOLog("IOKernelDebugger::%s no debugger device\n", __FUNCTION__); ! 173: } ! 174: ! 175: void IOKernelDebugger::nullRxHandler(IOService * provider, ! 176: void * buffer, ! 177: UInt * length, ! 178: UInt timeout) ! 179: { ! 180: IOLog("IOKernelDebugger::%s no debugger device\n", __FUNCTION__); ! 181: } ! 182: ! 183: //--------------------------------------------------------------------------- ! 184: // Take the debugger lock conditionally. ! 185: // The debugger lock is taken only if the provider given is the current ! 186: // registered debugger device. The debugger device is registered via the ! 187: // openProvider() method, and unregistered via closeProvider(). ! 188: // ! 189: // Returns kIODebuggerLocked if the lock was taken, or ! 190: // 0 if the lock was not taken. ! 191: ! 192: IODebuggerLockState IOKernelDebugger::lock(IOService * provider) ! 193: { ! 194: #ifdef __USE_DEBUGGER_LOCK ! 195: ! 196: if (gIODebuggerDevice == provider) ! 197: { ! 198: IOInterruptState irqState; ! 199: ! 200: IOTakeDebuggerLock(irqState); ! 201: ! 202: if (gIODebuggerDevice == provider) ! 203: { ! 204: gIODebuggerInterruptState = irqState; ! 205: return kIODebuggerLockTaken; ! 206: } ! 207: else { ! 208: IOReleaseDebuggerLock(irqState); ! 209: } ! 210: } ! 211: return (IODebuggerLockState) 0; ! 212: ! 213: #else /* !__USE_DEBUGGER_LOCK */ ! 214: ! 215: if (gIODebuggerDevice == provider) ! 216: { ! 217: if (gIODebuggerSemaphore) ! 218: IOLog("IOKernelDebugger::lock: already locked\n"); ! 219: ! 220: gIODebuggerSemaphore++; ! 221: return kIODebuggerLockTaken; ! 222: } ! 223: return (IODebuggerLockState) 0; ! 224: ! 225: #endif ! 226: } ! 227: ! 228: //--------------------------------------------------------------------------- ! 229: // Release the debugger lock if the kIODebuggerLockTaken flag is set. ! 230: // ! 231: // state: The saved return from a previous IOKernelDebugger::lock() call. ! 232: ! 233: void IOKernelDebugger::unlock(IODebuggerLockState state) ! 234: { ! 235: #ifdef __USE_DEBUGGER_LOCK ! 236: ! 237: if (state & kIODebuggerLockTaken) ! 238: IOReleaseDebuggerLock(gIODebuggerInterruptState); ! 239: ! 240: #else /* !__USE_DEBUGGER_LOCK */ ! 241: ! 242: if (state & kIODebuggerLockTaken) ! 243: gIODebuggerSemaphore--; ! 244: ! 245: #endif ! 246: } ! 247: ! 248: //--------------------------------------------------------------------------- ! 249: // IOKernelDebugger class initializer. The debugger lock is allocated and ! 250: // initialized. ! 251: ! 252: void IOKernelDebugger::initialize() ! 253: { ! 254: // Allocate and initialize the debugger lock (simple_lock). ! 255: ! 256: gIODebuggerLock = IOSimpleLockAlloc(); ! 257: assert(gIODebuggerLock); ! 258: IOSimpleLockInit(gIODebuggerLock); ! 259: } ! 260: ! 261: //--------------------------------------------------------------------------- ! 262: // The IOKernelDebugger initializer. ! 263: // ! 264: // provider: The provider of the IOKernelDebugger object. ! 265: // txHandler: The transmit handler. A pointer to a C function. ! 266: // rxHandler: The receive handler. A pointer to a C function. ! 267: // ! 268: // Returns true if the instance initialized successfully, false otherwise. ! 269: ! 270: bool IOKernelDebugger::init(IOService * provider, ! 271: IODebuggerTxHandler txHandler, ! 272: IODebuggerRxHandler rxHandler) ! 273: { ! 274: if (!OSDynamicCast(IOService, provider) || !txHandler || !rxHandler) ! 275: return false; ! 276: ! 277: if (!super::init()) ! 278: return false; ! 279: ! 280: // Register the provider and handlers provided. ! 281: ! 282: _provider = provider; ! 283: _txHandler = txHandler; ! 284: _rxHandler = rxHandler; ! 285: ! 286: return true; ! 287: } ! 288: ! 289: //--------------------------------------------------------------------------- ! 290: // A factory method that performs allocation and initialization. ! 291: // ! 292: // provider: The provider of the IOKernelDebugger object. ! 293: // txHandler: The transmit handler. A pointer to a C function. ! 294: // rxHandler: The receive handler. A pointer to a C function. ! 295: // ! 296: // Returns an IOKernelDebugger instance on success, 0 otherwise. ! 297: ! 298: IOKernelDebugger * IOKernelDebugger::debugger(IOService * provider, ! 299: IODebuggerTxHandler txHandler, ! 300: IODebuggerRxHandler rxHandler) ! 301: { ! 302: IOKernelDebugger * debugger = new IOKernelDebugger; ! 303: ! 304: if (debugger && !debugger->init(provider, txHandler, rxHandler)) ! 305: { ! 306: debugger->release(); ! 307: debugger = 0; ! 308: } ! 309: ! 310: return debugger; ! 311: } ! 312: ! 313: //--------------------------------------------------------------------------- ! 314: // Open the attached provider, register the dispatch and handler functions. ! 315: // ! 316: // provider: The provider object. This object is registered as the debugger ! 317: // device. ! 318: // ! 319: // Returns true on sucess, or false if the controller open failed, or there ! 320: // is a previously registered IOKernelDebugger instance. ! 321: ! 322: bool IOKernelDebugger::openProvider(IOService * provider) ! 323: { ! 324: bool ret = false; ! 325: bool doOpen; ! 326: bool wasOpen; ! 327: bool doRegistration = false; ! 328: IOInterruptState state; ! 329: ! 330: IOTakeDebuggerLock(state); ! 331: if (gIODebuggerNub) ! 332: { ! 333: // Debugger nub already registered. Sorry, only ! 334: // a single debugger nub at any given time. ! 335: ! 336: doOpen = false; ! 337: } ! 338: else ! 339: { ! 340: assert(gIODebuggerDevice == 0); ! 341: assert((gIODebuggerFlag & kIODebuggerFlagEnabled) == 0); ! 342: assert(provider == _provider); ! 343: ! 344: // Make reservation. ! 345: ! 346: gIODebuggerNub = this; ! 347: doOpen = true; ! 348: } ! 349: IOReleaseDebuggerLock(state); ! 350: ! 351: // If doOpen is true, then proceed and open the provider, ! 352: // otherwise we were unable to make reservation, so ! 353: // we give up and return false. ! 354: ! 355: do { ! 356: if (!doOpen) break; ! 357: ! 358: wasOpen = provider->open(this); ! 359: ! 360: // Take the debugger lock again and commit the reservation. ! 361: // Make sure nothing has happened to cause us to loose the ! 362: // initial reservation. ! 363: ! 364: IOTakeDebuggerLock(state); ! 365: ! 366: if (wasOpen && (gIODebuggerNub == this)) ! 367: { ! 368: gIODebuggerTxHandler = _txHandler; ! 369: gIODebuggerRxHandler = _rxHandler; ! 370: gIODebuggerDevice = provider; ! 371: gIODebuggerFlag |= kIODebuggerFlagEnabled; ! 372: ! 373: if ((gIODebuggerFlag & kIODebuggerFlagRegistered) == 0) ! 374: { ! 375: // Our static dispatch functions have not yet been ! 376: // registered with kdp, set doRegistration to ! 377: // perform registration after releasing the lock. ! 378: // The act of registering may trigger kdp to call ! 379: // our dispatch functions, so we should not be ! 380: // holding the debugger lock. ! 381: ! 382: gIODebuggerFlag |= kIODebuggerFlagRegistered; ! 383: doRegistration = true; ! 384: } ! 385: } ! 386: else ! 387: { ! 388: // Either we were unable to open provider, ! 389: // or perhaps we lost reservation. ! 390: ! 391: if (gIODebuggerNub == this) ! 392: { ! 393: // Unable to open provider, remove our ! 394: // reservation. ! 395: ! 396: gIODebuggerNub = 0; ! 397: } ! 398: IOReleaseDebuggerLock(state); ! 399: break; ! 400: } ! 401: ! 402: IOReleaseDebuggerLock(state); ! 403: ! 404: // NOTE: Once the provider has accepted an open from this ! 405: // object, it must be prepared to handle kdp requests ! 406: // immediately after its open method returns. ! 407: // ! 408: // Register the dispatch functions, that will route the ! 409: // kdp request to our provider�s registered handlers. ! 410: ! 411: if (doRegistration) ! 412: kdp_register_send_receive(kdpTransmitDispatcher, ! 413: kdpReceiveDispatcher); ! 414: ! 415: ret = true; // success ! 416: } ! 417: while (0); ! 418: ! 419: if (doOpen && !ret) ! 420: { ! 421: // Make sure the provider is closed. ! 422: provider->close(this); ! 423: } ! 424: ! 425: return ret; ! 426: } ! 427: ! 428: //--------------------------------------------------------------------------- ! 429: // Close our provider, and unregister the handler functions provided to ! 430: // init(). Another IOKernelDebugger instance that comes along will be ! 431: // able to assume the debugging responsibilities. ! 432: // ! 433: // provider: The provider object. This object is unregistered as the ! 434: // debugger device. ! 435: ! 436: void IOKernelDebugger::closeProvider(IOService * provider) ! 437: { ! 438: bool doClose = false; ! 439: IOInterruptState state; ! 440: ! 441: IOTakeDebuggerLock(state); ! 442: ! 443: if (gIODebuggerNub == this) ! 444: { ! 445: // There is no kdp unregistration. Thus setup the handlers ! 446: // to point to dummy functions to avoid a system panic ! 447: // when the debugger device gives up its responsibilities ! 448: // and the debugger is activated. ! 449: // Until the next debugger device comes along, nothing will ! 450: // happen when the debugger is activated, which is not good. ! 451: ! 452: gIODebuggerFlag &= ~kIODebuggerFlagEnabled; ! 453: gIODebuggerDevice = 0; ! 454: gIODebuggerNub = 0; ! 455: gIODebuggerTxHandler = &IOKernelDebugger::nullTxHandler; ! 456: gIODebuggerRxHandler = &IOKernelDebugger::nullRxHandler; ! 457: doClose = true; ! 458: } ! 459: IOReleaseDebuggerLock(state); ! 460: ! 461: if (doClose) ! 462: provider->close(this); ! 463: } ! 464: ! 465: //--------------------------------------------------------------------------- ! 466: // Attach to our provider, then call openProvider(). ! 467: // ! 468: // provider: The provider object. ! 469: // ! 470: // Returns true on success, false otherwise. ! 471: ! 472: bool IOKernelDebugger::attach(IOService * provider) ! 473: { ! 474: bool ret = false; ! 475: ! 476: assert(provider == _provider); ! 477: ! 478: if (!super::attach(provider)) ! 479: return false; // cannot attach to provider. ! 480: ! 481: ret = openProvider(provider); ! 482: ! 483: return ret; ! 484: } ! 485: ! 486: //--------------------------------------------------------------------------- ! 487: // Call closeProvider() then detach from our provider. ! 488: // ! 489: // provider: The provider object. ! 490: ! 491: void IOKernelDebugger::detach(IOService * provider) ! 492: { ! 493: // IOLog("IOKernelDebugger::%s provider:%x\n", __FUNCTION__, (UInt) provider); ! 494: ! 495: assert(provider == _provider); ! 496: ! 497: closeProvider(provider); ! 498: ! 499: super::detach(provider); ! 500: } ! 501: ! 502: //--------------------------------------------------------------------------- ! 503: // Final termination notification. Ensure that the closeProvider() is ! 504: // called before the object is terminated. ! 505: // ! 506: // options: termination options, not used. ! 507: ! 508: bool IOKernelDebugger::finalize(IOOptionBits options) ! 509: { ! 510: // IOLog("IOKernelDebugger::%s options:%x\n", __FUNCTION__, (UInt) options); ! 511: ! 512: closeProvider(_provider); ! 513: return super::finalize(options); ! 514: } ! 515: ! 516: //--------------------------------------------------------------------------- ! 517: // Facility provided by IOService for general purpose provider-to-client ! 518: // notification. We catch the kIOMessageServiceIsTerminated message to ! 519: // detect when our provider becomes inactive, and call closeProvider(). ! 520: // ! 521: // type: message tupe. ! 522: // provider: The provider object. ! 523: // argument: message argument. Not used. ! 524: // ! 525: // Returns kIOReturnSuccess for kIOMessageServiceIsTerminated messages, ! 526: // kIOReturnUnsupported otherwise. ! 527: ! 528: IOReturn IOKernelDebugger::message(UInt32 type, ! 529: IOService * provider, ! 530: void * argument = 0) ! 531: { ! 532: // IOLog("IOKernelDebugger::%s type:%x provider:%x\n", ! 533: // __FUNCTION__, (UInt) type, (UInt) provider); ! 534: ! 535: assert(provider == _provider); ! 536: ! 537: if (type == kIOMessageServiceIsTerminated) ! 538: { ! 539: // Close our provider when it becomes inactive. ! 540: ! 541: closeProvider(provider); ! 542: return kIOReturnSuccess; ! 543: } ! 544: ! 545: return kIOReturnUnsupported; ! 546: } ! 547: ! 548: //--------------------------------------------------------------------------- ! 549: // Free the IOKernelDebugger instance. ! 550: ! 551: void IOKernelDebugger::free() ! 552: { ! 553: // IOLog("IOKernelDebugger::%s %08lx\n", __FUNCTION__, (UInt32) this); ! 554: super::free(); ! 555: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.