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>
43 #include <IOKit/IOUserServer.h>
45 #include <IOKit/system.h>
48 #include <libkern/c++/OSContainers.h>
49 #include <libkern/crypto/sha1.h>
50 #include <libkern/OSAtomic.h>
53 #include <machine/machine_routines.h>
54 #include <pexpert/pexpert.h>
55 #include <uuid/uuid.h>
58 #define kShutdownTimeout 30 //in secs
60 #if defined(XNU_TARGET_OS_OSX)
62 boolean_t coprocessor_cross_panic_enabled
= TRUE
;
63 #define APPLE_VENDOR_VARIABLE_GUID "4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14"
64 #endif /* defined(XNU_TARGET_OS_OSX) */
66 void printDictionaryKeys(OSDictionary
* inDictionary
, char * inMsg
);
67 static void getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
);
70 * There are drivers which take mutexes in the quiesce callout or pass
71 * the quiesce/active action to super. Even though it sometimes panics,
72 * because it doesn't *always* panic, they get away with it.
73 * We need a chicken bit to diagnose and fix them all before this
74 * can be enabled by default.
76 * <rdar://problem/33831837> tracks turning this on by default.
78 uint32_t gEnforceQuiesceSafety
= 0;
80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
82 #define super IOService
84 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
86 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
87 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
88 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 2);
89 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 3);
90 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 4);
92 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
93 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
94 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
95 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
96 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
97 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
98 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
100 static IOPlatformExpert
* gIOPlatform
;
101 static OSDictionary
* gIOInterruptControllers
;
102 static IOLock
* gIOInterruptControllersLock
;
103 static IODTNVRAM
*gIOOptionsEntry
;
105 OSSymbol
* gPlatformInterruptControllerName
;
107 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
110 IOPlatformExpert::attach( IOService
* provider
)
112 if (!super::attach( provider
)) {
120 IOPlatformExpert::start( IOService
* provider
)
122 IORangeAllocator
* physicalRanges
;
123 OSData
* busFrequency
;
127 if (!super::start(provider
)) {
131 // Override the mapper present flag is requested by boot arguments, if SIP disabled.
133 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS
) == 0)
134 #endif /* CONFIG_CSR */
136 if (PE_parse_boot_argn("dart", &debugFlags
, sizeof(debugFlags
)) && (debugFlags
== 0)) {
137 removeProperty(kIOPlatformMapperPresentKey
);
139 #if DEBUG || DEVELOPMENT
140 if (PE_parse_boot_argn("-x", &debugFlags
, sizeof(debugFlags
))) {
141 removeProperty(kIOPlatformMapperPresentKey
);
143 #endif /* DEBUG || DEVELOPMENT */
146 // Register the presence or lack thereof a system
147 // PCI address mapper with the IOMapper class
148 IOMapper::setMapperRequired(NULL
!= getProperty(kIOPlatformMapperPresentKey
));
150 gIOInterruptControllers
= OSDictionary::withCapacity(1);
151 gIOInterruptControllersLock
= IOLockAlloc();
153 // Correct the bus frequency in the device tree.
154 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
155 provider
->setProperty("clock-frequency", busFrequency
);
156 busFrequency
->release();
158 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
160 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
161 IORangeAllocator::kLocking
);
162 assert(physicalRanges
);
163 setProperty("Platform Memory Ranges", physicalRanges
);
168 PMInstantiatePowerDomains();
170 // Parse the serial-number data and publish a user-readable string
171 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
172 if (mydata
!= NULL
) {
173 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
174 if (serNoString
!= NULL
) {
175 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
176 serNoString
->release();
181 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2
) {
182 coprocessor_paniclog_flush
= TRUE
;
183 extended_debug_log_init();
187 PE_parse_boot_argn("enforce_quiesce_safety", &gEnforceQuiesceSafety
,
188 sizeof(gEnforceQuiesceSafety
));
190 return configure(provider
);
194 IOPlatformExpert::configure( IOService
* provider
)
200 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
203 while ((dict
= OSDynamicCast( OSDictionary
,
204 topLevel
->getAnyObject()))) {
206 topLevel
->removeObject( dict
);
207 nub
= createNub( dict
);
213 nub
->registerService();
221 IOPlatformExpert::createNub( OSDictionary
* from
)
225 nub
= new IOPlatformDevice
;
227 if (!nub
->init( from
)) {
236 IOPlatformExpert::compareNubName( const IOService
* nub
,
237 OSString
* name
, OSString
** matched
) const
239 return nub
->IORegistryEntry::compareName( name
, matched
);
243 IOPlatformExpert::getNubResources( IOService
* nub
)
245 return kIOReturnSuccess
;
249 IOPlatformExpert::getBootROMType(void)
251 return _peBootROMType
;
255 IOPlatformExpert::getChipSetType(void)
257 return _peChipSetType
;
261 IOPlatformExpert::getMachineType(void)
263 return _peMachineType
;
267 IOPlatformExpert::setBootROMType(long peBootROMType
)
269 _peBootROMType
= peBootROMType
;
273 IOPlatformExpert::setChipSetType(long peChipSetType
)
275 _peChipSetType
= peChipSetType
;
279 IOPlatformExpert::setMachineType(long peMachineType
)
281 _peMachineType
= peMachineType
;
285 IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
291 IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
297 IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
303 IOPlatformExpert::getPhysicalRangeAllocator(void)
305 return OSDynamicCast(IORangeAllocator
,
306 getProperty("Platform Memory Ranges"));
309 int (*PE_halt_restart
)(unsigned int type
) = NULL
;
312 IOPlatformExpert::haltRestart(unsigned int type
)
314 if (type
== kPEPanicSync
) {
318 if (type
== kPEHangCPU
) {
323 if (type
== kPEUPSDelayHaltCPU
) {
324 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
329 // On ARM kPEPanicRestartCPU is supported in the drivers
330 if (type
== kPEPanicRestartCPU
) {
331 type
= kPERestartCPU
;
335 if (PE_halt_restart
) {
336 return (*PE_halt_restart
)(type
);
343 IOPlatformExpert::sleepKernel(void)
349 intState
= ml_set_interrupts_enabled(false);
351 for (cnt
= 0; cnt
< 10000; cnt
++) {
355 ml_set_interrupts_enabled(intState
);
357 // PE_initialize_console(0, kPEDisableScreen);
361 // PE_initialize_console(0, kPEEnableScreen);
366 IOPlatformExpert::getGMTTimeOfDay(void)
372 IOPlatformExpert::setGMTTimeOfDay(long secs
)
378 IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
380 return PE_current_console( consoleInfo
);
384 IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
387 return PE_initialize_console( consoleInfo
, op
);
391 IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
393 IOLockLock(gIOInterruptControllersLock
);
395 gIOInterruptControllers
->setObject(name
, interruptController
);
397 IOLockWakeup(gIOInterruptControllersLock
,
398 gIOInterruptControllers
, /* one-thread */ false);
400 IOLockUnlock(gIOInterruptControllersLock
);
402 return kIOReturnSuccess
;
406 IOPlatformExpert::deregisterInterruptController(OSSymbol
*name
)
408 IOLockLock(gIOInterruptControllersLock
);
410 gIOInterruptControllers
->removeObject(name
);
412 IOLockUnlock(gIOInterruptControllersLock
);
414 return kIOReturnSuccess
;
417 IOInterruptController
*
418 IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
422 IOLockLock(gIOInterruptControllersLock
);
424 object
= gIOInterruptControllers
->getObject(name
);
426 if (object
!= NULL
) {
430 IOLockSleep(gIOInterruptControllersLock
,
431 gIOInterruptControllers
, THREAD_UNINT
);
434 IOLockUnlock(gIOInterruptControllersLock
);
435 return OSDynamicCast(IOInterruptController
, object
);
440 IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
442 IOCPUInterruptController
*controller
;
444 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
446 controller
->setCPUInterruptProperties(service
);
451 IOPlatformExpert::atInterruptLevel(void)
453 return ml_at_interrupt_context();
457 IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
463 IOPlatformExpert::getUTCTimeOfDay(clock_sec_t
* secs
, clock_nsec_t
* nsecs
)
465 *secs
= getGMTTimeOfDay();
470 IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs
, __unused clock_nsec_t nsecs
)
472 setGMTTimeOfDay(secs
);
476 //*********************************************************************************
479 //*********************************************************************************
483 PMLog(const char *who
, unsigned long event
,
484 unsigned long param1
, unsigned long param2
)
488 clock_get_system_microtime(&nows
, &nowus
);
489 nowus
+= (nows
% 1000) * 1000000;
491 kprintf("pm%u %p %.30s %d %lx %lx\n",
492 nowus
, OBFUSCATE(current_thread()), who
, // Identity
493 (int) event
, (long)OBFUSCATE(param1
), (long)OBFUSCATE(param2
)); // Args
497 //*********************************************************************************
498 // PMInstantiatePowerDomains
500 // In this vanilla implementation, a Root Power Domain is instantiated.
501 // All other objects which register will be children of this Root.
502 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
503 // in a platform-specific subclass.
504 //*********************************************************************************
507 IOPlatformExpert::PMInstantiatePowerDomains( void )
509 root
= new IOPMrootDomain
;
516 //*********************************************************************************
519 // In this vanilla implementation, all callers are made children of the root power domain.
520 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
521 //*********************************************************************************
524 IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
526 root
->addPowerChild( theDevice
);
529 //*********************************************************************************
532 //*********************************************************************************
535 IOPlatformExpert::hasPMFeature(unsigned long featureMask
)
537 return (_pePMFeatures
& featureMask
) != 0;
540 //*********************************************************************************
543 //*********************************************************************************
546 IOPlatformExpert::hasPrivPMFeature(unsigned long privFeatureMask
)
548 return (_pePrivPMFeatures
& privFeatureMask
) != 0;
551 //*********************************************************************************
552 // numBatteriesSupported
554 //*********************************************************************************
557 IOPlatformExpert::numBatteriesSupported(void)
559 return _peNumBatteriesSupported
;
562 //*********************************************************************************
565 // This method is called by the instantiated sublass of the platform expert to
566 // determine how a device should be inserted into the Power Domain. The subclass
567 // provides an XML power tree description against which a device is matched based
568 // on class and provider. If a match is found this routine returns true in addition
569 // to flagging the description tree at the appropriate node that a device has been
570 // registered for the given service.
571 //*********************************************************************************
574 IOPlatformExpert::CheckSubTree(OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
577 unsigned int numPowerTreeNodes
;
578 OSDictionary
* entry
;
579 OSDictionary
* matchingDictionary
;
580 OSDictionary
* providerDictionary
;
581 OSDictionary
* deviceDictionary
;
582 OSDictionary
* nubDictionary
;
584 bool nodeFound
= false;
585 bool continueSearch
= false;
586 bool deviceMatch
= false;
587 bool providerMatch
= false;
588 bool multiParentMatch
= false;
590 if ((NULL
== theDevice
) || (NULL
== inSubTree
)) {
594 numPowerTreeNodes
= inSubTree
->getCount();
596 // iterate through the power tree to find a home for this device
598 for (i
= 0; i
< numPowerTreeNodes
; i
++) {
599 entry
= (OSDictionary
*) inSubTree
->getObject(i
);
601 matchingDictionary
= (OSDictionary
*) entry
->getObject("device");
602 providerDictionary
= (OSDictionary
*) entry
->getObject("provider");
604 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
605 if (matchingDictionary
) {
607 if (NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties())) {
608 deviceMatch
= deviceDictionary
->isEqualTo( matchingDictionary
, matchingDictionary
);
609 deviceDictionary
->release();
613 providerMatch
= true; // we indicate a match if there is no nub or provider
614 if (theNub
&& providerDictionary
) {
615 providerMatch
= false;
616 if (NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties())) {
617 providerMatch
= nubDictionary
->isEqualTo( providerDictionary
, providerDictionary
);
618 nubDictionary
->release();
622 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
623 if (deviceMatch
&& providerMatch
) {
624 if (NULL
!= multipleParentKeyValue
) {
625 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject("multiple-parent");
626 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo(aNumber
) : false;
630 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
632 // if the power tree specifies a provider dictionary but theNub is
633 // NULL then we cannot match with this entry.
635 if (theNub
== NULL
&& providerDictionary
!= NULL
) {
639 // if this node is THE ONE...then register the device
642 if (RegisterServiceInTree(theDevice
, entry
, theParent
, theNub
)) {
643 if (kIOLogPower
& gIOKitDebug
) {
644 IOLog("PMRegisterDevice/CheckSubTree - service registered!\n");
647 numInstancesRegistered
++;
649 // determine if we need to search for additional nodes for this item
650 multipleParentKeyValue
= (OSNumber
*) entry
->getObject("multiple-parent");
656 continueSearch
= ((false == nodeFound
) || (NULL
!= multipleParentKeyValue
));
658 if (continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject("children")))) {
659 nodeFound
= CheckSubTree( children
, theNub
, theDevice
, entry
);
660 continueSearch
= ((false == nodeFound
) || (NULL
!= multipleParentKeyValue
));
663 if (false == continueSearch
) {
671 //*********************************************************************************
672 // RegisterServiceInTree
674 // Register a device at the specified node of our power tree.
675 //*********************************************************************************
678 IOPlatformExpert::RegisterServiceInTree(IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
680 IOService
* aService
;
681 bool registered
= false;
683 unsigned int numChildren
;
684 OSDictionary
* child
;
686 // make sure someone is not already registered here
688 if (NULL
== theTreeNode
->getObject("service")) {
689 if (theTreeNode
->setObject("service", OSDynamicCast( OSObject
, theService
))) {
690 // 1. CHILDREN ------------------
692 // we registered the node in the tree...now if the node has children
693 // registered we must tell this service to add them.
695 if (NULL
!= (children
= (OSArray
*) theTreeNode
->getObject("children"))) {
696 numChildren
= children
->getCount();
697 for (unsigned int i
= 0; i
< numChildren
; i
++) {
698 if (NULL
!= (child
= (OSDictionary
*) children
->getObject(i
))) {
699 if (NULL
!= (aService
= (IOService
*) child
->getObject("service"))) {
700 theService
->addPowerChild(aService
);
706 // 2. PARENT --------------------
708 // also we must notify the parent of this node (if a registered service
709 // exists there) of a new child.
711 if (theTreeParentNode
) {
712 if (NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject("service"))) {
713 if (aService
!= theProvider
) {
714 aService
->addPowerChild(theService
);
726 //*********************************************************************************
727 // printDictionaryKeys
729 // Print the keys for the given dictionary and selected contents.
730 //*********************************************************************************
732 printDictionaryKeys(OSDictionary
* inDictionary
, char * inMsg
)
734 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection(inDictionary
);
741 mkey
= OSDynamicCast(OSSymbol
, mcoll
->getNextObject());
744 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
746 // if this is the IOClass key, print it's contents
748 if (mkey
->isEqualTo("IOClass")) {
749 ioClass
= (OSString
*) inDictionary
->getObject("IOClass");
751 IOLog("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy());
755 // if this is an IOProviderClass key print it
757 if (mkey
->isEqualTo("IOProviderClass")) {
758 ioClass
= (OSString
*) inDictionary
->getObject("IOProviderClass");
760 IOLog("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy());
764 // also print IONameMatch keys
765 if (mkey
->isEqualTo("IONameMatch")) {
766 ioClass
= (OSString
*) inDictionary
->getObject("IONameMatch");
768 IOLog("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy());
772 // also print IONameMatched keys
774 if (mkey
->isEqualTo("IONameMatched")) {
775 ioClass
= (OSString
*) inDictionary
->getObject("IONameMatched");
777 IOLog("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy());
784 if (mkey
->isEqualTo("AAPL,clock-id")) {
786 cstr
= getCStringForObject(inDictionary
->getObject("AAPL,clock-id"));
788 kprintf(" ===> AAPL,clock-id is %s\n", cstr
);
795 if (mkey
->isEqualTo("name")) {
798 getCStringForObject(inDictionary
->getObject("name"), nameStr
,
800 if (strlen(nameStr
) > 0) {
801 IOLog("%s name is %s\n", inMsg
, nameStr
);
805 mkey
= (OSSymbol
*) mcoll
->getNextObject();
814 getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
)
819 if ((NULL
== inObj
) || (NULL
== outStr
)) {
823 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
825 if ((0 == strncmp(objString
, "OSString", sizeof("OSString"))) ||
826 (0 == strncmp(objString
, "OSSymbol", sizeof("OSSymbol")))) {
827 strlcpy(outStr
, ((OSString
*)inObj
)->getCStringNoCopy(), outStrLen
);
828 } else if (0 == strncmp(objString
, "OSData", sizeof("OSData"))) {
829 len
= ((OSData
*)inObj
)->getLength();
830 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
831 if (buffer
&& (len
> 0)) {
832 for (i
= 0; i
< len
; i
++) {
833 outStr
[i
] = buffer
[i
];
840 /* IOShutdownNotificationsTimedOut
841 * - Called from a timer installed by PEHaltRestart
843 #ifdef CONFIG_EMBEDDED
847 IOShutdownNotificationsTimedOut(
848 thread_call_param_t p0
,
849 thread_call_param_t p1
)
851 #ifdef CONFIG_EMBEDDED
852 /* 30 seconds has elapsed - panic */
853 panic("Halt/Restart Timed Out");
855 #else /* ! CONFIG_EMBEDDED */
856 int type
= (int)(long)p0
;
857 uint32_t timeout
= (uint32_t)(uintptr_t)p1
;
859 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
861 if ((PEGetCoprocessorVersion() >= kCoprocessorVersion2
) || pmRootDomain
->checkShutdownTimeout()) {
862 pmRootDomain
->panicWithShutdownLog(timeout
* 1000);
866 /* 30 seconds has elapsed - resume shutdown */
868 gIOPlatform
->haltRestart(type
);
870 #endif /* CONFIG_EMBEDDED */
876 * Callouts from BSD for machine name & model
880 PEGetMachineName( char * name
, int maxLength
)
883 return gIOPlatform
->getMachineName( name
, maxLength
);
890 PEGetModelName( char * name
, int maxLength
)
893 return gIOPlatform
->getModelName( name
, maxLength
);
900 PEGetPlatformEpoch(void)
903 return gIOPlatform
->getBootROMType();
910 PEHaltRestart(unsigned int type
)
912 IOPMrootDomain
*pmRootDomain
;
913 AbsoluteTime deadline
;
914 thread_call_t shutdown_hang
;
915 IORegistryEntry
*node
;
917 uint32_t timeout
= kShutdownTimeout
;
918 static boolean_t panic_begin_called
= FALSE
;
920 if (type
== kPEHaltCPU
|| type
== kPERestartCPU
|| type
== kPEUPSDelayHaltCPU
) {
921 /* If we're in the panic path, the locks and memory allocations required below
922 * could fail. So just try to reboot instead of risking a nested panic.
924 if (panic_begin_called
) {
925 goto skip_to_haltRestart
;
928 pmRootDomain
= IOService::getPMRootDomain();
929 /* Notify IOKit PM clients of shutdown/restart
930 * Clients subscribe to this message with a call to
931 * IOService::registerInterest()
934 /* Spawn a thread that will panic in 30 seconds.
935 * If all goes well the machine will be off by the time
936 * the timer expires. If the device wants a different
937 * timeout, use that value instead of 30 seconds.
940 #define RESTART_NODE_PATH "/defaults"
942 #define RESTART_NODE_PATH "/chosen"
944 node
= IORegistryEntry::fromPath( RESTART_NODE_PATH
, gIODTPlane
);
946 data
= OSDynamicCast( OSData
, node
->getProperty( "halt-restart-timeout" ));
947 if (data
&& data
->getLength() == 4) {
948 timeout
= *((uint32_t *) data
->getBytesNoCopy());
952 #if (DEVELOPMENT || DEBUG)
953 /* Override the default timeout via a boot-arg */
954 uint32_t boot_arg_val
;
955 if (PE_parse_boot_argn("halt_restart_timeout", &boot_arg_val
, sizeof(boot_arg_val
))) {
956 timeout
= boot_arg_val
;
961 shutdown_hang
= thread_call_allocate( &IOShutdownNotificationsTimedOut
,
962 (thread_call_param_t
)(uintptr_t) type
);
963 clock_interval_to_deadline( timeout
, kSecondScale
, &deadline
);
964 thread_call_enter1_delayed( shutdown_hang
, (thread_call_param_t
)(uintptr_t)timeout
, deadline
);
967 pmRootDomain
->handlePlatformHaltRestart(type
);
968 /* This notification should have few clients who all do
969 * their work synchronously.
971 * In this "shutdown notification" context we don't give
972 * drivers the option of working asynchronously and responding
973 * later. PM internals make it very hard to wait for asynchronous
976 } else if (type
== kPEPanicRestartCPU
|| type
== kPEPanicSync
|| type
== kPEPanicRestartCPUNoPanicEndCallouts
||
977 type
== kPEPanicRestartCPUNoCallouts
) {
978 if (type
== kPEPanicRestartCPU
) {
979 // Notify any listeners that we're done collecting
980 // panic data before we call through to do the restart
982 if (coprocessor_cross_panic_enabled
)
984 IOCPURunPlatformPanicActions(kPEPanicEnd
);
987 if ((type
== kPEPanicRestartCPU
) || (type
== kPEPanicRestartCPUNoPanicEndCallouts
)) {
988 // Callout to shutdown the disk driver once we've returned from the
989 // kPEPanicEnd callbacks (if appropriate) and we know all coredumps
990 // on this system are complete).
991 IOCPURunPlatformPanicActions(kPEPanicDiskShutdown
);
994 if (type
== kPEPanicRestartCPUNoPanicEndCallouts
|| type
== kPEPanicRestartCPUNoCallouts
) {
995 // Replace the wrapper type with the type drivers handle
996 type
= kPEPanicRestartCPU
;
999 // Do an initial sync to flush as much panic data as possible,
1000 // in case we have a problem in one of the platorm panic handlers.
1001 // After running the platform handlers, do a final sync w/
1002 // platform hardware quiesced for the panic.
1003 PE_sync_panic_buffers();
1004 IOCPURunPlatformPanicActions(type
);
1005 PE_sync_panic_buffers();
1006 } else if (type
== kPEPanicEnd
) {
1007 #if !CONFIG_EMBEDDED
1008 if (coprocessor_cross_panic_enabled
)
1010 IOCPURunPlatformPanicActions(type
);
1011 } else if (type
== kPEPanicBegin
) {
1012 #if !CONFIG_EMBEDDED
1013 if (coprocessor_cross_panic_enabled
)
1016 // Only call the kPEPanicBegin callout once
1017 if (!panic_begin_called
) {
1018 panic_begin_called
= TRUE
;
1019 IOCPURunPlatformPanicActions(type
);
1024 skip_to_haltRestart
:
1026 return gIOPlatform
->haltRestart(type
);
1033 PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
1035 if (gIOPlatform
!= NULL
) {
1036 return gIOPlatform
->savePanicInfo(buffer
, length
);
1043 PESavePanicInfoAction(void *buffer
, UInt32 offset
, UInt32 length
)
1045 IOCPURunPlatformPanicSyncAction(buffer
, offset
, length
);
1051 init_gIOOptionsEntry(void)
1053 IORegistryEntry
*entry
;
1055 volatile void **options
;
1058 if (gIOOptionsEntry
) {
1062 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1067 nvram_entry
= (void *) OSDynamicCast(IODTNVRAM
, entry
);
1072 options
= (volatile void **) &gIOOptionsEntry
;
1073 if (!OSCompareAndSwapPtr(NULL
, nvram_entry
, options
)) {
1085 /* pass in a NULL value if you just want to figure out the len */
1087 PEReadNVRAMProperty(const char *symbol
, void *value
,
1094 if (!symbol
|| !len
) {
1098 if (init_gIOOptionsEntry() < 0) {
1105 obj
= gIOOptionsEntry
->getProperty(symbol
);
1110 /* convert to data */
1111 data
= OSDynamicCast(OSData
, obj
);
1116 *len
= data
->getLength();
1117 vlen
= min(vlen
, *len
);
1118 if (value
&& vlen
) {
1119 memcpy((void *) value
, data
->getBytesNoCopy(), vlen
);
1129 PEWriteNVRAMBooleanProperty(const char *symbol
, boolean_t value
)
1131 const OSSymbol
*sym
= NULL
;
1132 OSBoolean
*data
= NULL
;
1135 if (symbol
== NULL
) {
1139 if (init_gIOOptionsEntry() < 0) {
1143 if ((sym
= OSSymbol::withCStringNoCopy(symbol
)) == NULL
) {
1147 data
= value
? kOSBooleanTrue
: kOSBooleanFalse
;
1148 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1152 /* success, force the NVRAM to flush writes */
1154 gIOOptionsEntry
->sync();
1162 PEWriteNVRAMPropertyInternal(const char *symbol
, boolean_t copySymbol
, const void *value
,
1163 const unsigned int len
)
1165 const OSSymbol
*sym
;
1169 if (!symbol
|| !value
|| !len
) {
1173 if (init_gIOOptionsEntry() < 0) {
1177 if (copySymbol
== TRUE
) {
1178 sym
= OSSymbol::withCString(symbol
);
1180 sym
= OSSymbol::withCStringNoCopy(symbol
);
1187 data
= OSData::withBytes((void *) value
, len
);
1192 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1199 gIOOptionsEntry
->sync();
1208 PEWriteNVRAMProperty(const char *symbol
, const void *value
,
1209 const unsigned int len
)
1211 return PEWriteNVRAMPropertyInternal(symbol
, FALSE
, value
, len
);
1215 PEWriteNVRAMPropertyWithCopy(const char *symbol
, const void *value
,
1216 const unsigned int len
)
1218 return PEWriteNVRAMPropertyInternal(symbol
, TRUE
, value
, len
);
1222 PERemoveNVRAMProperty(const char *symbol
)
1224 const OSSymbol
*sym
;
1230 if (init_gIOOptionsEntry() < 0) {
1234 sym
= OSSymbol::withCStringNoCopy(symbol
);
1239 gIOOptionsEntry
->removeProperty(sym
);
1243 gIOOptionsEntry
->sync();
1251 PEGetGMTTimeOfDay(void)
1256 PEGetUTCTimeOfDay(&secs
, &usecs
);
1261 PESetGMTTimeOfDay(long secs
)
1263 PESetUTCTimeOfDay(secs
, 0);
1267 PEGetUTCTimeOfDay(clock_sec_t
* secs
, clock_usec_t
* usecs
)
1269 clock_nsec_t nsecs
= 0;
1273 gIOPlatform
->getUTCTimeOfDay(secs
, &nsecs
);
1276 assert(nsecs
< NSEC_PER_SEC
);
1277 *usecs
= nsecs
/ NSEC_PER_USEC
;
1281 PESetUTCTimeOfDay(clock_sec_t secs
, clock_usec_t usecs
)
1283 assert(usecs
< USEC_PER_SEC
);
1285 gIOPlatform
->setUTCTimeOfDay(secs
, usecs
* NSEC_PER_USEC
);
1290 PEGetCoprocessorVersion( void )
1292 coprocessor_type_t coprocessor_version
= kCoprocessorVersionNone
;
1293 #if !CONFIG_EMBEDDED
1294 IORegistryEntry
*platform_entry
= NULL
;
1295 OSData
*coprocessor_version_obj
= NULL
;
1297 platform_entry
= IORegistryEntry::fromPath(kIODeviceTreePlane
":/efi/platform");
1298 if (platform_entry
!= NULL
) {
1299 coprocessor_version_obj
= OSDynamicCast(OSData
, platform_entry
->getProperty("apple-coprocessor-version"));
1300 if ((coprocessor_version_obj
!= NULL
) && (coprocessor_version_obj
->getLength() <= sizeof(uint64_t))) {
1301 memcpy(&coprocessor_version
, coprocessor_version_obj
->getBytesNoCopy(), coprocessor_version_obj
->getLength());
1303 platform_entry
->release();
1306 return coprocessor_version
;
1311 IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
1314 IORegistryEntry
* entry
;
1315 OSString
* string
= NULL
;
1319 entry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
1323 data1
= OSDynamicCast( OSData
, entry
->getProperty( "unique-chip-id" ));
1324 if (data1
&& data1
->getLength() == 8) {
1327 data2
= OSDynamicCast( OSData
, entry
->getProperty( "chip-id" ));
1328 if (data2
&& data2
->getLength() == 4) {
1330 uint8_t digest
[SHA_DIGEST_LENGTH
];
1331 const uuid_t space
= { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
1333 SHA1Init( &context
);
1334 SHA1Update( &context
, space
, sizeof(space
));
1335 SHA1Update( &context
, data1
->getBytesNoCopy(), data1
->getLength());
1336 SHA1Update( &context
, data2
->getBytesNoCopy(), data2
->getLength());
1337 SHA1Final( digest
, &context
);
1339 digest
[6] = (digest
[6] & 0x0F) | 0x50;
1340 digest
[8] = (digest
[8] & 0x3F) | 0x80;
1342 uuid_unparse( digest
, uuid
);
1343 string
= OSString::withCString( uuid
);
1349 #endif /* CONFIG_EMBEDDED */
1351 #if defined(XNU_TARGET_OS_OSX)
1353 * If we have panic debugging enabled and the bridgeOS panic SoC watchdog is enabled,
1354 * disable cross panics so that the co-processor doesn't cause the system
1355 * to reset when we enter the debugger or hit a panic on the x86 side.
1357 if (panicDebugging
) {
1358 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1360 data
= OSDynamicCast( OSData
, entry
->getProperty( APPLE_VENDOR_VARIABLE_GUID
":BridgeOSPanicWatchdogEnabled" ));
1361 if (data
&& (data
->getLength() == sizeof(UInt8
))) {
1362 UInt8
*panicWatchdogEnabled
= (UInt8
*) data
->getBytesNoCopy();
1363 UInt32 debug_flags
= 0;
1364 if (*panicWatchdogEnabled
|| (PE_i_can_has_debugger(&debug_flags
) &&
1365 (debug_flags
& DB_DISABLE_CROSS_PANIC
))) {
1366 coprocessor_cross_panic_enabled
= FALSE
;
1373 entry
= IORegistryEntry::fromPath( "/efi/platform", gIODTPlane
);
1375 data
= OSDynamicCast( OSData
, entry
->getProperty( "system-id" ));
1376 if (data
&& data
->getLength() == 16) {
1378 uint8_t digest
[SHA_DIGEST_LENGTH
];
1379 const uuid_t space
= { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
1381 SHA1Init( &context
);
1382 SHA1Update( &context
, space
, sizeof(space
));
1383 SHA1Update( &context
, data
->getBytesNoCopy(), data
->getLength());
1384 SHA1Final( digest
, &context
);
1386 digest
[6] = (digest
[6] & 0x0F) | 0x50;
1387 digest
[8] = (digest
[8] & 0x3F) | 0x80;
1389 uuid_unparse( digest
, uuid
);
1390 string
= OSString::withCString( uuid
);
1395 #endif /* defined(XNU_TARGET_OS_OSX) */
1397 if (string
== NULL
) {
1398 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1400 data
= OSDynamicCast( OSData
, entry
->getProperty( "platform-uuid" ));
1401 if (data
&& data
->getLength() == sizeof(uuid_t
)) {
1402 uuid_unparse((uint8_t *) data
->getBytesNoCopy(), uuid
);
1403 string
= OSString::withCString( uuid
);
1411 getProvider()->setProperty( kIOPlatformUUIDKey
, string
);
1412 publishResource( kIOPlatformUUIDKey
, string
);
1417 publishResource("IONVRAM");
1421 IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
1422 bool waitForFunction
,
1423 void *param1
, void *param2
,
1424 void *param3
, void *param4
)
1426 IOService
*service
, *_resources
;
1428 if (functionName
== gIOPlatformQuiesceActionKey
||
1429 functionName
== gIOPlatformActiveActionKey
) {
1431 * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction
1432 * must consume that event themselves, without passing it up to super/IOPlatformExpert.
1434 if (gEnforceQuiesceSafety
) {
1435 panic("Class %s passed the quiesce/active action to IOPlatformExpert",
1436 getMetaClass()->getClassName());
1440 if (waitForFunction
) {
1441 _resources
= waitForService(resourceMatching(functionName
));
1443 _resources
= getResourceService();
1445 if (_resources
== NULL
) {
1446 return kIOReturnUnsupported
;
1449 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
1450 if (service
== NULL
) {
1451 return kIOReturnUnsupported
;
1454 return service
->callPlatformFunction(functionName
, waitForFunction
,
1455 param1
, param2
, param3
, param4
);
1459 IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1464 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1467 #define super IOPlatformExpert
1469 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
1471 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
1472 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
1473 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
1474 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
1475 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
1476 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
1477 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
1478 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
1480 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1483 IODTPlatformExpert::probe( IOService
* provider
,
1486 if (!super::probe( provider
, score
)) {
1490 // check machine types
1491 if (!provider
->compareNames( getProperty( gIONameMatchKey
))) {
1499 IODTPlatformExpert::configure( IOService
* provider
)
1501 if (!super::configure( provider
)) {
1505 processTopLevel( provider
);
1511 IODTPlatformExpert::createNub( IORegistryEntry
* from
)
1515 nub
= new IOPlatformDevice
;
1517 if (!nub
->init( from
, gIODTPlane
)) {
1526 IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
1528 IORegistryEntry
* next
;
1533 while ((next
= (IORegistryEntry
*) iter
->getNextObject())) {
1534 if (NULL
== (nub
= createNub( next
))) {
1538 nub
->attach( parent
);
1539 nub
->registerService();
1548 IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
1551 IORegistryEntry
* next
;
1552 IORegistryEntry
* cpus
;
1553 IORegistryEntry
* options
;
1556 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList());
1558 while ((next
= (IORegistryEntry
*)kids
->getNextObject())) {
1559 next
->detachAll( gIODTPlane
);
1564 // Publish an IODTNVRAM class on /options.
1565 options
= rootEntry
->childFromPath("options", gIODTPlane
);
1567 dtNVRAM
= new IODTNVRAM
;
1569 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
1573 dtNVRAM
->attach(this);
1574 dtNVRAM
->registerService();
1580 // Publish the cpus.
1581 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
1583 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, NULL
));
1587 // publish top level, minus excludeList
1588 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
1592 IODTPlatformExpert::getNubResources( IOService
* nub
)
1594 if (nub
->getDeviceMemory()) {
1595 return kIOReturnSuccess
;
1598 IODTResolveAddressing( nub
, "reg", NULL
);
1600 return kIOReturnSuccess
;
1604 IODTPlatformExpert::compareNubName( const IOService
* nub
,
1605 OSString
* name
, OSString
** matched
) const
1607 return IODTCompareNubName( nub
, name
, matched
)
1608 || super::compareNubName( nub
, name
, matched
);
1612 IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1622 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1624 str
= (const char *) prop
->getBytesNoCopy();
1626 if (0 == strncmp( str
, "AAPL,", strlen( "AAPL," ))) {
1627 str
+= strlen( "AAPL," );
1631 while ((c
= *str
++)) {
1632 if ((c
== '/') || (c
== ' ')) {
1637 if (len
>= maxLength
) {
1649 IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1655 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1656 ok
= (NULL
!= prop
);
1659 strlcpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1665 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1668 IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1671 dtNVRAM
->registerNVRAMController(nvram
);
1674 super::registerNVRAMController(nvram
);
1678 IODTPlatformExpert::haltRestart(unsigned int type
)
1684 return super::haltRestart(type
);
1688 IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1692 return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1694 return kIOReturnNotReady
;
1699 IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1703 return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1705 return kIOReturnNotReady
;
1710 IODTPlatformExpert::readNVRAMProperty(
1711 IORegistryEntry
* entry
,
1712 const OSSymbol
** name
, OSData
** value
)
1715 return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1717 return kIOReturnNotReady
;
1722 IODTPlatformExpert::writeNVRAMProperty(
1723 IORegistryEntry
* entry
,
1724 const OSSymbol
* name
, OSData
* value
)
1727 return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1729 return kIOReturnNotReady
;
1734 IODTPlatformExpert::getNVRAMPartitions(void)
1737 return dtNVRAM
->getNVRAMPartitions();
1744 IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1745 IOByteCount offset
, UInt8
* buffer
,
1749 return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1752 return kIOReturnNotReady
;
1757 IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1758 IOByteCount offset
, UInt8
* buffer
,
1762 return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1765 return kIOReturnNotReady
;
1770 IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1772 IOByteCount lengthSaved
= 0;
1775 lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1778 if (lengthSaved
== 0) {
1779 lengthSaved
= super::savePanicInfo(buffer
, length
);
1786 IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
1788 UInt8
* serialNumber
;
1789 unsigned int serialNumberSize
;
1790 unsigned short pos
= 0;
1794 if (myProperty
!= NULL
) {
1795 serialNumberSize
= myProperty
->getLength();
1796 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1797 temp
= (char*)serialNumber
;
1798 if (serialNumberSize
> 0) {
1799 // check to see if this is a CTO serial number...
1800 while (pos
< serialNumberSize
&& temp
[pos
] != '-') {
1804 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1805 memcpy(SerialNo
, serialNumber
+ 12, 8);
1806 memcpy(&SerialNo
[8], serialNumber
, 3);
1808 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1810 } else { // just a normal serial number
1811 memcpy(SerialNo
, serialNumber
+ 13, 8);
1812 memcpy(&SerialNo
[8], serialNumber
, 3);
1815 return OSString::withCString(SerialNo
);
1822 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1825 #define super IOService
1827 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1829 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1830 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1831 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1832 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1834 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1837 IOPlatformExpertDevice::compareName( OSString
* name
,
1838 OSString
** matched
) const
1840 return IODTCompareNubName( this, name
, matched
);
1844 IOPlatformExpertDevice::initWithArgs(
1845 void * dtTop
, void * p2
, void * p3
, void * p4
)
1847 IORegistryEntry
* dt
= NULL
;
1850 // dtTop may be zero on non- device tree systems
1851 if (dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
))) {
1852 ok
= super::init( dt
, gIODTPlane
);
1861 workLoop
= IOWorkLoop::workLoop();
1870 IOPlatformExpertDevice::getWorkLoop() const
1876 IOPlatformExpertDevice::setProperties( OSObject
* properties
)
1878 return kIOReturnUnsupported
;
1882 IOPlatformExpertDevice::newUserClient( task_t owningTask
, void * securityID
,
1883 UInt32 type
, OSDictionary
* properties
,
1884 IOUserClient
** handler
)
1886 IOReturn err
= kIOReturnSuccess
;
1887 IOUserClient
* newConnect
= NULL
;
1888 IOUserClient
* theConnect
= NULL
;
1891 case kIOKitDiagnosticsClientType
:
1892 newConnect
= IOKitDiagnosticsClient::withTask(owningTask
);
1894 err
= kIOReturnNotPermitted
;
1897 case kIOKitUserServerClientType
:
1898 newConnect
= IOUserServer::withTask(owningTask
);
1900 err
= kIOReturnNotPermitted
;
1904 err
= kIOReturnBadArgument
;
1908 if ((false == newConnect
->attach(this))
1909 || (false == newConnect
->start(this))) {
1910 newConnect
->detach( this );
1911 newConnect
->release();
1912 err
= kIOReturnNotPermitted
;
1914 theConnect
= newConnect
;
1918 *handler
= theConnect
;
1923 IOPlatformExpertDevice::free()
1926 workLoop
->release();
1930 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1933 #define super IOService
1935 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1937 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1938 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1939 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1940 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1942 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1945 IOPlatformDevice::compareName( OSString
* name
,
1946 OSString
** matched
) const
1948 return ((IOPlatformExpert
*)getProvider())->
1949 compareNubName( this, name
, matched
);
1953 IOPlatformDevice::matchLocation( IOService
* /* client */ )
1959 IOPlatformDevice::getResources( void )
1961 return ((IOPlatformExpert
*)getProvider())->getNubResources( this );
1964 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1966 /*********************************************************************
1967 * IOPanicPlatform class
1969 * If no legitimate IOPlatformDevice matches, this one does and panics
1970 * the kernel with a suitable message.
1971 *********************************************************************/
1973 class IOPanicPlatform
: IOPlatformExpert
{
1974 OSDeclareDefaultStructors(IOPanicPlatform
);
1977 bool start(IOService
* provider
) APPLE_KEXT_OVERRIDE
;
1981 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1985 IOPanicPlatform::start(IOService
* provider
)
1987 const char * platform_name
= "(unknown platform name)";
1990 platform_name
= provider
->getName();
1993 panic("Unable to find driver for this platform: \"%s\".\n",