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>
60 * This will eventually be properly exported in
61 * <rdar://problem/31181482> ER: Expose coprocessor version (T208/T290) in a kernel/kext header
62 * although we'll always need to hardcode this here since we won't be able to include whatever
63 * header this ends up in.
65 #define kCoprocessorMinVersion 0x00020000
67 boolean_t coprocessor_cross_panic_enabled
= TRUE
;
68 #endif /* !CONFIG_EMBEDDED */
70 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
71 static void getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
);
73 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75 #define super IOService
77 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
79 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
80 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
81 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 2);
82 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 3);
83 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 4);
85 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
86 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
87 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
88 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
89 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
90 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
91 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
93 static IOPlatformExpert
* gIOPlatform
;
94 static OSDictionary
* gIOInterruptControllers
;
95 static IOLock
* gIOInterruptControllersLock
;
96 static IODTNVRAM
*gIOOptionsEntry
;
98 OSSymbol
* gPlatformInterruptControllerName
;
100 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
102 bool IOPlatformExpert::attach( IOService
* provider
)
105 if( !super::attach( provider
))
111 bool IOPlatformExpert::start( IOService
* provider
)
113 IORangeAllocator
* physicalRanges
;
114 OSData
* busFrequency
;
118 IORegistryEntry
*platform_entry
= NULL
;
119 OSData
*coprocessor_version_obj
= NULL
;
120 uint64_t coprocessor_version
= 0;
123 if (!super::start(provider
))
126 // Override the mapper present flag is requested by boot arguments, if SIP disabled.
128 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS
) == 0)
129 #endif /* CONFIG_CSR */
131 if (PE_parse_boot_argn("dart", &debugFlags
, sizeof (debugFlags
)) && (debugFlags
== 0))
132 removeProperty(kIOPlatformMapperPresentKey
);
133 #if DEBUG || DEVELOPMENT
134 if (PE_parse_boot_argn("-x", &debugFlags
, sizeof (debugFlags
)))
135 removeProperty(kIOPlatformMapperPresentKey
);
136 #endif /* DEBUG || DEVELOPMENT */
139 // Register the presence or lack thereof a system
140 // PCI address mapper with the IOMapper class
141 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
143 gIOInterruptControllers
= OSDictionary::withCapacity(1);
144 gIOInterruptControllersLock
= IOLockAlloc();
146 // Correct the bus frequency in the device tree.
147 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
148 provider
->setProperty("clock-frequency", busFrequency
);
149 busFrequency
->release();
151 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
153 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
154 IORangeAllocator::kLocking
);
155 assert(physicalRanges
);
156 setProperty("Platform Memory Ranges", physicalRanges
);
161 PMInstantiatePowerDomains();
163 // Parse the serial-number data and publish a user-readable string
164 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
165 if (mydata
!= NULL
) {
166 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
167 if (serNoString
!= NULL
) {
168 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
169 serNoString
->release();
174 platform_entry
= IORegistryEntry::fromPath(kIODeviceTreePlane
":/efi/platform");
175 if (platform_entry
!= NULL
) {
176 coprocessor_version_obj
= OSDynamicCast(OSData
, platform_entry
->getProperty("apple-coprocessor-version"));
177 if ((coprocessor_version_obj
!= NULL
) && (coprocessor_version_obj
->getLength() <= sizeof(coprocessor_version
))) {
178 memcpy(&coprocessor_version
, coprocessor_version_obj
->getBytesNoCopy(), coprocessor_version_obj
->getLength());
179 if (coprocessor_version
>= kCoprocessorMinVersion
) {
180 coprocessor_paniclog_flush
= TRUE
;
181 extended_debug_log_init();
184 platform_entry
->release();
186 #endif /* !CONFIG_EMBEDDED */
188 return( configure(provider
) );
191 bool IOPlatformExpert::configure( IOService
* provider
)
197 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
200 while( (dict
= OSDynamicCast( OSDictionary
,
201 topLevel
->getAnyObject()))) {
203 topLevel
->removeObject( dict
);
204 nub
= createNub( dict
);
209 nub
->registerService();
216 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
220 nub
= new IOPlatformDevice
;
222 if( !nub
->init( from
)) {
230 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
231 OSString
* name
, OSString
** matched
) const
233 return( nub
->IORegistryEntry::compareName( name
, matched
));
236 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
238 return( kIOReturnSuccess
);
241 long IOPlatformExpert::getBootROMType(void)
243 return _peBootROMType
;
246 long IOPlatformExpert::getChipSetType(void)
248 return _peChipSetType
;
251 long IOPlatformExpert::getMachineType(void)
253 return _peMachineType
;
256 void IOPlatformExpert::setBootROMType(long peBootROMType
)
258 _peBootROMType
= peBootROMType
;
261 void IOPlatformExpert::setChipSetType(long peChipSetType
)
263 _peChipSetType
= peChipSetType
;
266 void IOPlatformExpert::setMachineType(long peMachineType
)
268 _peMachineType
= peMachineType
;
271 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
276 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
281 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
286 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
288 return(OSDynamicCast(IORangeAllocator
,
289 getProperty("Platform Memory Ranges")));
292 int (*PE_halt_restart
)(unsigned int type
) = 0;
294 int IOPlatformExpert::haltRestart(unsigned int type
)
296 if (type
== kPEPanicSync
) return 0;
298 if (type
== kPEHangCPU
) while (true) {}
300 if (type
== kPEUPSDelayHaltCPU
) {
301 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
306 // On ARM kPEPanicRestartCPU is supported in the drivers
307 if (type
== kPEPanicRestartCPU
)
308 type
= kPERestartCPU
;
311 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
315 void IOPlatformExpert::sleepKernel(void)
321 intState
= ml_set_interrupts_enabled(false);
323 for (cnt
= 0; cnt
< 10000; cnt
++) {
327 ml_set_interrupts_enabled(intState
);
329 // PE_initialize_console(0, kPEDisableScreen);
333 // PE_initialize_console(0, kPEEnableScreen);
337 long IOPlatformExpert::getGMTTimeOfDay(void)
342 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
347 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
349 return( PE_current_console( consoleInfo
));
352 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
355 return( PE_initialize_console( consoleInfo
, op
));
358 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
360 IOLockLock(gIOInterruptControllersLock
);
362 gIOInterruptControllers
->setObject(name
, interruptController
);
364 IOLockWakeup(gIOInterruptControllersLock
,
365 gIOInterruptControllers
, /* one-thread */ false);
367 IOLockUnlock(gIOInterruptControllersLock
);
369 return kIOReturnSuccess
;
372 IOReturn
IOPlatformExpert::deregisterInterruptController(OSSymbol
*name
)
374 IOLockLock(gIOInterruptControllersLock
);
376 gIOInterruptControllers
->removeObject(name
);
378 IOLockUnlock(gIOInterruptControllersLock
);
380 return kIOReturnSuccess
;
383 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
387 IOLockLock(gIOInterruptControllersLock
);
390 object
= gIOInterruptControllers
->getObject(name
);
395 IOLockSleep(gIOInterruptControllersLock
,
396 gIOInterruptControllers
, THREAD_UNINT
);
399 IOLockUnlock(gIOInterruptControllersLock
);
400 return OSDynamicCast(IOInterruptController
, object
);
404 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
406 IOCPUInterruptController
*controller
;
408 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
409 if (controller
) controller
->setCPUInterruptProperties(service
);
412 bool IOPlatformExpert::atInterruptLevel(void)
414 return ml_at_interrupt_context();
417 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
422 void IOPlatformExpert::getUTCTimeOfDay(clock_sec_t
* secs
, clock_nsec_t
* nsecs
)
424 *secs
= getGMTTimeOfDay();
428 void IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs
, __unused clock_nsec_t nsecs
)
430 setGMTTimeOfDay(secs
);
434 //*********************************************************************************
437 //*********************************************************************************
439 void IOPlatformExpert::
440 PMLog(const char *who
, unsigned long event
,
441 unsigned long param1
, unsigned long param2
)
445 clock_get_system_microtime(&nows
, &nowus
);
446 nowus
+= (nows
% 1000) * 1000000;
448 kprintf("pm%u %p %.30s %d %lx %lx\n",
449 nowus
, OBFUSCATE(current_thread()), who
, // Identity
450 (int) event
, (long)OBFUSCATE(param1
), (long)OBFUSCATE(param2
)); // Args
454 //*********************************************************************************
455 // PMInstantiatePowerDomains
457 // In this vanilla implementation, a Root Power Domain is instantiated.
458 // All other objects which register will be children of this Root.
459 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
460 // in a platform-specific subclass.
461 //*********************************************************************************
463 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
465 root
= new IOPMrootDomain
;
472 //*********************************************************************************
475 // In this vanilla implementation, all callers are made children of the root power domain.
476 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
477 //*********************************************************************************
479 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
481 root
->addPowerChild ( theDevice
);
484 //*********************************************************************************
487 //*********************************************************************************
489 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
491 return ((_pePMFeatures
& featureMask
) != 0);
494 //*********************************************************************************
497 //*********************************************************************************
499 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
501 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
504 //*********************************************************************************
505 // numBatteriesSupported
507 //*********************************************************************************
509 int IOPlatformExpert::numBatteriesSupported (void)
511 return (_peNumBatteriesSupported
);
514 //*********************************************************************************
517 // This method is called by the instantiated sublass of the platform expert to
518 // determine how a device should be inserted into the Power Domain. The subclass
519 // provides an XML power tree description against which a device is matched based
520 // on class and provider. If a match is found this routine returns true in addition
521 // to flagging the description tree at the appropriate node that a device has been
522 // registered for the given service.
523 //*********************************************************************************
525 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
528 unsigned int numPowerTreeNodes
;
529 OSDictionary
* entry
;
530 OSDictionary
* matchingDictionary
;
531 OSDictionary
* providerDictionary
;
532 OSDictionary
* deviceDictionary
;
533 OSDictionary
* nubDictionary
;
535 bool nodeFound
= false;
536 bool continueSearch
= false;
537 bool deviceMatch
= false;
538 bool providerMatch
= false;
539 bool multiParentMatch
= false;
541 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
544 numPowerTreeNodes
= inSubTree
->getCount ();
546 // iterate through the power tree to find a home for this device
548 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
550 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
552 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
553 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
555 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
556 if ( matchingDictionary
) {
558 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
559 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
560 deviceDictionary
->release ();
564 providerMatch
= true; // we indicate a match if there is no nub or provider
565 if ( theNub
&& providerDictionary
) {
566 providerMatch
= false;
567 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
568 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
569 nubDictionary
->release ();
573 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
574 if (deviceMatch
&& providerMatch
) {
575 if (NULL
!= multipleParentKeyValue
) {
576 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
577 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
581 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
583 // if the power tree specifies a provider dictionary but theNub is
584 // NULL then we cannot match with this entry.
586 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
589 // if this node is THE ONE...then register the device
592 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
594 if ( kIOLogPower
& gIOKitDebug
)
595 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
597 numInstancesRegistered
++;
599 // determine if we need to search for additional nodes for this item
600 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
606 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
608 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
609 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
610 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
613 if ( false == continueSearch
)
617 return ( nodeFound
);
620 //*********************************************************************************
621 // RegisterServiceInTree
623 // Register a device at the specified node of our power tree.
624 //*********************************************************************************
626 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
628 IOService
* aService
;
629 bool registered
= false;
631 unsigned int numChildren
;
632 OSDictionary
* child
;
634 // make sure someone is not already registered here
636 if ( NULL
== theTreeNode
->getObject ("service") ) {
638 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
640 // 1. CHILDREN ------------------
642 // we registered the node in the tree...now if the node has children
643 // registered we must tell this service to add them.
645 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
646 numChildren
= children
->getCount ();
647 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
648 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
649 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
650 theService
->addPowerChild (aService
);
655 // 2. PARENT --------------------
657 // also we must notify the parent of this node (if a registered service
658 // exists there) of a new child.
660 if ( theTreeParentNode
) {
661 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
662 if (aService
!= theProvider
)
663 aService
->addPowerChild (theService
);
673 //*********************************************************************************
674 // printDictionaryKeys
676 // Print the keys for the given dictionary and selected contents.
677 //*********************************************************************************
678 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
680 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
687 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
691 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
693 // if this is the IOClass key, print it's contents
695 if ( mkey
->isEqualTo ("IOClass") ) {
696 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
697 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
700 // if this is an IOProviderClass key print it
702 if ( mkey
->isEqualTo ("IOProviderClass") ) {
703 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
704 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
708 // also print IONameMatch keys
709 if ( mkey
->isEqualTo ("IONameMatch") ) {
710 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
711 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
714 // also print IONameMatched keys
716 if ( mkey
->isEqualTo ("IONameMatched") ) {
717 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
718 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
724 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
726 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
728 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
734 if ( mkey
->isEqualTo ("name") ) {
737 getCStringForObject(inDictionary
->getObject("name"), nameStr
,
739 if (strlen(nameStr
) > 0)
740 IOLog ("%s name is %s\n", inMsg
, nameStr
);
743 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
752 getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
)
757 if ( (NULL
== inObj
) || (NULL
== outStr
))
760 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
762 if ((0 == strncmp(objString
, "OSString", sizeof("OSString"))) ||
763 (0 == strncmp(objString
, "OSSymbol", sizeof("OSSymbol"))))
764 strlcpy(outStr
, ((OSString
*)inObj
)->getCStringNoCopy(), outStrLen
);
766 else if (0 == strncmp(objString
, "OSData", sizeof("OSData"))) {
767 len
= ((OSData
*)inObj
)->getLength();
768 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
769 if (buffer
&& (len
> 0)) {
770 for (i
=0; i
< len
; i
++) {
771 outStr
[i
] = buffer
[i
];
778 /* IOShutdownNotificationsTimedOut
779 * - Called from a timer installed by PEHaltRestart
781 static void IOShutdownNotificationsTimedOut(
782 thread_call_param_t p0
,
783 thread_call_param_t p1
)
785 #ifdef CONFIG_EMBEDDED
786 /* 30 seconds has elapsed - panic */
787 panic("Halt/Restart Timed Out");
789 #else /* ! CONFIG_EMBEDDED */
790 int type
= (int)(long)p0
;
792 /* 30 seconds has elapsed - resume shutdown */
793 if(gIOPlatform
) gIOPlatform
->haltRestart(type
);
794 #endif /* CONFIG_EMBEDDED */
801 * Callouts from BSD for machine name & model
804 boolean_t
PEGetMachineName( char * name
, int maxLength
)
807 return( gIOPlatform
->getMachineName( name
, maxLength
));
812 boolean_t
PEGetModelName( char * name
, int maxLength
)
815 return( gIOPlatform
->getModelName( name
, maxLength
));
820 int PEGetPlatformEpoch(void)
823 return( gIOPlatform
->getBootROMType());
828 int PEHaltRestart(unsigned int type
)
830 IOPMrootDomain
*pmRootDomain
;
831 AbsoluteTime deadline
;
832 thread_call_t shutdown_hang
;
833 IORegistryEntry
*node
;
835 uint32_t timeout
= 30;
836 static boolean_t panic_begin_called
= FALSE
;
838 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
|| type
== kPEUPSDelayHaltCPU
)
840 pmRootDomain
= IOService::getPMRootDomain();
841 /* Notify IOKit PM clients of shutdown/restart
842 Clients subscribe to this message with a call to
843 IOService::registerInterest()
846 /* Spawn a thread that will panic in 30 seconds.
847 If all goes well the machine will be off by the time
848 the timer expires. If the device wants a different
849 timeout, use that value instead of 30 seconds.
852 #define RESTART_NODE_PATH "/defaults"
854 #define RESTART_NODE_PATH "/chosen"
856 node
= IORegistryEntry::fromPath( RESTART_NODE_PATH
, gIODTPlane
);
858 data
= OSDynamicCast( OSData
, node
->getProperty( "halt-restart-timeout" ) );
859 if ( data
&& data
->getLength() == 4 )
860 timeout
= *((uint32_t *) data
->getBytesNoCopy());
863 shutdown_hang
= thread_call_allocate( &IOShutdownNotificationsTimedOut
,
864 (thread_call_param_t
)(uintptr_t) type
);
865 clock_interval_to_deadline( timeout
, kSecondScale
, &deadline
);
866 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
868 pmRootDomain
->handlePlatformHaltRestart(type
);
869 /* This notification should have few clients who all do
870 their work synchronously.
872 In this "shutdown notification" context we don't give
873 drivers the option of working asynchronously and responding
874 later. PM internals make it very hard to wait for asynchronous
878 else if(type
== kPEPanicRestartCPU
|| type
== kPEPanicSync
)
880 if (type
== kPEPanicRestartCPU
) {
881 // Notify any listeners that we're done collecting
882 // panic data before we call through to do the restart
883 IOCPURunPlatformPanicActions(kPEPanicEnd
);
885 // Callout to shutdown the disk driver once we've returned from the
886 // kPEPanicEnd callback (and we know all core dumps on this system
888 IOCPURunPlatformPanicActions(kPEPanicDiskShutdown
);
891 // Do an initial sync to flush as much panic data as possible,
892 // in case we have a problem in one of the platorm panic handlers.
893 // After running the platform handlers, do a final sync w/
894 // platform hardware quiesced for the panic.
895 PE_sync_panic_buffers();
896 IOCPURunPlatformPanicActions(type
);
897 PE_sync_panic_buffers();
899 else if (type
== kPEPanicEnd
) {
901 if (coprocessor_cross_panic_enabled
)
903 IOCPURunPlatformPanicActions(type
);
905 } else if (type
== kPEPanicBegin
) {
907 if (coprocessor_cross_panic_enabled
)
910 // Only call the kPEPanicBegin callout once
911 if (!panic_begin_called
) {
912 panic_begin_called
= TRUE
;
913 IOCPURunPlatformPanicActions(type
);
918 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
922 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
924 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
928 void PESavePanicInfoAction(void *buffer
, size_t length
)
930 IOCPURunPlatformPanicSyncAction(buffer
, length
);
935 inline static int init_gIOOptionsEntry(void)
937 IORegistryEntry
*entry
;
939 volatile void **options
;
945 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
949 nvram_entry
= (void *) OSDynamicCast(IODTNVRAM
, entry
);
953 options
= (volatile void **) &gIOOptionsEntry
;
954 if (!OSCompareAndSwapPtr(NULL
, nvram_entry
, options
)) {
967 /* pass in a NULL value if you just want to figure out the len */
968 boolean_t
PEReadNVRAMProperty(const char *symbol
, void *value
,
978 if (init_gIOOptionsEntry() < 0)
984 obj
= gIOOptionsEntry
->getProperty(symbol
);
988 /* convert to data */
989 data
= OSDynamicCast(OSData
, obj
);
993 *len
= data
->getLength();
994 vlen
= min(vlen
, *len
);
996 memcpy((void *) value
, data
->getBytesNoCopy(), vlen
);
1005 PEWriteNVRAMBooleanProperty(const char *symbol
, boolean_t value
)
1007 const OSSymbol
*sym
= NULL
;
1008 OSBoolean
*data
= NULL
;
1011 if (symbol
== NULL
) {
1015 if (init_gIOOptionsEntry() < 0) {
1019 if ((sym
= OSSymbol::withCStringNoCopy(symbol
)) == NULL
) {
1023 data
= value
? kOSBooleanTrue
: kOSBooleanFalse
;
1024 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1028 /* success, force the NVRAM to flush writes */
1030 gIOOptionsEntry
->sync();
1037 boolean_t
PEWriteNVRAMProperty(const char *symbol
, const void *value
,
1038 const unsigned int len
)
1040 const OSSymbol
*sym
;
1044 if (!symbol
|| !value
|| !len
)
1047 if (init_gIOOptionsEntry() < 0)
1050 sym
= OSSymbol::withCStringNoCopy(symbol
);
1054 data
= OSData::withBytes((void *) value
, len
);
1058 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1065 gIOOptionsEntry
->sync();
1074 boolean_t
PERemoveNVRAMProperty(const char *symbol
)
1076 const OSSymbol
*sym
;
1081 if (init_gIOOptionsEntry() < 0)
1084 sym
= OSSymbol::withCStringNoCopy(symbol
);
1088 gIOOptionsEntry
->removeProperty(sym
);
1092 gIOOptionsEntry
->sync();
1100 long PEGetGMTTimeOfDay(void)
1105 PEGetUTCTimeOfDay(&secs
, &usecs
);
1109 void PESetGMTTimeOfDay(long secs
)
1111 PESetUTCTimeOfDay(secs
, 0);
1114 void PEGetUTCTimeOfDay(clock_sec_t
* secs
, clock_usec_t
* usecs
)
1116 clock_nsec_t nsecs
= 0;
1120 gIOPlatform
->getUTCTimeOfDay(secs
, &nsecs
);
1122 assert(nsecs
< NSEC_PER_SEC
);
1123 *usecs
= nsecs
/ NSEC_PER_USEC
;
1126 void PESetUTCTimeOfDay(clock_sec_t secs
, clock_usec_t usecs
)
1128 assert(usecs
< USEC_PER_SEC
);
1130 gIOPlatform
->setUTCTimeOfDay(secs
, usecs
* NSEC_PER_USEC
);
1135 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
1138 IORegistryEntry
* entry
;
1139 OSString
* string
= 0;
1143 entry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
1148 data1
= OSDynamicCast( OSData
, entry
->getProperty( "unique-chip-id" ) );
1149 if ( data1
&& data1
->getLength( ) == 8 )
1153 data2
= OSDynamicCast( OSData
, entry
->getProperty( "chip-id" ) );
1154 if ( data2
&& data2
->getLength( ) == 4 )
1157 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1158 const uuid_t space
= { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
1160 SHA1Init( &context
);
1161 SHA1Update( &context
, space
, sizeof( space
) );
1162 SHA1Update( &context
, data1
->getBytesNoCopy( ), data1
->getLength( ) );
1163 SHA1Update( &context
, data2
->getBytesNoCopy( ), data2
->getLength( ) );
1164 SHA1Final( digest
, &context
);
1166 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1167 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1169 uuid_unparse( digest
, uuid
);
1170 string
= OSString::withCString( uuid
);
1176 #else /* !CONFIG_EMBEDDED */
1178 * If we have panic debugging enabled and a prod-fused coprocessor,
1179 * disable cross panics so that the co-processor doesn't cause the system
1180 * to reset when we enter the debugger or hit a panic on the x86 side.
1182 if ( panicDebugging
)
1184 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1187 data
= OSDynamicCast( OSData
, entry
->getProperty( "EffectiveProductionStatus" ) );
1188 if ( data
&& ( data
->getLength( ) == sizeof( UInt8
) ) ) {
1189 UInt8
*isProdFused
= (UInt8
*) data
->getBytesNoCopy( );
1190 if ( *isProdFused
) {
1191 coprocessor_cross_panic_enabled
= FALSE
;
1198 entry
= IORegistryEntry::fromPath( "/efi/platform", gIODTPlane
);
1201 data
= OSDynamicCast( OSData
, entry
->getProperty( "system-id" ) );
1202 if ( data
&& data
->getLength( ) == 16 )
1205 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1206 const uuid_t space
= { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
1208 SHA1Init( &context
);
1209 SHA1Update( &context
, space
, sizeof( space
) );
1210 SHA1Update( &context
, data
->getBytesNoCopy( ), data
->getLength( ) );
1211 SHA1Final( digest
, &context
);
1213 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1214 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1216 uuid_unparse( digest
, uuid
);
1217 string
= OSString::withCString( uuid
);
1222 #endif /* !CONFIG_EMBEDDED */
1226 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1229 data
= OSDynamicCast( OSData
, entry
->getProperty( "platform-uuid" ) );
1230 if ( data
&& data
->getLength( ) == sizeof( uuid_t
) )
1232 uuid_unparse( ( uint8_t * ) data
->getBytesNoCopy( ), uuid
);
1233 string
= OSString::withCString( uuid
);
1242 getProvider( )->setProperty( kIOPlatformUUIDKey
, string
);
1243 publishResource( kIOPlatformUUIDKey
, string
);
1248 publishResource("IONVRAM");
1251 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
1252 bool waitForFunction
,
1253 void *param1
, void *param2
,
1254 void *param3
, void *param4
)
1256 IOService
*service
, *_resources
;
1258 if (waitForFunction
) {
1259 _resources
= waitForService(resourceMatching(functionName
));
1261 _resources
= getResourceService();
1263 if (_resources
== 0) return kIOReturnUnsupported
;
1265 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
1266 if (service
== 0) return kIOReturnUnsupported
;
1268 return service
->callPlatformFunction(functionName
, waitForFunction
,
1269 param1
, param2
, param3
, param4
);
1272 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1277 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1280 #define super IOPlatformExpert
1282 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
1284 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
1285 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
1286 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
1287 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
1288 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
1289 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
1290 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
1291 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
1293 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1295 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
1298 if( !super::probe( provider
, score
))
1301 // check machine types
1302 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
1308 bool IODTPlatformExpert::configure( IOService
* provider
)
1310 if( !super::configure( provider
))
1313 processTopLevel( provider
);
1318 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
1322 nub
= new IOPlatformDevice
;
1324 if( !nub
->init( from
, gIODTPlane
)) {
1332 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
1334 IORegistryEntry
* next
;
1339 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
1341 if( 0 == (nub
= createNub( next
)))
1344 nub
->attach( parent
);
1345 nub
->registerService();
1353 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
1356 IORegistryEntry
* next
;
1357 IORegistryEntry
* cpus
;
1358 IORegistryEntry
* options
;
1361 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
1363 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
1364 next
->detachAll( gIODTPlane
);
1369 // Publish an IODTNVRAM class on /options.
1370 options
= rootEntry
->childFromPath("options", gIODTPlane
);
1372 dtNVRAM
= new IODTNVRAM
;
1374 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
1378 dtNVRAM
->attach(this);
1379 dtNVRAM
->registerService();
1385 // Publish the cpus.
1386 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
1389 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
1393 // publish top level, minus excludeList
1394 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
1397 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
1399 if( nub
->getDeviceMemory())
1400 return( kIOReturnSuccess
);
1402 IODTResolveAddressing( nub
, "reg", 0);
1404 return( kIOReturnSuccess
);
1407 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
1408 OSString
* name
, OSString
** matched
) const
1410 return( IODTCompareNubName( nub
, name
, matched
)
1411 || super::compareNubName( nub
, name
, matched
) );
1414 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1424 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1426 str
= (const char *) prop
->getBytesNoCopy();
1428 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1429 str
+= strlen( "AAPL," );
1432 while( (c
= *str
++)) {
1433 if( (c
== '/') || (c
== ' '))
1437 if( len
>= maxLength
)
1447 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1453 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1457 strlcpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1462 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1464 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1466 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1468 super::registerNVRAMController(nvram
);
1471 int IODTPlatformExpert::haltRestart(unsigned int type
)
1473 if (dtNVRAM
) dtNVRAM
->sync();
1475 return super::haltRestart(type
);
1478 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1481 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1482 else return kIOReturnNotReady
;
1485 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1488 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1489 else return kIOReturnNotReady
;
1492 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1493 IORegistryEntry
* entry
,
1494 const OSSymbol
** name
, OSData
** value
)
1496 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1497 else return kIOReturnNotReady
;
1500 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1501 IORegistryEntry
* entry
,
1502 const OSSymbol
* name
, OSData
* value
)
1504 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1505 else return kIOReturnNotReady
;
1508 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1510 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1514 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1515 IOByteCount offset
, UInt8
* buffer
,
1518 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1520 else return kIOReturnNotReady
;
1523 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1524 IOByteCount offset
, UInt8
* buffer
,
1527 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1529 else return kIOReturnNotReady
;
1532 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1534 IOByteCount lengthSaved
= 0;
1536 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1538 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1543 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1544 UInt8
* serialNumber
;
1545 unsigned int serialNumberSize
;
1546 unsigned short pos
= 0;
1550 if (myProperty
!= NULL
) {
1551 serialNumberSize
= myProperty
->getLength();
1552 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1553 temp
= (char*)serialNumber
;
1554 if (serialNumberSize
> 0) {
1555 // check to see if this is a CTO serial number...
1556 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1558 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1559 memcpy(SerialNo
, serialNumber
+ 12, 8);
1560 memcpy(&SerialNo
[8], serialNumber
, 3);
1562 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1564 } else { // just a normal serial number
1565 memcpy(SerialNo
, serialNumber
+ 13, 8);
1566 memcpy(&SerialNo
[8], serialNumber
, 3);
1569 return OSString::withCString(SerialNo
);
1576 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1579 #define super IOService
1581 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1583 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1584 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1585 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1586 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1588 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1590 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1591 OSString
** matched
) const
1593 return( IODTCompareNubName( this, name
, matched
));
1597 IOPlatformExpertDevice::initWithArgs(
1598 void * dtTop
, void * p2
, void * p3
, void * p4
)
1600 IORegistryEntry
* dt
= 0;
1603 // dtTop may be zero on non- device tree systems
1604 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1605 ok
= super::init( dt
, gIODTPlane
);
1613 workLoop
= IOWorkLoop::workLoop();
1620 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1625 IOReturn
IOPlatformExpertDevice::setProperties( OSObject
* properties
)
1627 OSDictionary
* dictionary
;
1631 status
= super::setProperties( properties
);
1632 if ( status
!= kIOReturnUnsupported
) return status
;
1634 status
= IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator
);
1635 if ( status
!= kIOReturnSuccess
) return status
;
1637 dictionary
= OSDynamicCast( OSDictionary
, properties
);
1638 if ( dictionary
== 0 ) return kIOReturnBadArgument
;
1640 object
= dictionary
->getObject( kIOPlatformUUIDKey
);
1643 IORegistryEntry
* entry
;
1647 string
= ( OSString
* ) getProperty( kIOPlatformUUIDKey
);
1648 if ( string
) return kIOReturnNotPermitted
;
1650 string
= OSDynamicCast( OSString
, object
);
1651 if ( string
== 0 ) return kIOReturnBadArgument
;
1653 status
= uuid_parse( string
->getCStringNoCopy( ), uuid
);
1654 if ( status
!= 0 ) return kIOReturnBadArgument
;
1656 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1659 entry
->setProperty( "platform-uuid", uuid
, sizeof( uuid_t
) );
1663 setProperty( kIOPlatformUUIDKey
, string
);
1664 publishResource( kIOPlatformUUIDKey
, string
);
1666 return kIOReturnSuccess
;
1669 return kIOReturnUnsupported
;
1672 IOReturn
IOPlatformExpertDevice::newUserClient( task_t owningTask
, void * securityID
,
1673 UInt32 type
, OSDictionary
* properties
,
1674 IOUserClient
** handler
)
1676 IOReturn err
= kIOReturnSuccess
;
1677 IOUserClient
* newConnect
= 0;
1678 IOUserClient
* theConnect
= 0;
1682 case kIOKitDiagnosticsClientType
:
1683 newConnect
= IOKitDiagnosticsClient::withTask(owningTask
);
1684 if (!newConnect
) err
= kIOReturnNotPermitted
;
1687 err
= kIOReturnBadArgument
;
1692 if ((false == newConnect
->attach(this))
1693 || (false == newConnect
->start(this)))
1695 newConnect
->detach( this );
1696 newConnect
->release();
1697 err
= kIOReturnNotPermitted
;
1700 theConnect
= newConnect
;
1703 *handler
= theConnect
;
1707 void IOPlatformExpertDevice::free()
1710 workLoop
->release();
1713 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1716 #define super IOService
1718 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1720 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1721 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1722 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1723 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1725 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1727 bool IOPlatformDevice::compareName( OSString
* name
,
1728 OSString
** matched
) const
1730 return( ((IOPlatformExpert
*)getProvider())->
1731 compareNubName( this, name
, matched
));
1734 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1739 IOReturn
IOPlatformDevice::getResources( void )
1741 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1744 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1746 /*********************************************************************
1747 * IOPanicPlatform class
1749 * If no legitimate IOPlatformDevice matches, this one does and panics
1750 * the kernel with a suitable message.
1751 *********************************************************************/
1753 class IOPanicPlatform
: IOPlatformExpert
{
1754 OSDeclareDefaultStructors(IOPanicPlatform
);
1757 bool start(IOService
* provider
) APPLE_KEXT_OVERRIDE
;
1761 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1764 bool IOPanicPlatform::start(IOService
* provider
) {
1765 const char * platform_name
= "(unknown platform name)";
1767 if (provider
) platform_name
= provider
->getName();
1769 panic("Unable to find driver for this platform: \"%s\".\n",