Annotation of XNU/iokit/Families/IONetworking/IOKernelDebugger.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.