2 * Copyright (c) 1998-2014 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 #if defined(__x86_64__)
59 * This will eventually be properly exported in
60 * <rdar://problem/31181482> ER: Expose coprocessor version (T208/T290) in a kernel/kext header
61 * although we'll always need to hardcode this here since we won't be able to include whatever
62 * header this ends up in.
64 #define kCoprocessorMinVersion 0x00020000
67 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
68 static void getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
);
70 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
72 #define super IOService
74 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
76 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
77 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
78 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 2);
79 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 3);
80 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 4);
82 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
83 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
84 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
85 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
86 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
87 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
88 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
90 static IOPlatformExpert
* gIOPlatform
;
91 static OSDictionary
* gIOInterruptControllers
;
92 static IOLock
* gIOInterruptControllersLock
;
93 static IODTNVRAM
*gIOOptionsEntry
;
95 OSSymbol
* gPlatformInterruptControllerName
;
97 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
99 bool IOPlatformExpert::attach( IOService
* provider
)
102 if( !super::attach( provider
))
108 bool IOPlatformExpert::start( IOService
* provider
)
110 IORangeAllocator
* physicalRanges
;
111 OSData
* busFrequency
;
114 #if defined(__x86_64__)
115 IORegistryEntry
*platform_entry
= NULL
;
116 OSData
*coprocessor_version_obj
= NULL
;
117 uint64_t coprocessor_version
= 0;
120 if (!super::start(provider
))
123 // Override the mapper present flag is requested by boot arguments, if SIP disabled.
125 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS
) == 0)
126 #endif /* CONFIG_CSR */
128 if (PE_parse_boot_argn("dart", &debugFlags
, sizeof (debugFlags
)) && (debugFlags
== 0))
129 removeProperty(kIOPlatformMapperPresentKey
);
130 #if DEBUG || DEVELOPMENT
131 if (PE_parse_boot_argn("-x", &debugFlags
, sizeof (debugFlags
)))
132 removeProperty(kIOPlatformMapperPresentKey
);
133 #endif /* DEBUG || DEVELOPMENT */
136 // Register the presence or lack thereof a system
137 // PCI address mapper with the IOMapper class
138 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
140 gIOInterruptControllers
= OSDictionary::withCapacity(1);
141 gIOInterruptControllersLock
= IOLockAlloc();
143 // Correct the bus frequency in the device tree.
144 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
145 provider
->setProperty("clock-frequency", busFrequency
);
146 busFrequency
->release();
148 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
150 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
151 IORangeAllocator::kLocking
);
152 assert(physicalRanges
);
153 setProperty("Platform Memory Ranges", physicalRanges
);
158 PMInstantiatePowerDomains();
160 // Parse the serial-number data and publish a user-readable string
161 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
162 if (mydata
!= NULL
) {
163 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
164 if (serNoString
!= NULL
) {
165 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
166 serNoString
->release();
170 #if defined(__x86_64__)
171 platform_entry
= IORegistryEntry::fromPath(kIODeviceTreePlane
":/efi/platform");
172 if (platform_entry
!= NULL
) {
173 coprocessor_version_obj
= OSDynamicCast(OSData
, platform_entry
->getProperty("apple-coprocessor-version"));
174 if ((coprocessor_version_obj
!= NULL
) && (coprocessor_version_obj
->getLength() <= sizeof(coprocessor_version
))) {
175 memcpy(&coprocessor_version
, coprocessor_version_obj
->getBytesNoCopy(), coprocessor_version_obj
->getLength());
176 if (coprocessor_version
>= kCoprocessorMinVersion
) {
177 coprocessor_paniclog_flush
= TRUE
;
180 platform_entry
->release();
182 #endif /* defined(__x86_64__) */
184 return( configure(provider
) );
187 bool IOPlatformExpert::configure( IOService
* provider
)
193 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
196 while( (dict
= OSDynamicCast( OSDictionary
,
197 topLevel
->getAnyObject()))) {
199 topLevel
->removeObject( dict
);
200 nub
= createNub( dict
);
205 nub
->registerService();
212 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
216 nub
= new IOPlatformDevice
;
218 if( !nub
->init( from
)) {
226 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
227 OSString
* name
, OSString
** matched
) const
229 return( nub
->IORegistryEntry::compareName( name
, matched
));
232 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
234 return( kIOReturnSuccess
);
237 long IOPlatformExpert::getBootROMType(void)
239 return _peBootROMType
;
242 long IOPlatformExpert::getChipSetType(void)
244 return _peChipSetType
;
247 long IOPlatformExpert::getMachineType(void)
249 return _peMachineType
;
252 void IOPlatformExpert::setBootROMType(long peBootROMType
)
254 _peBootROMType
= peBootROMType
;
257 void IOPlatformExpert::setChipSetType(long peChipSetType
)
259 _peChipSetType
= peChipSetType
;
262 void IOPlatformExpert::setMachineType(long peMachineType
)
264 _peMachineType
= peMachineType
;
267 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
272 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
277 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
282 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
284 return(OSDynamicCast(IORangeAllocator
,
285 getProperty("Platform Memory Ranges")));
288 int (*PE_halt_restart
)(unsigned int type
) = 0;
290 int IOPlatformExpert::haltRestart(unsigned int type
)
292 if (type
== kPEPanicSync
) return 0;
294 if (type
== kPEHangCPU
) while (true) {}
296 if (type
== kPEUPSDelayHaltCPU
) {
297 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
302 // On ARM kPEPanicRestartCPU is supported in the drivers
303 if (type
== kPEPanicRestartCPU
)
304 type
= kPERestartCPU
;
307 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
311 void IOPlatformExpert::sleepKernel(void)
317 intState
= ml_set_interrupts_enabled(false);
319 for (cnt
= 0; cnt
< 10000; cnt
++) {
323 ml_set_interrupts_enabled(intState
);
325 // PE_initialize_console(0, kPEDisableScreen);
329 // PE_initialize_console(0, kPEEnableScreen);
333 long IOPlatformExpert::getGMTTimeOfDay(void)
338 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
343 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
345 return( PE_current_console( consoleInfo
));
348 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
351 return( PE_initialize_console( consoleInfo
, op
));
354 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
356 IOLockLock(gIOInterruptControllersLock
);
358 gIOInterruptControllers
->setObject(name
, interruptController
);
360 IOLockWakeup(gIOInterruptControllersLock
,
361 gIOInterruptControllers
, /* one-thread */ false);
363 IOLockUnlock(gIOInterruptControllersLock
);
365 return kIOReturnSuccess
;
368 IOReturn
IOPlatformExpert::deregisterInterruptController(OSSymbol
*name
)
370 IOLockLock(gIOInterruptControllersLock
);
372 gIOInterruptControllers
->removeObject(name
);
374 IOLockUnlock(gIOInterruptControllersLock
);
376 return kIOReturnSuccess
;
379 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
383 IOLockLock(gIOInterruptControllersLock
);
386 object
= gIOInterruptControllers
->getObject(name
);
391 IOLockSleep(gIOInterruptControllersLock
,
392 gIOInterruptControllers
, THREAD_UNINT
);
395 IOLockUnlock(gIOInterruptControllersLock
);
396 return OSDynamicCast(IOInterruptController
, object
);
400 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
402 IOCPUInterruptController
*controller
;
404 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
405 if (controller
) controller
->setCPUInterruptProperties(service
);
408 bool IOPlatformExpert::atInterruptLevel(void)
410 return ml_at_interrupt_context();
413 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
418 void IOPlatformExpert::getUTCTimeOfDay(clock_sec_t
* secs
, clock_nsec_t
* nsecs
)
420 *secs
= getGMTTimeOfDay();
424 void IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs
, __unused clock_nsec_t nsecs
)
426 setGMTTimeOfDay(secs
);
430 //*********************************************************************************
433 //*********************************************************************************
435 void IOPlatformExpert::
436 PMLog(const char *who
, unsigned long event
,
437 unsigned long param1
, unsigned long param2
)
441 clock_get_system_microtime(&nows
, &nowus
);
442 nowus
+= (nows
% 1000) * 1000000;
444 kprintf("pm%u %p %.30s %d %lx %lx\n",
445 nowus
, OBFUSCATE(current_thread()), who
, // Identity
446 (int) event
, (long)OBFUSCATE(param1
), (long)OBFUSCATE(param2
)); // Args
450 //*********************************************************************************
451 // PMInstantiatePowerDomains
453 // In this vanilla implementation, a Root Power Domain is instantiated.
454 // All other objects which register will be children of this Root.
455 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
456 // in a platform-specific subclass.
457 //*********************************************************************************
459 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
461 root
= new IOPMrootDomain
;
468 //*********************************************************************************
471 // In this vanilla implementation, all callers are made children of the root power domain.
472 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
473 //*********************************************************************************
475 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
477 root
->addPowerChild ( theDevice
);
480 //*********************************************************************************
483 //*********************************************************************************
485 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
487 return ((_pePMFeatures
& featureMask
) != 0);
490 //*********************************************************************************
493 //*********************************************************************************
495 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
497 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
500 //*********************************************************************************
501 // numBatteriesSupported
503 //*********************************************************************************
505 int IOPlatformExpert::numBatteriesSupported (void)
507 return (_peNumBatteriesSupported
);
510 //*********************************************************************************
513 // This method is called by the instantiated sublass of the platform expert to
514 // determine how a device should be inserted into the Power Domain. The subclass
515 // provides an XML power tree description against which a device is matched based
516 // on class and provider. If a match is found this routine returns true in addition
517 // to flagging the description tree at the appropriate node that a device has been
518 // registered for the given service.
519 //*********************************************************************************
521 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
524 unsigned int numPowerTreeNodes
;
525 OSDictionary
* entry
;
526 OSDictionary
* matchingDictionary
;
527 OSDictionary
* providerDictionary
;
528 OSDictionary
* deviceDictionary
;
529 OSDictionary
* nubDictionary
;
531 bool nodeFound
= false;
532 bool continueSearch
= false;
533 bool deviceMatch
= false;
534 bool providerMatch
= false;
535 bool multiParentMatch
= false;
537 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
540 numPowerTreeNodes
= inSubTree
->getCount ();
542 // iterate through the power tree to find a home for this device
544 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
546 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
548 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
549 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
551 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
552 if ( matchingDictionary
) {
554 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
555 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
556 deviceDictionary
->release ();
560 providerMatch
= true; // we indicate a match if there is no nub or provider
561 if ( theNub
&& providerDictionary
) {
562 providerMatch
= false;
563 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
564 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
565 nubDictionary
->release ();
569 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
570 if (deviceMatch
&& providerMatch
) {
571 if (NULL
!= multipleParentKeyValue
) {
572 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
573 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
577 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
579 // if the power tree specifies a provider dictionary but theNub is
580 // NULL then we cannot match with this entry.
582 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
585 // if this node is THE ONE...then register the device
588 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
590 if ( kIOLogPower
& gIOKitDebug
)
591 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
593 numInstancesRegistered
++;
595 // determine if we need to search for additional nodes for this item
596 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
602 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
604 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
605 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
606 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
609 if ( false == continueSearch
)
613 return ( nodeFound
);
616 //*********************************************************************************
617 // RegisterServiceInTree
619 // Register a device at the specified node of our power tree.
620 //*********************************************************************************
622 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
624 IOService
* aService
;
625 bool registered
= false;
627 unsigned int numChildren
;
628 OSDictionary
* child
;
630 // make sure someone is not already registered here
632 if ( NULL
== theTreeNode
->getObject ("service") ) {
634 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
636 // 1. CHILDREN ------------------
638 // we registered the node in the tree...now if the node has children
639 // registered we must tell this service to add them.
641 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
642 numChildren
= children
->getCount ();
643 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
644 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
645 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
646 theService
->addPowerChild (aService
);
651 // 2. PARENT --------------------
653 // also we must notify the parent of this node (if a registered service
654 // exists there) of a new child.
656 if ( theTreeParentNode
) {
657 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
658 if (aService
!= theProvider
)
659 aService
->addPowerChild (theService
);
669 //*********************************************************************************
670 // printDictionaryKeys
672 // Print the keys for the given dictionary and selected contents.
673 //*********************************************************************************
674 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
676 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
683 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
687 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
689 // if this is the IOClass key, print it's contents
691 if ( mkey
->isEqualTo ("IOClass") ) {
692 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
693 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
696 // if this is an IOProviderClass key print it
698 if ( mkey
->isEqualTo ("IOProviderClass") ) {
699 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
700 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
704 // also print IONameMatch keys
705 if ( mkey
->isEqualTo ("IONameMatch") ) {
706 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
707 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
710 // also print IONameMatched keys
712 if ( mkey
->isEqualTo ("IONameMatched") ) {
713 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
714 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
720 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
722 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
724 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
730 if ( mkey
->isEqualTo ("name") ) {
733 getCStringForObject(inDictionary
->getObject("name"), nameStr
,
735 if (strlen(nameStr
) > 0)
736 IOLog ("%s name is %s\n", inMsg
, nameStr
);
739 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
748 getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
)
753 if ( (NULL
== inObj
) || (NULL
== outStr
))
756 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
758 if ((0 == strncmp(objString
, "OSString", sizeof("OSString"))) ||
759 (0 == strncmp(objString
, "OSSymbol", sizeof("OSSymbol"))))
760 strlcpy(outStr
, ((OSString
*)inObj
)->getCStringNoCopy(), outStrLen
);
762 else if (0 == strncmp(objString
, "OSData", sizeof("OSData"))) {
763 len
= ((OSData
*)inObj
)->getLength();
764 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
765 if (buffer
&& (len
> 0)) {
766 for (i
=0; i
< len
; i
++) {
767 outStr
[i
] = buffer
[i
];
774 /* IOShutdownNotificationsTimedOut
775 * - Called from a timer installed by PEHaltRestart
777 static void IOShutdownNotificationsTimedOut(
778 thread_call_param_t p0
,
779 thread_call_param_t p1
)
781 #ifdef CONFIG_EMBEDDED
782 /* 30 seconds has elapsed - panic */
783 panic("Halt/Restart Timed Out");
785 #else /* ! CONFIG_EMBEDDED */
786 int type
= (int)(long)p0
;
788 /* 30 seconds has elapsed - resume shutdown */
789 if(gIOPlatform
) gIOPlatform
->haltRestart(type
);
790 #endif /* CONFIG_EMBEDDED */
797 * Callouts from BSD for machine name & model
800 boolean_t
PEGetMachineName( char * name
, int maxLength
)
803 return( gIOPlatform
->getMachineName( name
, maxLength
));
808 boolean_t
PEGetModelName( char * name
, int maxLength
)
811 return( gIOPlatform
->getModelName( name
, maxLength
));
816 int PEGetPlatformEpoch(void)
819 return( gIOPlatform
->getBootROMType());
824 int PEHaltRestart(unsigned int type
)
826 IOPMrootDomain
*pmRootDomain
;
827 AbsoluteTime deadline
;
828 thread_call_t shutdown_hang
;
829 IORegistryEntry
*node
;
831 uint32_t timeout
= 30;
832 static boolean_t panic_begin_called
= FALSE
;
834 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
|| type
== kPEUPSDelayHaltCPU
)
836 pmRootDomain
= IOService::getPMRootDomain();
837 /* Notify IOKit PM clients of shutdown/restart
838 Clients subscribe to this message with a call to
839 IOService::registerInterest()
842 /* Spawn a thread that will panic in 30 seconds.
843 If all goes well the machine will be off by the time
844 the timer expires. If the device wants a different
845 timeout, use that value instead of 30 seconds.
848 #define RESTART_NODE_PATH "/defaults"
850 #define RESTART_NODE_PATH "/chosen"
852 node
= IORegistryEntry::fromPath( RESTART_NODE_PATH
, gIODTPlane
);
854 data
= OSDynamicCast( OSData
, node
->getProperty( "halt-restart-timeout" ) );
855 if ( data
&& data
->getLength() == 4 )
856 timeout
= *((uint32_t *) data
->getBytesNoCopy());
859 shutdown_hang
= thread_call_allocate( &IOShutdownNotificationsTimedOut
,
860 (thread_call_param_t
)(uintptr_t) type
);
861 clock_interval_to_deadline( timeout
, kSecondScale
, &deadline
);
862 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
864 pmRootDomain
->handlePlatformHaltRestart(type
);
865 /* This notification should have few clients who all do
866 their work synchronously.
868 In this "shutdown notification" context we don't give
869 drivers the option of working asynchronously and responding
870 later. PM internals make it very hard to wait for asynchronous
874 else if(type
== kPEPanicRestartCPU
|| type
== kPEPanicSync
)
876 if (type
== kPEPanicRestartCPU
) {
877 // Notify any listeners that we're done collecting
878 // panic data before we call through to do the restart
879 IOCPURunPlatformPanicActions(kPEPanicEnd
);
882 // Do an initial sync to flush as much panic data as possible,
883 // in case we have a problem in one of the platorm panic handlers.
884 // After running the platform handlers, do a final sync w/
885 // platform hardware quiesced for the panic.
886 PE_sync_panic_buffers();
887 IOCPURunPlatformPanicActions(type
);
888 PE_sync_panic_buffers();
890 else if (type
== kPEPanicEnd
) {
891 IOCPURunPlatformPanicActions(type
);
892 } else if (type
== kPEPanicBegin
) {
893 // Only call the kPEPanicBegin callout once
894 if (!panic_begin_called
) {
895 panic_begin_called
= TRUE
;
896 IOCPURunPlatformPanicActions(type
);
900 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
904 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
906 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
910 void PESavePanicInfoAction(void *buffer
, size_t length
)
912 IOCPURunPlatformPanicSyncAction(buffer
, length
);
917 inline static int init_gIOOptionsEntry(void)
919 IORegistryEntry
*entry
;
921 volatile void **options
;
927 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
931 nvram_entry
= (void *) OSDynamicCast(IODTNVRAM
, entry
);
935 options
= (volatile void **) &gIOOptionsEntry
;
936 if (!OSCompareAndSwapPtr(NULL
, nvram_entry
, options
)) {
949 /* pass in a NULL value if you just want to figure out the len */
950 boolean_t
PEReadNVRAMProperty(const char *symbol
, void *value
,
960 if (init_gIOOptionsEntry() < 0)
966 obj
= gIOOptionsEntry
->getProperty(symbol
);
970 /* convert to data */
971 data
= OSDynamicCast(OSData
, obj
);
975 *len
= data
->getLength();
976 vlen
= min(vlen
, *len
);
978 memcpy((void *) value
, data
->getBytesNoCopy(), vlen
);
987 PEWriteNVRAMBooleanProperty(const char *symbol
, boolean_t value
)
989 const OSSymbol
*sym
= NULL
;
990 OSBoolean
*data
= NULL
;
993 if (symbol
== NULL
) {
997 if (init_gIOOptionsEntry() < 0) {
1001 if ((sym
= OSSymbol::withCStringNoCopy(symbol
)) == NULL
) {
1005 data
= value
? kOSBooleanTrue
: kOSBooleanFalse
;
1006 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1010 /* success, force the NVRAM to flush writes */
1012 gIOOptionsEntry
->sync();
1019 boolean_t
PEWriteNVRAMProperty(const char *symbol
, const void *value
,
1020 const unsigned int len
)
1022 const OSSymbol
*sym
;
1026 if (!symbol
|| !value
|| !len
)
1029 if (init_gIOOptionsEntry() < 0)
1032 sym
= OSSymbol::withCStringNoCopy(symbol
);
1036 data
= OSData::withBytes((void *) value
, len
);
1040 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1047 gIOOptionsEntry
->sync();
1056 boolean_t
PERemoveNVRAMProperty(const char *symbol
)
1058 const OSSymbol
*sym
;
1063 if (init_gIOOptionsEntry() < 0)
1066 sym
= OSSymbol::withCStringNoCopy(symbol
);
1070 gIOOptionsEntry
->removeProperty(sym
);
1074 gIOOptionsEntry
->sync();
1082 long PEGetGMTTimeOfDay(void)
1087 PEGetUTCTimeOfDay(&secs
, &usecs
);
1091 void PESetGMTTimeOfDay(long secs
)
1093 PESetUTCTimeOfDay(secs
, 0);
1096 void PEGetUTCTimeOfDay(clock_sec_t
* secs
, clock_usec_t
* usecs
)
1098 clock_nsec_t nsecs
= 0;
1102 gIOPlatform
->getUTCTimeOfDay(secs
, &nsecs
);
1104 assert(nsecs
< NSEC_PER_SEC
);
1105 *usecs
= nsecs
/ NSEC_PER_USEC
;
1108 void PESetUTCTimeOfDay(clock_sec_t secs
, clock_usec_t usecs
)
1110 assert(usecs
< USEC_PER_SEC
);
1112 gIOPlatform
->setUTCTimeOfDay(secs
, usecs
* NSEC_PER_USEC
);
1117 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
1120 IORegistryEntry
* entry
;
1121 OSString
* string
= 0;
1125 entry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
1130 data1
= OSDynamicCast( OSData
, entry
->getProperty( "unique-chip-id" ) );
1131 if ( data1
&& data1
->getLength( ) == 8 )
1135 data2
= OSDynamicCast( OSData
, entry
->getProperty( "chip-id" ) );
1136 if ( data2
&& data2
->getLength( ) == 4 )
1139 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1140 const uuid_t space
= { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
1142 SHA1Init( &context
);
1143 SHA1Update( &context
, space
, sizeof( space
) );
1144 SHA1Update( &context
, data1
->getBytesNoCopy( ), data1
->getLength( ) );
1145 SHA1Update( &context
, data2
->getBytesNoCopy( ), data2
->getLength( ) );
1146 SHA1Final( digest
, &context
);
1148 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1149 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1151 uuid_unparse( digest
, uuid
);
1152 string
= OSString::withCString( uuid
);
1158 #else /* !CONFIG_EMBEDDED */
1159 entry
= IORegistryEntry::fromPath( "/efi/platform", gIODTPlane
);
1162 data
= OSDynamicCast( OSData
, entry
->getProperty( "system-id" ) );
1163 if ( data
&& data
->getLength( ) == 16 )
1166 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1167 const uuid_t space
= { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
1169 SHA1Init( &context
);
1170 SHA1Update( &context
, space
, sizeof( space
) );
1171 SHA1Update( &context
, data
->getBytesNoCopy( ), data
->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
);
1183 #endif /* !CONFIG_EMBEDDED */
1187 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1190 data
= OSDynamicCast( OSData
, entry
->getProperty( "platform-uuid" ) );
1191 if ( data
&& data
->getLength( ) == sizeof( uuid_t
) )
1193 uuid_unparse( ( uint8_t * ) data
->getBytesNoCopy( ), uuid
);
1194 string
= OSString::withCString( uuid
);
1203 getProvider( )->setProperty( kIOPlatformUUIDKey
, string
);
1204 publishResource( kIOPlatformUUIDKey
, string
);
1209 publishResource("IONVRAM");
1212 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
1213 bool waitForFunction
,
1214 void *param1
, void *param2
,
1215 void *param3
, void *param4
)
1217 IOService
*service
, *_resources
;
1219 if (waitForFunction
) {
1220 _resources
= waitForService(resourceMatching(functionName
));
1222 _resources
= getResourceService();
1224 if (_resources
== 0) return kIOReturnUnsupported
;
1226 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
1227 if (service
== 0) return kIOReturnUnsupported
;
1229 return service
->callPlatformFunction(functionName
, waitForFunction
,
1230 param1
, param2
, param3
, param4
);
1233 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1238 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1241 #define super IOPlatformExpert
1243 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
1245 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
1246 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
1247 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
1248 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
1249 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
1250 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
1251 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
1252 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
1254 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1256 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
1259 if( !super::probe( provider
, score
))
1262 // check machine types
1263 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
1269 bool IODTPlatformExpert::configure( IOService
* provider
)
1271 if( !super::configure( provider
))
1274 processTopLevel( provider
);
1279 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
1283 nub
= new IOPlatformDevice
;
1285 if( !nub
->init( from
, gIODTPlane
)) {
1293 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
1295 IORegistryEntry
* next
;
1300 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
1302 if( 0 == (nub
= createNub( next
)))
1305 nub
->attach( parent
);
1306 nub
->registerService();
1314 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
1317 IORegistryEntry
* next
;
1318 IORegistryEntry
* cpus
;
1319 IORegistryEntry
* options
;
1322 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
1324 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
1325 next
->detachAll( gIODTPlane
);
1330 // Publish an IODTNVRAM class on /options.
1331 options
= rootEntry
->childFromPath("options", gIODTPlane
);
1333 dtNVRAM
= new IODTNVRAM
;
1335 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
1339 dtNVRAM
->attach(this);
1340 dtNVRAM
->registerService();
1346 // Publish the cpus.
1347 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
1350 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
1354 // publish top level, minus excludeList
1355 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
1358 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
1360 if( nub
->getDeviceMemory())
1361 return( kIOReturnSuccess
);
1363 IODTResolveAddressing( nub
, "reg", 0);
1365 return( kIOReturnSuccess
);
1368 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
1369 OSString
* name
, OSString
** matched
) const
1371 return( IODTCompareNubName( nub
, name
, matched
)
1372 || super::compareNubName( nub
, name
, matched
) );
1375 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1385 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1387 str
= (const char *) prop
->getBytesNoCopy();
1389 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1390 str
+= strlen( "AAPL," );
1393 while( (c
= *str
++)) {
1394 if( (c
== '/') || (c
== ' '))
1398 if( len
>= maxLength
)
1408 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1414 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1418 strlcpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1423 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1425 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1427 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1429 super::registerNVRAMController(nvram
);
1432 int IODTPlatformExpert::haltRestart(unsigned int type
)
1434 if (dtNVRAM
) dtNVRAM
->sync();
1436 return super::haltRestart(type
);
1439 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1442 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1443 else return kIOReturnNotReady
;
1446 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1449 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1450 else return kIOReturnNotReady
;
1453 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1454 IORegistryEntry
* entry
,
1455 const OSSymbol
** name
, OSData
** value
)
1457 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1458 else return kIOReturnNotReady
;
1461 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1462 IORegistryEntry
* entry
,
1463 const OSSymbol
* name
, OSData
* value
)
1465 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1466 else return kIOReturnNotReady
;
1469 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1471 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1475 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1476 IOByteCount offset
, UInt8
* buffer
,
1479 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1481 else return kIOReturnNotReady
;
1484 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1485 IOByteCount offset
, UInt8
* buffer
,
1488 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1490 else return kIOReturnNotReady
;
1493 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1495 IOByteCount lengthSaved
= 0;
1497 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1499 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1504 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1505 UInt8
* serialNumber
;
1506 unsigned int serialNumberSize
;
1507 unsigned short pos
= 0;
1511 if (myProperty
!= NULL
) {
1512 serialNumberSize
= myProperty
->getLength();
1513 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1514 temp
= (char*)serialNumber
;
1515 if (serialNumberSize
> 0) {
1516 // check to see if this is a CTO serial number...
1517 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1519 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1520 memcpy(SerialNo
, serialNumber
+ 12, 8);
1521 memcpy(&SerialNo
[8], serialNumber
, 3);
1523 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1525 } else { // just a normal serial number
1526 memcpy(SerialNo
, serialNumber
+ 13, 8);
1527 memcpy(&SerialNo
[8], serialNumber
, 3);
1530 return OSString::withCString(SerialNo
);
1537 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1540 #define super IOService
1542 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1544 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1545 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1546 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1547 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1549 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1551 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1552 OSString
** matched
) const
1554 return( IODTCompareNubName( this, name
, matched
));
1558 IOPlatformExpertDevice::initWithArgs(
1559 void * dtTop
, void * p2
, void * p3
, void * p4
)
1561 IORegistryEntry
* dt
= 0;
1564 // dtTop may be zero on non- device tree systems
1565 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1566 ok
= super::init( dt
, gIODTPlane
);
1574 workLoop
= IOWorkLoop::workLoop();
1581 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1586 IOReturn
IOPlatformExpertDevice::setProperties( OSObject
* properties
)
1588 OSDictionary
* dictionary
;
1592 status
= super::setProperties( properties
);
1593 if ( status
!= kIOReturnUnsupported
) return status
;
1595 status
= IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator
);
1596 if ( status
!= kIOReturnSuccess
) return status
;
1598 dictionary
= OSDynamicCast( OSDictionary
, properties
);
1599 if ( dictionary
== 0 ) return kIOReturnBadArgument
;
1601 object
= dictionary
->getObject( kIOPlatformUUIDKey
);
1604 IORegistryEntry
* entry
;
1608 string
= ( OSString
* ) getProperty( kIOPlatformUUIDKey
);
1609 if ( string
) return kIOReturnNotPermitted
;
1611 string
= OSDynamicCast( OSString
, object
);
1612 if ( string
== 0 ) return kIOReturnBadArgument
;
1614 status
= uuid_parse( string
->getCStringNoCopy( ), uuid
);
1615 if ( status
!= 0 ) return kIOReturnBadArgument
;
1617 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1620 entry
->setProperty( "platform-uuid", uuid
, sizeof( uuid_t
) );
1624 setProperty( kIOPlatformUUIDKey
, string
);
1625 publishResource( kIOPlatformUUIDKey
, string
);
1627 return kIOReturnSuccess
;
1630 return kIOReturnUnsupported
;
1633 IOReturn
IOPlatformExpertDevice::newUserClient( task_t owningTask
, void * securityID
,
1634 UInt32 type
, OSDictionary
* properties
,
1635 IOUserClient
** handler
)
1637 IOReturn err
= kIOReturnSuccess
;
1638 IOUserClient
* newConnect
= 0;
1639 IOUserClient
* theConnect
= 0;
1643 case kIOKitDiagnosticsClientType
:
1644 newConnect
= IOKitDiagnosticsClient::withTask(owningTask
);
1645 if (!newConnect
) err
= kIOReturnNotPermitted
;
1648 err
= kIOReturnBadArgument
;
1653 if ((false == newConnect
->attach(this))
1654 || (false == newConnect
->start(this)))
1656 newConnect
->detach( this );
1657 newConnect
->release();
1658 err
= kIOReturnNotPermitted
;
1661 theConnect
= newConnect
;
1664 *handler
= theConnect
;
1668 void IOPlatformExpertDevice::free()
1671 workLoop
->release();
1674 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1677 #define super IOService
1679 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1681 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1682 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1683 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1684 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1686 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1688 bool IOPlatformDevice::compareName( OSString
* name
,
1689 OSString
** matched
) const
1691 return( ((IOPlatformExpert
*)getProvider())->
1692 compareNubName( this, name
, matched
));
1695 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1700 IOReturn
IOPlatformDevice::getResources( void )
1702 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1705 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1707 /*********************************************************************
1708 * IOPanicPlatform class
1710 * If no legitimate IOPlatformDevice matches, this one does and panics
1711 * the kernel with a suitable message.
1712 *********************************************************************/
1714 class IOPanicPlatform
: IOPlatformExpert
{
1715 OSDeclareDefaultStructors(IOPanicPlatform
);
1718 bool start(IOService
* provider
) APPLE_KEXT_OVERRIDE
;
1722 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1725 bool IOPanicPlatform::start(IOService
* provider
) {
1726 const char * platform_name
= "(unknown platform name)";
1728 if (provider
) platform_name
= provider
->getName();
1730 panic("Unable to find driver for this platform: \"%s\".\n",