2 * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IOCPU.h>
30 #include <IOKit/IODeviceTreeSupport.h>
31 #include <IOKit/IOKitDebug.h>
32 #include <IOKit/IOMapper.h>
33 #include <IOKit/IOMessage.h>
34 #include <IOKit/IONVRAM.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IORangeAllocator.h>
37 #include <IOKit/IOWorkLoop.h>
38 #include <IOKit/pwr_mgt/RootDomain.h>
39 #include <IOKit/IOKitKeys.h>
40 #include <IOKit/IOTimeStamp.h>
41 #include <IOKit/IOUserClient.h>
42 #include <IOKit/IOKitDiagnosticsUserClient.h>
44 #include <IOKit/system.h>
47 #include <libkern/c++/OSContainers.h>
48 #include <libkern/crypto/sha1.h>
49 #include <libkern/OSAtomic.h>
52 #include <machine/machine_routines.h>
53 #include <pexpert/pexpert.h>
54 #include <uuid/uuid.h>
57 #define kShutdownTimeout 30 //in secs
61 boolean_t coprocessor_cross_panic_enabled
= TRUE
;
62 #endif /* !CONFIG_EMBEDDED */
64 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
65 static void getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
);
67 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
69 #define super IOService
71 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
73 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
74 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
75 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 2);
76 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 3);
77 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 4);
79 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
80 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
81 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
82 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
83 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
84 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
85 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
87 static IOPlatformExpert
* gIOPlatform
;
88 static OSDictionary
* gIOInterruptControllers
;
89 static IOLock
* gIOInterruptControllersLock
;
90 static IODTNVRAM
*gIOOptionsEntry
;
92 OSSymbol
* gPlatformInterruptControllerName
;
94 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
96 bool IOPlatformExpert::attach( IOService
* provider
)
99 if( !super::attach( provider
))
105 bool IOPlatformExpert::start( IOService
* provider
)
107 IORangeAllocator
* physicalRanges
;
108 OSData
* busFrequency
;
112 if (!super::start(provider
))
115 // Override the mapper present flag is requested by boot arguments, if SIP disabled.
117 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS
) == 0)
118 #endif /* CONFIG_CSR */
120 if (PE_parse_boot_argn("dart", &debugFlags
, sizeof (debugFlags
)) && (debugFlags
== 0))
121 removeProperty(kIOPlatformMapperPresentKey
);
122 #if DEBUG || DEVELOPMENT
123 if (PE_parse_boot_argn("-x", &debugFlags
, sizeof (debugFlags
)))
124 removeProperty(kIOPlatformMapperPresentKey
);
125 #endif /* DEBUG || DEVELOPMENT */
128 // Register the presence or lack thereof a system
129 // PCI address mapper with the IOMapper class
130 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
132 gIOInterruptControllers
= OSDictionary::withCapacity(1);
133 gIOInterruptControllersLock
= IOLockAlloc();
135 // Correct the bus frequency in the device tree.
136 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
137 provider
->setProperty("clock-frequency", busFrequency
);
138 busFrequency
->release();
140 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
142 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
143 IORangeAllocator::kLocking
);
144 assert(physicalRanges
);
145 setProperty("Platform Memory Ranges", physicalRanges
);
150 PMInstantiatePowerDomains();
152 // Parse the serial-number data and publish a user-readable string
153 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
154 if (mydata
!= NULL
) {
155 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
156 if (serNoString
!= NULL
) {
157 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
158 serNoString
->release();
163 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2
) {
164 coprocessor_paniclog_flush
= TRUE
;
165 extended_debug_log_init();
169 return( configure(provider
) );
172 bool IOPlatformExpert::configure( IOService
* provider
)
178 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
181 while( (dict
= OSDynamicCast( OSDictionary
,
182 topLevel
->getAnyObject()))) {
184 topLevel
->removeObject( dict
);
185 nub
= createNub( dict
);
190 nub
->registerService();
197 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
201 nub
= new IOPlatformDevice
;
203 if( !nub
->init( from
)) {
211 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
212 OSString
* name
, OSString
** matched
) const
214 return( nub
->IORegistryEntry::compareName( name
, matched
));
217 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
219 return( kIOReturnSuccess
);
222 long IOPlatformExpert::getBootROMType(void)
224 return _peBootROMType
;
227 long IOPlatformExpert::getChipSetType(void)
229 return _peChipSetType
;
232 long IOPlatformExpert::getMachineType(void)
234 return _peMachineType
;
237 void IOPlatformExpert::setBootROMType(long peBootROMType
)
239 _peBootROMType
= peBootROMType
;
242 void IOPlatformExpert::setChipSetType(long peChipSetType
)
244 _peChipSetType
= peChipSetType
;
247 void IOPlatformExpert::setMachineType(long peMachineType
)
249 _peMachineType
= peMachineType
;
252 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
257 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
262 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
267 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
269 return(OSDynamicCast(IORangeAllocator
,
270 getProperty("Platform Memory Ranges")));
273 int (*PE_halt_restart
)(unsigned int type
) = 0;
275 int IOPlatformExpert::haltRestart(unsigned int type
)
277 if (type
== kPEPanicSync
) return 0;
279 if (type
== kPEHangCPU
) while (true) {}
281 if (type
== kPEUPSDelayHaltCPU
) {
282 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
287 // On ARM kPEPanicRestartCPU is supported in the drivers
288 if (type
== kPEPanicRestartCPU
)
289 type
= kPERestartCPU
;
292 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
296 void IOPlatformExpert::sleepKernel(void)
302 intState
= ml_set_interrupts_enabled(false);
304 for (cnt
= 0; cnt
< 10000; cnt
++) {
308 ml_set_interrupts_enabled(intState
);
310 // PE_initialize_console(0, kPEDisableScreen);
314 // PE_initialize_console(0, kPEEnableScreen);
318 long IOPlatformExpert::getGMTTimeOfDay(void)
323 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
328 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
330 return( PE_current_console( consoleInfo
));
333 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
336 return( PE_initialize_console( consoleInfo
, op
));
339 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
341 IOLockLock(gIOInterruptControllersLock
);
343 gIOInterruptControllers
->setObject(name
, interruptController
);
345 IOLockWakeup(gIOInterruptControllersLock
,
346 gIOInterruptControllers
, /* one-thread */ false);
348 IOLockUnlock(gIOInterruptControllersLock
);
350 return kIOReturnSuccess
;
353 IOReturn
IOPlatformExpert::deregisterInterruptController(OSSymbol
*name
)
355 IOLockLock(gIOInterruptControllersLock
);
357 gIOInterruptControllers
->removeObject(name
);
359 IOLockUnlock(gIOInterruptControllersLock
);
361 return kIOReturnSuccess
;
364 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
368 IOLockLock(gIOInterruptControllersLock
);
371 object
= gIOInterruptControllers
->getObject(name
);
376 IOLockSleep(gIOInterruptControllersLock
,
377 gIOInterruptControllers
, THREAD_UNINT
);
380 IOLockUnlock(gIOInterruptControllersLock
);
381 return OSDynamicCast(IOInterruptController
, object
);
385 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
387 IOCPUInterruptController
*controller
;
389 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
390 if (controller
) controller
->setCPUInterruptProperties(service
);
393 bool IOPlatformExpert::atInterruptLevel(void)
395 return ml_at_interrupt_context();
398 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
403 void IOPlatformExpert::getUTCTimeOfDay(clock_sec_t
* secs
, clock_nsec_t
* nsecs
)
405 *secs
= getGMTTimeOfDay();
409 void IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs
, __unused clock_nsec_t nsecs
)
411 setGMTTimeOfDay(secs
);
415 //*********************************************************************************
418 //*********************************************************************************
420 void IOPlatformExpert::
421 PMLog(const char *who
, unsigned long event
,
422 unsigned long param1
, unsigned long param2
)
426 clock_get_system_microtime(&nows
, &nowus
);
427 nowus
+= (nows
% 1000) * 1000000;
429 kprintf("pm%u %p %.30s %d %lx %lx\n",
430 nowus
, OBFUSCATE(current_thread()), who
, // Identity
431 (int) event
, (long)OBFUSCATE(param1
), (long)OBFUSCATE(param2
)); // Args
435 //*********************************************************************************
436 // PMInstantiatePowerDomains
438 // In this vanilla implementation, a Root Power Domain is instantiated.
439 // All other objects which register will be children of this Root.
440 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
441 // in a platform-specific subclass.
442 //*********************************************************************************
444 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
446 root
= new IOPMrootDomain
;
453 //*********************************************************************************
456 // In this vanilla implementation, all callers are made children of the root power domain.
457 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
458 //*********************************************************************************
460 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
462 root
->addPowerChild ( theDevice
);
465 //*********************************************************************************
468 //*********************************************************************************
470 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
472 return ((_pePMFeatures
& featureMask
) != 0);
475 //*********************************************************************************
478 //*********************************************************************************
480 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
482 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
485 //*********************************************************************************
486 // numBatteriesSupported
488 //*********************************************************************************
490 int IOPlatformExpert::numBatteriesSupported (void)
492 return (_peNumBatteriesSupported
);
495 //*********************************************************************************
498 // This method is called by the instantiated sublass of the platform expert to
499 // determine how a device should be inserted into the Power Domain. The subclass
500 // provides an XML power tree description against which a device is matched based
501 // on class and provider. If a match is found this routine returns true in addition
502 // to flagging the description tree at the appropriate node that a device has been
503 // registered for the given service.
504 //*********************************************************************************
506 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
509 unsigned int numPowerTreeNodes
;
510 OSDictionary
* entry
;
511 OSDictionary
* matchingDictionary
;
512 OSDictionary
* providerDictionary
;
513 OSDictionary
* deviceDictionary
;
514 OSDictionary
* nubDictionary
;
516 bool nodeFound
= false;
517 bool continueSearch
= false;
518 bool deviceMatch
= false;
519 bool providerMatch
= false;
520 bool multiParentMatch
= false;
522 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
525 numPowerTreeNodes
= inSubTree
->getCount ();
527 // iterate through the power tree to find a home for this device
529 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
531 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
533 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
534 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
536 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
537 if ( matchingDictionary
) {
539 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
540 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
541 deviceDictionary
->release ();
545 providerMatch
= true; // we indicate a match if there is no nub or provider
546 if ( theNub
&& providerDictionary
) {
547 providerMatch
= false;
548 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
549 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
550 nubDictionary
->release ();
554 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
555 if (deviceMatch
&& providerMatch
) {
556 if (NULL
!= multipleParentKeyValue
) {
557 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
558 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
562 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
564 // if the power tree specifies a provider dictionary but theNub is
565 // NULL then we cannot match with this entry.
567 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
570 // if this node is THE ONE...then register the device
573 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
575 if ( kIOLogPower
& gIOKitDebug
)
576 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
578 numInstancesRegistered
++;
580 // determine if we need to search for additional nodes for this item
581 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
587 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
589 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
590 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
591 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
594 if ( false == continueSearch
)
598 return ( nodeFound
);
601 //*********************************************************************************
602 // RegisterServiceInTree
604 // Register a device at the specified node of our power tree.
605 //*********************************************************************************
607 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
609 IOService
* aService
;
610 bool registered
= false;
612 unsigned int numChildren
;
613 OSDictionary
* child
;
615 // make sure someone is not already registered here
617 if ( NULL
== theTreeNode
->getObject ("service") ) {
619 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
621 // 1. CHILDREN ------------------
623 // we registered the node in the tree...now if the node has children
624 // registered we must tell this service to add them.
626 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
627 numChildren
= children
->getCount ();
628 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
629 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
630 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
631 theService
->addPowerChild (aService
);
636 // 2. PARENT --------------------
638 // also we must notify the parent of this node (if a registered service
639 // exists there) of a new child.
641 if ( theTreeParentNode
) {
642 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
643 if (aService
!= theProvider
)
644 aService
->addPowerChild (theService
);
654 //*********************************************************************************
655 // printDictionaryKeys
657 // Print the keys for the given dictionary and selected contents.
658 //*********************************************************************************
659 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
661 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
668 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
672 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
674 // if this is the IOClass key, print it's contents
676 if ( mkey
->isEqualTo ("IOClass") ) {
677 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
678 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
681 // if this is an IOProviderClass key print it
683 if ( mkey
->isEqualTo ("IOProviderClass") ) {
684 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
685 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
689 // also print IONameMatch keys
690 if ( mkey
->isEqualTo ("IONameMatch") ) {
691 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
692 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
695 // also print IONameMatched keys
697 if ( mkey
->isEqualTo ("IONameMatched") ) {
698 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
699 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
705 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
707 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
709 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
715 if ( mkey
->isEqualTo ("name") ) {
718 getCStringForObject(inDictionary
->getObject("name"), nameStr
,
720 if (strlen(nameStr
) > 0)
721 IOLog ("%s name is %s\n", inMsg
, nameStr
);
724 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
733 getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
)
738 if ( (NULL
== inObj
) || (NULL
== outStr
))
741 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
743 if ((0 == strncmp(objString
, "OSString", sizeof("OSString"))) ||
744 (0 == strncmp(objString
, "OSSymbol", sizeof("OSSymbol"))))
745 strlcpy(outStr
, ((OSString
*)inObj
)->getCStringNoCopy(), outStrLen
);
747 else if (0 == strncmp(objString
, "OSData", sizeof("OSData"))) {
748 len
= ((OSData
*)inObj
)->getLength();
749 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
750 if (buffer
&& (len
> 0)) {
751 for (i
=0; i
< len
; i
++) {
752 outStr
[i
] = buffer
[i
];
759 /* IOShutdownNotificationsTimedOut
760 * - Called from a timer installed by PEHaltRestart
762 static void IOShutdownNotificationsTimedOut(
763 thread_call_param_t p0
,
764 thread_call_param_t p1
)
766 #ifdef CONFIG_EMBEDDED
767 /* 30 seconds has elapsed - panic */
768 panic("Halt/Restart Timed Out");
770 #else /* ! CONFIG_EMBEDDED */
771 int type
= (int)(long)p0
;
772 uint32_t timeout
= (uint32_t)(uintptr_t)p1
;
774 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
776 if ((PEGetCoprocessorVersion() >= kCoprocessorVersion2
) || pmRootDomain
->checkShutdownTimeout()) {
777 pmRootDomain
->panicWithShutdownLog(timeout
* 1000);
781 /* 30 seconds has elapsed - resume shutdown */
782 if(gIOPlatform
) gIOPlatform
->haltRestart(type
);
783 #endif /* CONFIG_EMBEDDED */
790 * Callouts from BSD for machine name & model
793 boolean_t
PEGetMachineName( char * name
, int maxLength
)
796 return( gIOPlatform
->getMachineName( name
, maxLength
));
801 boolean_t
PEGetModelName( char * name
, int maxLength
)
804 return( gIOPlatform
->getModelName( name
, maxLength
));
809 int PEGetPlatformEpoch(void)
812 return( gIOPlatform
->getBootROMType());
817 int PEHaltRestart(unsigned int type
)
819 IOPMrootDomain
*pmRootDomain
;
820 AbsoluteTime deadline
;
821 thread_call_t shutdown_hang
;
822 IORegistryEntry
*node
;
824 uint32_t timeout
= kShutdownTimeout
;
825 static boolean_t panic_begin_called
= FALSE
;
827 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
|| type
== kPEUPSDelayHaltCPU
)
829 pmRootDomain
= IOService::getPMRootDomain();
830 /* Notify IOKit PM clients of shutdown/restart
831 Clients subscribe to this message with a call to
832 IOService::registerInterest()
835 /* Spawn a thread that will panic in 30 seconds.
836 If all goes well the machine will be off by the time
837 the timer expires. If the device wants a different
838 timeout, use that value instead of 30 seconds.
841 #define RESTART_NODE_PATH "/defaults"
843 #define RESTART_NODE_PATH "/chosen"
845 node
= IORegistryEntry::fromPath( RESTART_NODE_PATH
, gIODTPlane
);
847 data
= OSDynamicCast( OSData
, node
->getProperty( "halt-restart-timeout" ) );
848 if ( data
&& data
->getLength() == 4 )
849 timeout
= *((uint32_t *) data
->getBytesNoCopy());
852 shutdown_hang
= thread_call_allocate( &IOShutdownNotificationsTimedOut
,
853 (thread_call_param_t
)(uintptr_t) type
);
854 clock_interval_to_deadline( timeout
, kSecondScale
, &deadline
);
855 thread_call_enter1_delayed( shutdown_hang
, (thread_call_param_t
)(uintptr_t)timeout
, deadline
);
857 pmRootDomain
->handlePlatformHaltRestart(type
);
858 /* This notification should have few clients who all do
859 their work synchronously.
861 In this "shutdown notification" context we don't give
862 drivers the option of working asynchronously and responding
863 later. PM internals make it very hard to wait for asynchronous
867 else if(type
== kPEPanicRestartCPU
|| type
== kPEPanicSync
)
869 if (type
== kPEPanicRestartCPU
) {
870 // Notify any listeners that we're done collecting
871 // panic data before we call through to do the restart
872 IOCPURunPlatformPanicActions(kPEPanicEnd
);
874 // Callout to shutdown the disk driver once we've returned from the
875 // kPEPanicEnd callback (and we know all core dumps on this system
877 IOCPURunPlatformPanicActions(kPEPanicDiskShutdown
);
880 // Do an initial sync to flush as much panic data as possible,
881 // in case we have a problem in one of the platorm panic handlers.
882 // After running the platform handlers, do a final sync w/
883 // platform hardware quiesced for the panic.
884 PE_sync_panic_buffers();
885 IOCPURunPlatformPanicActions(type
);
886 PE_sync_panic_buffers();
888 else if (type
== kPEPanicEnd
) {
890 if (coprocessor_cross_panic_enabled
)
892 IOCPURunPlatformPanicActions(type
);
894 } else if (type
== kPEPanicBegin
) {
896 if (coprocessor_cross_panic_enabled
)
899 // Only call the kPEPanicBegin callout once
900 if (!panic_begin_called
) {
901 panic_begin_called
= TRUE
;
902 IOCPURunPlatformPanicActions(type
);
907 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
911 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
913 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
917 void PESavePanicInfoAction(void *buffer
, UInt32 offset
, UInt32 length
)
919 IOCPURunPlatformPanicSyncAction(buffer
, offset
, length
);
924 inline static int init_gIOOptionsEntry(void)
926 IORegistryEntry
*entry
;
928 volatile void **options
;
934 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
938 nvram_entry
= (void *) OSDynamicCast(IODTNVRAM
, entry
);
942 options
= (volatile void **) &gIOOptionsEntry
;
943 if (!OSCompareAndSwapPtr(NULL
, nvram_entry
, options
)) {
956 /* pass in a NULL value if you just want to figure out the len */
957 boolean_t
PEReadNVRAMProperty(const char *symbol
, void *value
,
967 if (init_gIOOptionsEntry() < 0)
973 obj
= gIOOptionsEntry
->getProperty(symbol
);
977 /* convert to data */
978 data
= OSDynamicCast(OSData
, obj
);
982 *len
= data
->getLength();
983 vlen
= min(vlen
, *len
);
985 memcpy((void *) value
, data
->getBytesNoCopy(), vlen
);
994 PEWriteNVRAMBooleanProperty(const char *symbol
, boolean_t value
)
996 const OSSymbol
*sym
= NULL
;
997 OSBoolean
*data
= NULL
;
1000 if (symbol
== NULL
) {
1004 if (init_gIOOptionsEntry() < 0) {
1008 if ((sym
= OSSymbol::withCStringNoCopy(symbol
)) == NULL
) {
1012 data
= value
? kOSBooleanTrue
: kOSBooleanFalse
;
1013 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1017 /* success, force the NVRAM to flush writes */
1019 gIOOptionsEntry
->sync();
1026 boolean_t
PEWriteNVRAMProperty(const char *symbol
, const void *value
,
1027 const unsigned int len
)
1029 const OSSymbol
*sym
;
1033 if (!symbol
|| !value
|| !len
)
1036 if (init_gIOOptionsEntry() < 0)
1039 sym
= OSSymbol::withCStringNoCopy(symbol
);
1043 data
= OSData::withBytes((void *) value
, len
);
1047 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1054 gIOOptionsEntry
->sync();
1063 boolean_t
PERemoveNVRAMProperty(const char *symbol
)
1065 const OSSymbol
*sym
;
1070 if (init_gIOOptionsEntry() < 0)
1073 sym
= OSSymbol::withCStringNoCopy(symbol
);
1077 gIOOptionsEntry
->removeProperty(sym
);
1081 gIOOptionsEntry
->sync();
1089 long PEGetGMTTimeOfDay(void)
1094 PEGetUTCTimeOfDay(&secs
, &usecs
);
1098 void PESetGMTTimeOfDay(long secs
)
1100 PESetUTCTimeOfDay(secs
, 0);
1103 void PEGetUTCTimeOfDay(clock_sec_t
* secs
, clock_usec_t
* usecs
)
1105 clock_nsec_t nsecs
= 0;
1109 gIOPlatform
->getUTCTimeOfDay(secs
, &nsecs
);
1111 assert(nsecs
< NSEC_PER_SEC
);
1112 *usecs
= nsecs
/ NSEC_PER_USEC
;
1115 void PESetUTCTimeOfDay(clock_sec_t secs
, clock_usec_t usecs
)
1117 assert(usecs
< USEC_PER_SEC
);
1119 gIOPlatform
->setUTCTimeOfDay(secs
, usecs
* NSEC_PER_USEC
);
1122 coprocessor_type_t
PEGetCoprocessorVersion( void )
1124 coprocessor_type_t coprocessor_version
= kCoprocessorVersionNone
;
1125 #if !CONFIG_EMBEDDED
1126 IORegistryEntry
*platform_entry
= NULL
;
1127 OSData
*coprocessor_version_obj
= NULL
;
1129 platform_entry
= IORegistryEntry::fromPath(kIODeviceTreePlane
":/efi/platform");
1130 if (platform_entry
!= NULL
) {
1131 coprocessor_version_obj
= OSDynamicCast(OSData
, platform_entry
->getProperty("apple-coprocessor-version"));
1132 if ((coprocessor_version_obj
!= NULL
) && (coprocessor_version_obj
->getLength() <= sizeof(uint64_t))) {
1133 memcpy(&coprocessor_version
, coprocessor_version_obj
->getBytesNoCopy(), coprocessor_version_obj
->getLength());
1135 platform_entry
->release();
1138 return coprocessor_version
;
1143 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
1146 IORegistryEntry
* entry
;
1147 OSString
* string
= 0;
1151 entry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
1156 data1
= OSDynamicCast( OSData
, entry
->getProperty( "unique-chip-id" ) );
1157 if ( data1
&& data1
->getLength( ) == 8 )
1161 data2
= OSDynamicCast( OSData
, entry
->getProperty( "chip-id" ) );
1162 if ( data2
&& data2
->getLength( ) == 4 )
1165 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1166 const uuid_t space
= { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
1168 SHA1Init( &context
);
1169 SHA1Update( &context
, space
, sizeof( space
) );
1170 SHA1Update( &context
, data1
->getBytesNoCopy( ), data1
->getLength( ) );
1171 SHA1Update( &context
, data2
->getBytesNoCopy( ), data2
->getLength( ) );
1172 SHA1Final( digest
, &context
);
1174 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1175 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1177 uuid_unparse( digest
, uuid
);
1178 string
= OSString::withCString( uuid
);
1184 #else /* !CONFIG_EMBEDDED */
1186 * If we have panic debugging enabled and a prod-fused coprocessor,
1187 * disable cross panics so that the co-processor doesn't cause the system
1188 * to reset when we enter the debugger or hit a panic on the x86 side.
1190 if ( panicDebugging
)
1192 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1195 data
= OSDynamicCast( OSData
, entry
->getProperty( "EffectiveProductionStatus" ) );
1196 if ( data
&& ( data
->getLength( ) == sizeof( UInt8
) ) ) {
1197 UInt8
*isProdFused
= (UInt8
*) data
->getBytesNoCopy( );
1198 UInt32 debug_flags
= 0;
1199 if ( *isProdFused
|| ( PE_i_can_has_debugger(&debug_flags
) &&
1200 ( debug_flags
& DB_DISABLE_CROSS_PANIC
) ) ) {
1201 coprocessor_cross_panic_enabled
= FALSE
;
1208 entry
= IORegistryEntry::fromPath( "/efi/platform", gIODTPlane
);
1211 data
= OSDynamicCast( OSData
, entry
->getProperty( "system-id" ) );
1212 if ( data
&& data
->getLength( ) == 16 )
1215 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1216 const uuid_t space
= { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
1218 SHA1Init( &context
);
1219 SHA1Update( &context
, space
, sizeof( space
) );
1220 SHA1Update( &context
, data
->getBytesNoCopy( ), data
->getLength( ) );
1221 SHA1Final( digest
, &context
);
1223 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1224 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1226 uuid_unparse( digest
, uuid
);
1227 string
= OSString::withCString( uuid
);
1232 #endif /* !CONFIG_EMBEDDED */
1236 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1239 data
= OSDynamicCast( OSData
, entry
->getProperty( "platform-uuid" ) );
1240 if ( data
&& data
->getLength( ) == sizeof( uuid_t
) )
1242 uuid_unparse( ( uint8_t * ) data
->getBytesNoCopy( ), uuid
);
1243 string
= OSString::withCString( uuid
);
1252 getProvider( )->setProperty( kIOPlatformUUIDKey
, string
);
1253 publishResource( kIOPlatformUUIDKey
, string
);
1258 publishResource("IONVRAM");
1261 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
1262 bool waitForFunction
,
1263 void *param1
, void *param2
,
1264 void *param3
, void *param4
)
1266 IOService
*service
, *_resources
;
1268 if (waitForFunction
) {
1269 _resources
= waitForService(resourceMatching(functionName
));
1271 _resources
= getResourceService();
1273 if (_resources
== 0) return kIOReturnUnsupported
;
1275 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
1276 if (service
== 0) return kIOReturnUnsupported
;
1278 return service
->callPlatformFunction(functionName
, waitForFunction
,
1279 param1
, param2
, param3
, param4
);
1282 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1287 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1290 #define super IOPlatformExpert
1292 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
1294 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
1295 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
1296 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
1297 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
1298 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
1299 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
1300 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
1301 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
1303 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1305 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
1308 if( !super::probe( provider
, score
))
1311 // check machine types
1312 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
1318 bool IODTPlatformExpert::configure( IOService
* provider
)
1320 if( !super::configure( provider
))
1323 processTopLevel( provider
);
1328 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
1332 nub
= new IOPlatformDevice
;
1334 if( !nub
->init( from
, gIODTPlane
)) {
1342 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
1344 IORegistryEntry
* next
;
1349 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
1351 if( 0 == (nub
= createNub( next
)))
1354 nub
->attach( parent
);
1355 nub
->registerService();
1363 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
1366 IORegistryEntry
* next
;
1367 IORegistryEntry
* cpus
;
1368 IORegistryEntry
* options
;
1371 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
1373 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
1374 next
->detachAll( gIODTPlane
);
1379 // Publish an IODTNVRAM class on /options.
1380 options
= rootEntry
->childFromPath("options", gIODTPlane
);
1382 dtNVRAM
= new IODTNVRAM
;
1384 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
1388 dtNVRAM
->attach(this);
1389 dtNVRAM
->registerService();
1395 // Publish the cpus.
1396 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
1399 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
1403 // publish top level, minus excludeList
1404 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
1407 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
1409 if( nub
->getDeviceMemory())
1410 return( kIOReturnSuccess
);
1412 IODTResolveAddressing( nub
, "reg", 0);
1414 return( kIOReturnSuccess
);
1417 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
1418 OSString
* name
, OSString
** matched
) const
1420 return( IODTCompareNubName( nub
, name
, matched
)
1421 || super::compareNubName( nub
, name
, matched
) );
1424 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1434 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1436 str
= (const char *) prop
->getBytesNoCopy();
1438 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1439 str
+= strlen( "AAPL," );
1442 while( (c
= *str
++)) {
1443 if( (c
== '/') || (c
== ' '))
1447 if( len
>= maxLength
)
1457 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1463 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1467 strlcpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1472 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1474 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1476 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1478 super::registerNVRAMController(nvram
);
1481 int IODTPlatformExpert::haltRestart(unsigned int type
)
1483 if (dtNVRAM
) dtNVRAM
->sync();
1485 return super::haltRestart(type
);
1488 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1491 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1492 else return kIOReturnNotReady
;
1495 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1498 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1499 else return kIOReturnNotReady
;
1502 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1503 IORegistryEntry
* entry
,
1504 const OSSymbol
** name
, OSData
** value
)
1506 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1507 else return kIOReturnNotReady
;
1510 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1511 IORegistryEntry
* entry
,
1512 const OSSymbol
* name
, OSData
* value
)
1514 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1515 else return kIOReturnNotReady
;
1518 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1520 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1524 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1525 IOByteCount offset
, UInt8
* buffer
,
1528 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1530 else return kIOReturnNotReady
;
1533 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1534 IOByteCount offset
, UInt8
* buffer
,
1537 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1539 else return kIOReturnNotReady
;
1542 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1544 IOByteCount lengthSaved
= 0;
1546 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1548 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1553 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1554 UInt8
* serialNumber
;
1555 unsigned int serialNumberSize
;
1556 unsigned short pos
= 0;
1560 if (myProperty
!= NULL
) {
1561 serialNumberSize
= myProperty
->getLength();
1562 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1563 temp
= (char*)serialNumber
;
1564 if (serialNumberSize
> 0) {
1565 // check to see if this is a CTO serial number...
1566 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1568 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1569 memcpy(SerialNo
, serialNumber
+ 12, 8);
1570 memcpy(&SerialNo
[8], serialNumber
, 3);
1572 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1574 } else { // just a normal serial number
1575 memcpy(SerialNo
, serialNumber
+ 13, 8);
1576 memcpy(&SerialNo
[8], serialNumber
, 3);
1579 return OSString::withCString(SerialNo
);
1586 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1589 #define super IOService
1591 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1593 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1594 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1595 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1596 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1598 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1600 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1601 OSString
** matched
) const
1603 return( IODTCompareNubName( this, name
, matched
));
1607 IOPlatformExpertDevice::initWithArgs(
1608 void * dtTop
, void * p2
, void * p3
, void * p4
)
1610 IORegistryEntry
* dt
= 0;
1613 // dtTop may be zero on non- device tree systems
1614 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1615 ok
= super::init( dt
, gIODTPlane
);
1623 workLoop
= IOWorkLoop::workLoop();
1630 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1635 IOReturn
IOPlatformExpertDevice::setProperties( OSObject
* properties
)
1637 OSDictionary
* dictionary
;
1641 status
= super::setProperties( properties
);
1642 if ( status
!= kIOReturnUnsupported
) return status
;
1644 status
= IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator
);
1645 if ( status
!= kIOReturnSuccess
) return status
;
1647 dictionary
= OSDynamicCast( OSDictionary
, properties
);
1648 if ( dictionary
== 0 ) return kIOReturnBadArgument
;
1650 object
= dictionary
->getObject( kIOPlatformUUIDKey
);
1653 IORegistryEntry
* entry
;
1657 string
= ( OSString
* ) getProperty( kIOPlatformUUIDKey
);
1658 if ( string
) return kIOReturnNotPermitted
;
1660 string
= OSDynamicCast( OSString
, object
);
1661 if ( string
== 0 ) return kIOReturnBadArgument
;
1663 status
= uuid_parse( string
->getCStringNoCopy( ), uuid
);
1664 if ( status
!= 0 ) return kIOReturnBadArgument
;
1666 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1669 entry
->setProperty( "platform-uuid", uuid
, sizeof( uuid_t
) );
1673 setProperty( kIOPlatformUUIDKey
, string
);
1674 publishResource( kIOPlatformUUIDKey
, string
);
1676 return kIOReturnSuccess
;
1679 return kIOReturnUnsupported
;
1682 IOReturn
IOPlatformExpertDevice::newUserClient( task_t owningTask
, void * securityID
,
1683 UInt32 type
, OSDictionary
* properties
,
1684 IOUserClient
** handler
)
1686 IOReturn err
= kIOReturnSuccess
;
1687 IOUserClient
* newConnect
= 0;
1688 IOUserClient
* theConnect
= 0;
1692 case kIOKitDiagnosticsClientType
:
1693 newConnect
= IOKitDiagnosticsClient::withTask(owningTask
);
1694 if (!newConnect
) err
= kIOReturnNotPermitted
;
1697 err
= kIOReturnBadArgument
;
1702 if ((false == newConnect
->attach(this))
1703 || (false == newConnect
->start(this)))
1705 newConnect
->detach( this );
1706 newConnect
->release();
1707 err
= kIOReturnNotPermitted
;
1710 theConnect
= newConnect
;
1713 *handler
= theConnect
;
1717 void IOPlatformExpertDevice::free()
1720 workLoop
->release();
1723 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1726 #define super IOService
1728 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1730 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1731 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1732 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1733 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1735 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1737 bool IOPlatformDevice::compareName( OSString
* name
,
1738 OSString
** matched
) const
1740 return( ((IOPlatformExpert
*)getProvider())->
1741 compareNubName( this, name
, matched
));
1744 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1749 IOReturn
IOPlatformDevice::getResources( void )
1751 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1754 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1756 /*********************************************************************
1757 * IOPanicPlatform class
1759 * If no legitimate IOPlatformDevice matches, this one does and panics
1760 * the kernel with a suitable message.
1761 *********************************************************************/
1763 class IOPanicPlatform
: IOPlatformExpert
{
1764 OSDeclareDefaultStructors(IOPanicPlatform
);
1767 bool start(IOService
* provider
) APPLE_KEXT_OVERRIDE
;
1771 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1774 bool IOPanicPlatform::start(IOService
* provider
) {
1775 const char * platform_name
= "(unknown platform name)";
1777 if (provider
) platform_name
= provider
->getName();
1779 panic("Unable to find driver for this platform: \"%s\".\n",