2 * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IOCPU.h>
30 #include <IOKit/IODeviceTreeSupport.h>
31 #include <IOKit/IOKitDebug.h>
32 #include <IOKit/IOMapper.h>
33 #include <IOKit/IOMessage.h>
34 #include <IOKit/IONVRAM.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IORangeAllocator.h>
37 #include <IOKit/IOWorkLoop.h>
38 #include <IOKit/pwr_mgt/RootDomain.h>
39 #include <IOKit/IOKitKeys.h>
40 #include <IOKit/IOTimeStamp.h>
41 #include <IOKit/IOUserClient.h>
42 #include <IOKit/IOKitDiagnosticsUserClient.h>
44 #include <IOKit/system.h>
47 #include <libkern/c++/OSContainers.h>
48 #include <libkern/crypto/sha1.h>
49 #include <libkern/OSAtomic.h>
52 #include <machine/machine_routines.h>
53 #include <pexpert/pexpert.h>
54 #include <uuid/uuid.h>
57 #define kShutdownTimeout 30 //in secs
61 boolean_t coprocessor_cross_panic_enabled
= TRUE
;
62 #define APPLE_SECURE_BOOT_VARIABLE_GUID "94b73556-2197-4702-82a8-3e1337dafbfb"
63 #endif /* !CONFIG_EMBEDDED */
65 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
66 static void getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
);
68 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
70 #define super IOService
72 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
74 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
75 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
76 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 2);
77 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 3);
78 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 4);
80 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
81 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
82 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
83 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
84 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
85 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
86 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
88 static IOPlatformExpert
* gIOPlatform
;
89 static OSDictionary
* gIOInterruptControllers
;
90 static IOLock
* gIOInterruptControllersLock
;
91 static IODTNVRAM
*gIOOptionsEntry
;
93 OSSymbol
* gPlatformInterruptControllerName
;
95 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
97 bool IOPlatformExpert::attach( IOService
* provider
)
100 if( !super::attach( provider
))
106 bool IOPlatformExpert::start( IOService
* provider
)
108 IORangeAllocator
* physicalRanges
;
109 OSData
* busFrequency
;
113 if (!super::start(provider
))
116 // Override the mapper present flag is requested by boot arguments, if SIP disabled.
118 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS
) == 0)
119 #endif /* CONFIG_CSR */
121 if (PE_parse_boot_argn("dart", &debugFlags
, sizeof (debugFlags
)) && (debugFlags
== 0))
122 removeProperty(kIOPlatformMapperPresentKey
);
123 #if DEBUG || DEVELOPMENT
124 if (PE_parse_boot_argn("-x", &debugFlags
, sizeof (debugFlags
)))
125 removeProperty(kIOPlatformMapperPresentKey
);
126 #endif /* DEBUG || DEVELOPMENT */
129 // Register the presence or lack thereof a system
130 // PCI address mapper with the IOMapper class
131 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
133 gIOInterruptControllers
= OSDictionary::withCapacity(1);
134 gIOInterruptControllersLock
= IOLockAlloc();
136 // Correct the bus frequency in the device tree.
137 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
138 provider
->setProperty("clock-frequency", busFrequency
);
139 busFrequency
->release();
141 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
143 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
144 IORangeAllocator::kLocking
);
145 assert(physicalRanges
);
146 setProperty("Platform Memory Ranges", physicalRanges
);
151 PMInstantiatePowerDomains();
153 // Parse the serial-number data and publish a user-readable string
154 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
155 if (mydata
!= NULL
) {
156 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
157 if (serNoString
!= NULL
) {
158 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
159 serNoString
->release();
164 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2
) {
165 coprocessor_paniclog_flush
= TRUE
;
166 extended_debug_log_init();
170 return( configure(provider
) );
173 bool IOPlatformExpert::configure( IOService
* provider
)
179 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
182 while( (dict
= OSDynamicCast( OSDictionary
,
183 topLevel
->getAnyObject()))) {
185 topLevel
->removeObject( dict
);
186 nub
= createNub( dict
);
191 nub
->registerService();
198 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
202 nub
= new IOPlatformDevice
;
204 if( !nub
->init( from
)) {
212 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
213 OSString
* name
, OSString
** matched
) const
215 return( nub
->IORegistryEntry::compareName( name
, matched
));
218 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
220 return( kIOReturnSuccess
);
223 long IOPlatformExpert::getBootROMType(void)
225 return _peBootROMType
;
228 long IOPlatformExpert::getChipSetType(void)
230 return _peChipSetType
;
233 long IOPlatformExpert::getMachineType(void)
235 return _peMachineType
;
238 void IOPlatformExpert::setBootROMType(long peBootROMType
)
240 _peBootROMType
= peBootROMType
;
243 void IOPlatformExpert::setChipSetType(long peChipSetType
)
245 _peChipSetType
= peChipSetType
;
248 void IOPlatformExpert::setMachineType(long peMachineType
)
250 _peMachineType
= peMachineType
;
253 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
258 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
263 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
268 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
270 return(OSDynamicCast(IORangeAllocator
,
271 getProperty("Platform Memory Ranges")));
274 int (*PE_halt_restart
)(unsigned int type
) = 0;
276 int IOPlatformExpert::haltRestart(unsigned int type
)
278 if (type
== kPEPanicSync
) return 0;
280 if (type
== kPEHangCPU
) while (true) {}
282 if (type
== kPEUPSDelayHaltCPU
) {
283 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
288 // On ARM kPEPanicRestartCPU is supported in the drivers
289 if (type
== kPEPanicRestartCPU
)
290 type
= kPERestartCPU
;
293 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
297 void IOPlatformExpert::sleepKernel(void)
303 intState
= ml_set_interrupts_enabled(false);
305 for (cnt
= 0; cnt
< 10000; cnt
++) {
309 ml_set_interrupts_enabled(intState
);
311 // PE_initialize_console(0, kPEDisableScreen);
315 // PE_initialize_console(0, kPEEnableScreen);
319 long IOPlatformExpert::getGMTTimeOfDay(void)
324 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
329 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
331 return( PE_current_console( consoleInfo
));
334 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
337 return( PE_initialize_console( consoleInfo
, op
));
340 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
342 IOLockLock(gIOInterruptControllersLock
);
344 gIOInterruptControllers
->setObject(name
, interruptController
);
346 IOLockWakeup(gIOInterruptControllersLock
,
347 gIOInterruptControllers
, /* one-thread */ false);
349 IOLockUnlock(gIOInterruptControllersLock
);
351 return kIOReturnSuccess
;
354 IOReturn
IOPlatformExpert::deregisterInterruptController(OSSymbol
*name
)
356 IOLockLock(gIOInterruptControllersLock
);
358 gIOInterruptControllers
->removeObject(name
);
360 IOLockUnlock(gIOInterruptControllersLock
);
362 return kIOReturnSuccess
;
365 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
369 IOLockLock(gIOInterruptControllersLock
);
372 object
= gIOInterruptControllers
->getObject(name
);
377 IOLockSleep(gIOInterruptControllersLock
,
378 gIOInterruptControllers
, THREAD_UNINT
);
381 IOLockUnlock(gIOInterruptControllersLock
);
382 return OSDynamicCast(IOInterruptController
, object
);
386 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
388 IOCPUInterruptController
*controller
;
390 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
391 if (controller
) controller
->setCPUInterruptProperties(service
);
394 bool IOPlatformExpert::atInterruptLevel(void)
396 return ml_at_interrupt_context();
399 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
404 void IOPlatformExpert::getUTCTimeOfDay(clock_sec_t
* secs
, clock_nsec_t
* nsecs
)
406 *secs
= getGMTTimeOfDay();
410 void IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs
, __unused clock_nsec_t nsecs
)
412 setGMTTimeOfDay(secs
);
416 //*********************************************************************************
419 //*********************************************************************************
421 void IOPlatformExpert::
422 PMLog(const char *who
, unsigned long event
,
423 unsigned long param1
, unsigned long param2
)
427 clock_get_system_microtime(&nows
, &nowus
);
428 nowus
+= (nows
% 1000) * 1000000;
430 kprintf("pm%u %p %.30s %d %lx %lx\n",
431 nowus
, OBFUSCATE(current_thread()), who
, // Identity
432 (int) event
, (long)OBFUSCATE(param1
), (long)OBFUSCATE(param2
)); // Args
436 //*********************************************************************************
437 // PMInstantiatePowerDomains
439 // In this vanilla implementation, a Root Power Domain is instantiated.
440 // All other objects which register will be children of this Root.
441 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
442 // in a platform-specific subclass.
443 //*********************************************************************************
445 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
447 root
= new IOPMrootDomain
;
454 //*********************************************************************************
457 // In this vanilla implementation, all callers are made children of the root power domain.
458 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
459 //*********************************************************************************
461 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
463 root
->addPowerChild ( theDevice
);
466 //*********************************************************************************
469 //*********************************************************************************
471 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
473 return ((_pePMFeatures
& featureMask
) != 0);
476 //*********************************************************************************
479 //*********************************************************************************
481 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
483 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
486 //*********************************************************************************
487 // numBatteriesSupported
489 //*********************************************************************************
491 int IOPlatformExpert::numBatteriesSupported (void)
493 return (_peNumBatteriesSupported
);
496 //*********************************************************************************
499 // This method is called by the instantiated sublass of the platform expert to
500 // determine how a device should be inserted into the Power Domain. The subclass
501 // provides an XML power tree description against which a device is matched based
502 // on class and provider. If a match is found this routine returns true in addition
503 // to flagging the description tree at the appropriate node that a device has been
504 // registered for the given service.
505 //*********************************************************************************
507 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
510 unsigned int numPowerTreeNodes
;
511 OSDictionary
* entry
;
512 OSDictionary
* matchingDictionary
;
513 OSDictionary
* providerDictionary
;
514 OSDictionary
* deviceDictionary
;
515 OSDictionary
* nubDictionary
;
517 bool nodeFound
= false;
518 bool continueSearch
= false;
519 bool deviceMatch
= false;
520 bool providerMatch
= false;
521 bool multiParentMatch
= false;
523 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
526 numPowerTreeNodes
= inSubTree
->getCount ();
528 // iterate through the power tree to find a home for this device
530 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
532 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
534 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
535 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
537 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
538 if ( matchingDictionary
) {
540 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
541 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
542 deviceDictionary
->release ();
546 providerMatch
= true; // we indicate a match if there is no nub or provider
547 if ( theNub
&& providerDictionary
) {
548 providerMatch
= false;
549 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
550 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
551 nubDictionary
->release ();
555 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
556 if (deviceMatch
&& providerMatch
) {
557 if (NULL
!= multipleParentKeyValue
) {
558 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
559 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
563 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
565 // if the power tree specifies a provider dictionary but theNub is
566 // NULL then we cannot match with this entry.
568 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
571 // if this node is THE ONE...then register the device
574 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
576 if ( kIOLogPower
& gIOKitDebug
)
577 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
579 numInstancesRegistered
++;
581 // determine if we need to search for additional nodes for this item
582 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
588 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
590 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
591 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
592 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
595 if ( false == continueSearch
)
599 return ( nodeFound
);
602 //*********************************************************************************
603 // RegisterServiceInTree
605 // Register a device at the specified node of our power tree.
606 //*********************************************************************************
608 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
610 IOService
* aService
;
611 bool registered
= false;
613 unsigned int numChildren
;
614 OSDictionary
* child
;
616 // make sure someone is not already registered here
618 if ( NULL
== theTreeNode
->getObject ("service") ) {
620 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
622 // 1. CHILDREN ------------------
624 // we registered the node in the tree...now if the node has children
625 // registered we must tell this service to add them.
627 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
628 numChildren
= children
->getCount ();
629 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
630 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
631 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
632 theService
->addPowerChild (aService
);
637 // 2. PARENT --------------------
639 // also we must notify the parent of this node (if a registered service
640 // exists there) of a new child.
642 if ( theTreeParentNode
) {
643 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
644 if (aService
!= theProvider
)
645 aService
->addPowerChild (theService
);
655 //*********************************************************************************
656 // printDictionaryKeys
658 // Print the keys for the given dictionary and selected contents.
659 //*********************************************************************************
660 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
662 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
669 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
673 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
675 // if this is the IOClass key, print it's contents
677 if ( mkey
->isEqualTo ("IOClass") ) {
678 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
679 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
682 // if this is an IOProviderClass key print it
684 if ( mkey
->isEqualTo ("IOProviderClass") ) {
685 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
686 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
690 // also print IONameMatch keys
691 if ( mkey
->isEqualTo ("IONameMatch") ) {
692 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
693 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
696 // also print IONameMatched keys
698 if ( mkey
->isEqualTo ("IONameMatched") ) {
699 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
700 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
706 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
708 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
710 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
716 if ( mkey
->isEqualTo ("name") ) {
719 getCStringForObject(inDictionary
->getObject("name"), nameStr
,
721 if (strlen(nameStr
) > 0)
722 IOLog ("%s name is %s\n", inMsg
, nameStr
);
725 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
734 getCStringForObject(OSObject
*inObj
, char *outStr
, size_t outStrLen
)
739 if ( (NULL
== inObj
) || (NULL
== outStr
))
742 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
744 if ((0 == strncmp(objString
, "OSString", sizeof("OSString"))) ||
745 (0 == strncmp(objString
, "OSSymbol", sizeof("OSSymbol"))))
746 strlcpy(outStr
, ((OSString
*)inObj
)->getCStringNoCopy(), outStrLen
);
748 else if (0 == strncmp(objString
, "OSData", sizeof("OSData"))) {
749 len
= ((OSData
*)inObj
)->getLength();
750 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
751 if (buffer
&& (len
> 0)) {
752 for (i
=0; i
< len
; i
++) {
753 outStr
[i
] = buffer
[i
];
760 /* IOShutdownNotificationsTimedOut
761 * - Called from a timer installed by PEHaltRestart
763 static void IOShutdownNotificationsTimedOut(
764 thread_call_param_t p0
,
765 thread_call_param_t p1
)
767 #ifdef CONFIG_EMBEDDED
768 /* 30 seconds has elapsed - panic */
769 panic("Halt/Restart Timed Out");
771 #else /* ! CONFIG_EMBEDDED */
772 int type
= (int)(long)p0
;
773 uint32_t timeout
= (uint32_t)(uintptr_t)p1
;
775 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
777 if ((PEGetCoprocessorVersion() >= kCoprocessorVersion2
) || pmRootDomain
->checkShutdownTimeout()) {
778 pmRootDomain
->panicWithShutdownLog(timeout
* 1000);
782 /* 30 seconds has elapsed - resume shutdown */
783 if(gIOPlatform
) gIOPlatform
->haltRestart(type
);
784 #endif /* CONFIG_EMBEDDED */
791 * Callouts from BSD for machine name & model
794 boolean_t
PEGetMachineName( char * name
, int maxLength
)
797 return( gIOPlatform
->getMachineName( name
, maxLength
));
802 boolean_t
PEGetModelName( char * name
, int maxLength
)
805 return( gIOPlatform
->getModelName( name
, maxLength
));
810 int PEGetPlatformEpoch(void)
813 return( gIOPlatform
->getBootROMType());
818 int PEHaltRestart(unsigned int type
)
820 IOPMrootDomain
*pmRootDomain
;
821 AbsoluteTime deadline
;
822 thread_call_t shutdown_hang
;
823 IORegistryEntry
*node
;
825 uint32_t timeout
= kShutdownTimeout
;
826 static boolean_t panic_begin_called
= FALSE
;
828 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
|| type
== kPEUPSDelayHaltCPU
)
830 pmRootDomain
= IOService::getPMRootDomain();
831 /* Notify IOKit PM clients of shutdown/restart
832 Clients subscribe to this message with a call to
833 IOService::registerInterest()
836 /* Spawn a thread that will panic in 30 seconds.
837 If all goes well the machine will be off by the time
838 the timer expires. If the device wants a different
839 timeout, use that value instead of 30 seconds.
842 #define RESTART_NODE_PATH "/defaults"
844 #define RESTART_NODE_PATH "/chosen"
846 node
= IORegistryEntry::fromPath( RESTART_NODE_PATH
, gIODTPlane
);
848 data
= OSDynamicCast( OSData
, node
->getProperty( "halt-restart-timeout" ) );
849 if ( data
&& data
->getLength() == 4 )
850 timeout
= *((uint32_t *) data
->getBytesNoCopy());
853 shutdown_hang
= thread_call_allocate( &IOShutdownNotificationsTimedOut
,
854 (thread_call_param_t
)(uintptr_t) type
);
855 clock_interval_to_deadline( timeout
, kSecondScale
, &deadline
);
856 thread_call_enter1_delayed( shutdown_hang
, (thread_call_param_t
)(uintptr_t)timeout
, deadline
);
858 pmRootDomain
->handlePlatformHaltRestart(type
);
859 /* This notification should have few clients who all do
860 their work synchronously.
862 In this "shutdown notification" context we don't give
863 drivers the option of working asynchronously and responding
864 later. PM internals make it very hard to wait for asynchronous
868 else if(type
== kPEPanicRestartCPU
|| type
== kPEPanicSync
)
870 if (type
== kPEPanicRestartCPU
) {
871 // Notify any listeners that we're done collecting
872 // panic data before we call through to do the restart
874 if (coprocessor_cross_panic_enabled
)
876 IOCPURunPlatformPanicActions(kPEPanicEnd
);
878 // Callout to shutdown the disk driver once we've returned from the
879 // kPEPanicEnd callback (and we know all core dumps on this system
881 IOCPURunPlatformPanicActions(kPEPanicDiskShutdown
);
884 // Do an initial sync to flush as much panic data as possible,
885 // in case we have a problem in one of the platorm panic handlers.
886 // After running the platform handlers, do a final sync w/
887 // platform hardware quiesced for the panic.
888 PE_sync_panic_buffers();
889 IOCPURunPlatformPanicActions(type
);
890 PE_sync_panic_buffers();
892 else if (type
== kPEPanicEnd
) {
894 if (coprocessor_cross_panic_enabled
)
896 IOCPURunPlatformPanicActions(type
);
898 } else if (type
== kPEPanicBegin
) {
900 if (coprocessor_cross_panic_enabled
)
903 // Only call the kPEPanicBegin callout once
904 if (!panic_begin_called
) {
905 panic_begin_called
= TRUE
;
906 IOCPURunPlatformPanicActions(type
);
911 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
915 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
917 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
921 void PESavePanicInfoAction(void *buffer
, UInt32 offset
, UInt32 length
)
923 IOCPURunPlatformPanicSyncAction(buffer
, offset
, length
);
928 inline static int init_gIOOptionsEntry(void)
930 IORegistryEntry
*entry
;
932 volatile void **options
;
938 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
942 nvram_entry
= (void *) OSDynamicCast(IODTNVRAM
, entry
);
946 options
= (volatile void **) &gIOOptionsEntry
;
947 if (!OSCompareAndSwapPtr(NULL
, nvram_entry
, options
)) {
960 /* pass in a NULL value if you just want to figure out the len */
961 boolean_t
PEReadNVRAMProperty(const char *symbol
, void *value
,
971 if (init_gIOOptionsEntry() < 0)
977 obj
= gIOOptionsEntry
->getProperty(symbol
);
981 /* convert to data */
982 data
= OSDynamicCast(OSData
, obj
);
986 *len
= data
->getLength();
987 vlen
= min(vlen
, *len
);
989 memcpy((void *) value
, data
->getBytesNoCopy(), vlen
);
998 PEWriteNVRAMBooleanProperty(const char *symbol
, boolean_t value
)
1000 const OSSymbol
*sym
= NULL
;
1001 OSBoolean
*data
= NULL
;
1004 if (symbol
== NULL
) {
1008 if (init_gIOOptionsEntry() < 0) {
1012 if ((sym
= OSSymbol::withCStringNoCopy(symbol
)) == NULL
) {
1016 data
= value
? kOSBooleanTrue
: kOSBooleanFalse
;
1017 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1021 /* success, force the NVRAM to flush writes */
1023 gIOOptionsEntry
->sync();
1030 boolean_t
PEWriteNVRAMProperty(const char *symbol
, const void *value
,
1031 const unsigned int len
)
1033 const OSSymbol
*sym
;
1037 if (!symbol
|| !value
|| !len
)
1040 if (init_gIOOptionsEntry() < 0)
1043 sym
= OSSymbol::withCStringNoCopy(symbol
);
1047 data
= OSData::withBytes((void *) value
, len
);
1051 ret
= gIOOptionsEntry
->setProperty(sym
, data
);
1058 gIOOptionsEntry
->sync();
1067 boolean_t
PERemoveNVRAMProperty(const char *symbol
)
1069 const OSSymbol
*sym
;
1074 if (init_gIOOptionsEntry() < 0)
1077 sym
= OSSymbol::withCStringNoCopy(symbol
);
1081 gIOOptionsEntry
->removeProperty(sym
);
1085 gIOOptionsEntry
->sync();
1093 long PEGetGMTTimeOfDay(void)
1098 PEGetUTCTimeOfDay(&secs
, &usecs
);
1102 void PESetGMTTimeOfDay(long secs
)
1104 PESetUTCTimeOfDay(secs
, 0);
1107 void PEGetUTCTimeOfDay(clock_sec_t
* secs
, clock_usec_t
* usecs
)
1109 clock_nsec_t nsecs
= 0;
1113 gIOPlatform
->getUTCTimeOfDay(secs
, &nsecs
);
1115 assert(nsecs
< NSEC_PER_SEC
);
1116 *usecs
= nsecs
/ NSEC_PER_USEC
;
1119 void PESetUTCTimeOfDay(clock_sec_t secs
, clock_usec_t usecs
)
1121 assert(usecs
< USEC_PER_SEC
);
1123 gIOPlatform
->setUTCTimeOfDay(secs
, usecs
* NSEC_PER_USEC
);
1126 coprocessor_type_t
PEGetCoprocessorVersion( void )
1128 coprocessor_type_t coprocessor_version
= kCoprocessorVersionNone
;
1129 #if !CONFIG_EMBEDDED
1130 IORegistryEntry
*platform_entry
= NULL
;
1131 OSData
*coprocessor_version_obj
= NULL
;
1133 platform_entry
= IORegistryEntry::fromPath(kIODeviceTreePlane
":/efi/platform");
1134 if (platform_entry
!= NULL
) {
1135 coprocessor_version_obj
= OSDynamicCast(OSData
, platform_entry
->getProperty("apple-coprocessor-version"));
1136 if ((coprocessor_version_obj
!= NULL
) && (coprocessor_version_obj
->getLength() <= sizeof(uint64_t))) {
1137 memcpy(&coprocessor_version
, coprocessor_version_obj
->getBytesNoCopy(), coprocessor_version_obj
->getLength());
1139 platform_entry
->release();
1142 return coprocessor_version
;
1147 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
1150 IORegistryEntry
* entry
;
1151 OSString
* string
= 0;
1155 entry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
);
1160 data1
= OSDynamicCast( OSData
, entry
->getProperty( "unique-chip-id" ) );
1161 if ( data1
&& data1
->getLength( ) == 8 )
1165 data2
= OSDynamicCast( OSData
, entry
->getProperty( "chip-id" ) );
1166 if ( data2
&& data2
->getLength( ) == 4 )
1169 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1170 const uuid_t space
= { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
1172 SHA1Init( &context
);
1173 SHA1Update( &context
, space
, sizeof( space
) );
1174 SHA1Update( &context
, data1
->getBytesNoCopy( ), data1
->getLength( ) );
1175 SHA1Update( &context
, data2
->getBytesNoCopy( ), data2
->getLength( ) );
1176 SHA1Final( digest
, &context
);
1178 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1179 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1181 uuid_unparse( digest
, uuid
);
1182 string
= OSString::withCString( uuid
);
1188 #else /* !CONFIG_EMBEDDED */
1190 * If we have panic debugging enabled and a prod-fused coprocessor,
1191 * disable cross panics so that the co-processor doesn't cause the system
1192 * to reset when we enter the debugger or hit a panic on the x86 side.
1194 if ( panicDebugging
)
1196 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1199 data
= OSDynamicCast( OSData
, entry
->getProperty( APPLE_SECURE_BOOT_VARIABLE_GUID
":EffectiveProductionStatus" ) );
1200 if ( data
&& ( data
->getLength( ) == sizeof( UInt8
) ) ) {
1201 UInt8
*isProdFused
= (UInt8
*) data
->getBytesNoCopy( );
1202 UInt32 debug_flags
= 0;
1203 if ( *isProdFused
|| ( PE_i_can_has_debugger(&debug_flags
) &&
1204 ( debug_flags
& DB_DISABLE_CROSS_PANIC
) ) ) {
1205 coprocessor_cross_panic_enabled
= FALSE
;
1212 entry
= IORegistryEntry::fromPath( "/efi/platform", gIODTPlane
);
1215 data
= OSDynamicCast( OSData
, entry
->getProperty( "system-id" ) );
1216 if ( data
&& data
->getLength( ) == 16 )
1219 uint8_t digest
[ SHA_DIGEST_LENGTH
];
1220 const uuid_t space
= { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
1222 SHA1Init( &context
);
1223 SHA1Update( &context
, space
, sizeof( space
) );
1224 SHA1Update( &context
, data
->getBytesNoCopy( ), data
->getLength( ) );
1225 SHA1Final( digest
, &context
);
1227 digest
[ 6 ] = ( digest
[ 6 ] & 0x0F ) | 0x50;
1228 digest
[ 8 ] = ( digest
[ 8 ] & 0x3F ) | 0x80;
1230 uuid_unparse( digest
, uuid
);
1231 string
= OSString::withCString( uuid
);
1236 #endif /* !CONFIG_EMBEDDED */
1240 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1243 data
= OSDynamicCast( OSData
, entry
->getProperty( "platform-uuid" ) );
1244 if ( data
&& data
->getLength( ) == sizeof( uuid_t
) )
1246 uuid_unparse( ( uint8_t * ) data
->getBytesNoCopy( ), uuid
);
1247 string
= OSString::withCString( uuid
);
1256 getProvider( )->setProperty( kIOPlatformUUIDKey
, string
);
1257 publishResource( kIOPlatformUUIDKey
, string
);
1262 publishResource("IONVRAM");
1265 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
1266 bool waitForFunction
,
1267 void *param1
, void *param2
,
1268 void *param3
, void *param4
)
1270 IOService
*service
, *_resources
;
1272 if (waitForFunction
) {
1273 _resources
= waitForService(resourceMatching(functionName
));
1275 _resources
= getResourceService();
1277 if (_resources
== 0) return kIOReturnUnsupported
;
1279 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
1280 if (service
== 0) return kIOReturnUnsupported
;
1282 return service
->callPlatformFunction(functionName
, waitForFunction
,
1283 param1
, param2
, param3
, param4
);
1286 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1291 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1294 #define super IOPlatformExpert
1296 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
1298 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
1299 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
1300 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
1301 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
1302 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
1303 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
1304 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
1305 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
1307 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1309 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
1312 if( !super::probe( provider
, score
))
1315 // check machine types
1316 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
1322 bool IODTPlatformExpert::configure( IOService
* provider
)
1324 if( !super::configure( provider
))
1327 processTopLevel( provider
);
1332 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
1336 nub
= new IOPlatformDevice
;
1338 if( !nub
->init( from
, gIODTPlane
)) {
1346 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
1348 IORegistryEntry
* next
;
1353 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
1355 if( 0 == (nub
= createNub( next
)))
1358 nub
->attach( parent
);
1359 nub
->registerService();
1367 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
1370 IORegistryEntry
* next
;
1371 IORegistryEntry
* cpus
;
1372 IORegistryEntry
* options
;
1375 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
1377 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
1378 next
->detachAll( gIODTPlane
);
1383 // Publish an IODTNVRAM class on /options.
1384 options
= rootEntry
->childFromPath("options", gIODTPlane
);
1386 dtNVRAM
= new IODTNVRAM
;
1388 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
1392 dtNVRAM
->attach(this);
1393 dtNVRAM
->registerService();
1399 // Publish the cpus.
1400 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
1403 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
1407 // publish top level, minus excludeList
1408 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
1411 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
1413 if( nub
->getDeviceMemory())
1414 return( kIOReturnSuccess
);
1416 IODTResolveAddressing( nub
, "reg", 0);
1418 return( kIOReturnSuccess
);
1421 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
1422 OSString
* name
, OSString
** matched
) const
1424 return( IODTCompareNubName( nub
, name
, matched
)
1425 || super::compareNubName( nub
, name
, matched
) );
1428 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1438 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1440 str
= (const char *) prop
->getBytesNoCopy();
1442 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1443 str
+= strlen( "AAPL," );
1446 while( (c
= *str
++)) {
1447 if( (c
== '/') || (c
== ' '))
1451 if( len
>= maxLength
)
1461 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1467 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1471 strlcpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1476 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1478 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1480 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1482 super::registerNVRAMController(nvram
);
1485 int IODTPlatformExpert::haltRestart(unsigned int type
)
1487 if (dtNVRAM
) dtNVRAM
->sync();
1489 return super::haltRestart(type
);
1492 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1495 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1496 else return kIOReturnNotReady
;
1499 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1502 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1503 else return kIOReturnNotReady
;
1506 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1507 IORegistryEntry
* entry
,
1508 const OSSymbol
** name
, OSData
** value
)
1510 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1511 else return kIOReturnNotReady
;
1514 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1515 IORegistryEntry
* entry
,
1516 const OSSymbol
* name
, OSData
* value
)
1518 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1519 else return kIOReturnNotReady
;
1522 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1524 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1528 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1529 IOByteCount offset
, UInt8
* buffer
,
1532 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1534 else return kIOReturnNotReady
;
1537 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1538 IOByteCount offset
, UInt8
* buffer
,
1541 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1543 else return kIOReturnNotReady
;
1546 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1548 IOByteCount lengthSaved
= 0;
1550 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1552 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1557 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1558 UInt8
* serialNumber
;
1559 unsigned int serialNumberSize
;
1560 unsigned short pos
= 0;
1564 if (myProperty
!= NULL
) {
1565 serialNumberSize
= myProperty
->getLength();
1566 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1567 temp
= (char*)serialNumber
;
1568 if (serialNumberSize
> 0) {
1569 // check to see if this is a CTO serial number...
1570 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1572 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1573 memcpy(SerialNo
, serialNumber
+ 12, 8);
1574 memcpy(&SerialNo
[8], serialNumber
, 3);
1576 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1578 } else { // just a normal serial number
1579 memcpy(SerialNo
, serialNumber
+ 13, 8);
1580 memcpy(&SerialNo
[8], serialNumber
, 3);
1583 return OSString::withCString(SerialNo
);
1590 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1593 #define super IOService
1595 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1597 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1598 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1599 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1600 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1602 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1604 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1605 OSString
** matched
) const
1607 return( IODTCompareNubName( this, name
, matched
));
1611 IOPlatformExpertDevice::initWithArgs(
1612 void * dtTop
, void * p2
, void * p3
, void * p4
)
1614 IORegistryEntry
* dt
= 0;
1617 // dtTop may be zero on non- device tree systems
1618 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1619 ok
= super::init( dt
, gIODTPlane
);
1626 workLoop
= IOWorkLoop::workLoop();
1633 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1638 IOReturn
IOPlatformExpertDevice::setProperties( OSObject
* properties
)
1640 OSDictionary
* dictionary
;
1644 status
= super::setProperties( properties
);
1645 if ( status
!= kIOReturnUnsupported
) return status
;
1647 status
= IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator
);
1648 if ( status
!= kIOReturnSuccess
) return status
;
1650 dictionary
= OSDynamicCast( OSDictionary
, properties
);
1651 if ( dictionary
== 0 ) return kIOReturnBadArgument
;
1653 object
= dictionary
->getObject( kIOPlatformUUIDKey
);
1656 IORegistryEntry
* entry
;
1660 string
= ( OSString
* ) getProperty( kIOPlatformUUIDKey
);
1661 if ( string
) return kIOReturnNotPermitted
;
1663 string
= OSDynamicCast( OSString
, object
);
1664 if ( string
== 0 ) return kIOReturnBadArgument
;
1666 status
= uuid_parse( string
->getCStringNoCopy( ), uuid
);
1667 if ( status
!= 0 ) return kIOReturnBadArgument
;
1669 entry
= IORegistryEntry::fromPath( "/options", gIODTPlane
);
1672 entry
->setProperty( "platform-uuid", uuid
, sizeof( uuid_t
) );
1676 setProperty( kIOPlatformUUIDKey
, string
);
1677 publishResource( kIOPlatformUUIDKey
, string
);
1679 return kIOReturnSuccess
;
1682 return kIOReturnUnsupported
;
1685 IOReturn
IOPlatformExpertDevice::newUserClient( task_t owningTask
, void * securityID
,
1686 UInt32 type
, OSDictionary
* properties
,
1687 IOUserClient
** handler
)
1689 IOReturn err
= kIOReturnSuccess
;
1690 IOUserClient
* newConnect
= 0;
1691 IOUserClient
* theConnect
= 0;
1695 case kIOKitDiagnosticsClientType
:
1696 newConnect
= IOKitDiagnosticsClient::withTask(owningTask
);
1697 if (!newConnect
) err
= kIOReturnNotPermitted
;
1700 err
= kIOReturnBadArgument
;
1705 if ((false == newConnect
->attach(this))
1706 || (false == newConnect
->start(this)))
1708 newConnect
->detach( this );
1709 newConnect
->release();
1710 err
= kIOReturnNotPermitted
;
1713 theConnect
= newConnect
;
1716 *handler
= theConnect
;
1720 void IOPlatformExpertDevice::free()
1723 workLoop
->release();
1726 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1729 #define super IOService
1731 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1733 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1734 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1735 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1736 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1738 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1740 bool IOPlatformDevice::compareName( OSString
* name
,
1741 OSString
** matched
) const
1743 return( ((IOPlatformExpert
*)getProvider())->
1744 compareNubName( this, name
, matched
));
1747 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1752 IOReturn
IOPlatformDevice::getResources( void )
1754 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1757 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1759 /*********************************************************************
1760 * IOPanicPlatform class
1762 * If no legitimate IOPlatformDevice matches, this one does and panics
1763 * the kernel with a suitable message.
1764 *********************************************************************/
1766 class IOPanicPlatform
: IOPlatformExpert
{
1767 OSDeclareDefaultStructors(IOPanicPlatform
);
1770 bool start(IOService
* provider
) APPLE_KEXT_OVERRIDE
;
1774 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1777 bool IOPanicPlatform::start(IOService
* provider
) {
1778 const char * platform_name
= "(unknown platform name)";
1780 if (provider
) platform_name
= provider
->getName();
1782 panic("Unable to find driver for this platform: \"%s\".\n",