]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOPlatformExpert.cpp
xnu-6153.61.1.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
CommitLineData
1c79356b 1/*
cc8bc92a 2 * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
0a7de745 28
1c79356b
A
29#include <IOKit/IOCPU.h>
30#include <IOKit/IODeviceTreeSupport.h>
de355530 31#include <IOKit/IOKitDebug.h>
55e303ae
A
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>
1c79356b
A
37#include <IOKit/IOWorkLoop.h>
38#include <IOKit/pwr_mgt/RootDomain.h>
55e303ae 39#include <IOKit/IOKitKeys.h>
91447636 40#include <IOKit/IOTimeStamp.h>
2d21ac55 41#include <IOKit/IOUserClient.h>
3e170ce0 42#include <IOKit/IOKitDiagnosticsUserClient.h>
cb323159 43#include <IOKit/IOUserServer.h>
55e303ae
A
44
45#include <IOKit/system.h>
5ba3f43e 46#include <sys/csr.h>
55e303ae 47
1c79356b 48#include <libkern/c++/OSContainers.h>
4a3eedf9 49#include <libkern/crypto/sha1.h>
6d2010ae 50#include <libkern/OSAtomic.h>
1c79356b 51
1c79356b
A
52extern "C" {
53#include <machine/machine_routines.h>
54#include <pexpert/pexpert.h>
2d21ac55 55#include <uuid/uuid.h>
1c79356b
A
56}
57
5c9f4661 58#define kShutdownTimeout 30 //in secs
cc8bc92a 59
cb323159 60#if defined(XNU_TARGET_OS_OSX)
cc8bc92a
A
61
62boolean_t coprocessor_cross_panic_enabled = TRUE;
cb323159
A
63#define APPLE_VENDOR_VARIABLE_GUID "4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14"
64#endif /* defined(XNU_TARGET_OS_OSX) */
5ba3f43e 65
0a7de745 66void printDictionaryKeys(OSDictionary * inDictionary, char * inMsg);
2d21ac55 67static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen);
1c79356b 68
cb323159
A
69/*
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.
75 *
76 * <rdar://problem/33831837> tracks turning this on by default.
77 */
78uint32_t gEnforceQuiesceSafety = 0;
79
1c79356b
A
80/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
81
82#define super IOService
83
84OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
85
0a7de745
A
86OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
87OSMetaClassDefineReservedUsed(IOPlatformExpert, 1);
88OSMetaClassDefineReservedUsed(IOPlatformExpert, 2);
89OSMetaClassDefineReservedUsed(IOPlatformExpert, 3);
90OSMetaClassDefineReservedUsed(IOPlatformExpert, 4);
91
92OSMetaClassDefineReservedUnused(IOPlatformExpert, 5);
93OSMetaClassDefineReservedUnused(IOPlatformExpert, 6);
94OSMetaClassDefineReservedUnused(IOPlatformExpert, 7);
95OSMetaClassDefineReservedUnused(IOPlatformExpert, 8);
96OSMetaClassDefineReservedUnused(IOPlatformExpert, 9);
1c79356b
A
97OSMetaClassDefineReservedUnused(IOPlatformExpert, 10);
98OSMetaClassDefineReservedUnused(IOPlatformExpert, 11);
99
100static IOPlatformExpert * gIOPlatform;
fa4905b1
A
101static OSDictionary * gIOInterruptControllers;
102static IOLock * gIOInterruptControllersLock;
6d2010ae 103static IODTNVRAM *gIOOptionsEntry;
1c79356b
A
104
105OSSymbol * gPlatformInterruptControllerName;
106
107/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
108
0a7de745
A
109bool
110IOPlatformExpert::attach( IOService * provider )
1c79356b 111{
0a7de745
A
112 if (!super::attach( provider )) {
113 return false;
114 }
1c79356b 115
0a7de745 116 return true;
1c79356b
A
117}
118
0a7de745
A
119bool
120IOPlatformExpert::start( IOService * provider )
1c79356b 121{
0a7de745
A
122 IORangeAllocator * physicalRanges;
123 OSData * busFrequency;
124 uint32_t debugFlags;
125
126
127 if (!super::start(provider)) {
128 return false;
129 }
5ba3f43e 130
0a7de745 131 // Override the mapper present flag is requested by boot arguments, if SIP disabled.
5ba3f43e 132#if CONFIG_CSR
0a7de745 133 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) == 0)
5ba3f43e 134#endif /* CONFIG_CSR */
0a7de745
A
135 {
136 if (PE_parse_boot_argn("dart", &debugFlags, sizeof(debugFlags)) && (debugFlags == 0)) {
137 removeProperty(kIOPlatformMapperPresentKey);
138 }
5ba3f43e 139#if DEBUG || DEVELOPMENT
0a7de745
A
140 if (PE_parse_boot_argn("-x", &debugFlags, sizeof(debugFlags))) {
141 removeProperty(kIOPlatformMapperPresentKey);
142 }
5ba3f43e 143#endif /* DEBUG || DEVELOPMENT */
0a7de745
A
144 }
145
146 // Register the presence or lack thereof a system
147 // PCI address mapper with the IOMapper class
cb323159 148 IOMapper::setMapperRequired(NULL != getProperty(kIOPlatformMapperPresentKey));
0a7de745
A
149
150 gIOInterruptControllers = OSDictionary::withCapacity(1);
151 gIOInterruptControllersLock = IOLockAlloc();
152
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();
157
158 gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
159
160 physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16,
161 IORangeAllocator::kLocking);
162 assert(physicalRanges);
163 setProperty("Platform Memory Ranges", physicalRanges);
164
165 setPlatform( this );
166 gIOPlatform = this;
167
168 PMInstantiatePowerDomains();
169
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();
177 }
178 }
5ba3f43e 179
cc8bc92a 180#if !CONFIG_EMBEDDED
0a7de745
A
181 if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
182 coprocessor_paniclog_flush = TRUE;
183 extended_debug_log_init();
184 }
5c9f4661 185#endif
5ba3f43e 186
cb323159
A
187 PE_parse_boot_argn("enforce_quiesce_safety", &gEnforceQuiesceSafety,
188 sizeof(gEnforceQuiesceSafety));
189
0a7de745 190 return configure(provider);
1c79356b
A
191}
192
0a7de745
A
193bool
194IOPlatformExpert::configure( IOService * provider )
195{
196 OSSet * topLevel;
197 OSDictionary * dict;
198 IOService * nub;
199
200 topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
201
202 if (topLevel) {
203 while ((dict = OSDynamicCast( OSDictionary,
204 topLevel->getAnyObject()))) {
205 dict->retain();
206 topLevel->removeObject( dict );
207 nub = createNub( dict );
cb323159 208 if (NULL == nub) {
0a7de745
A
209 continue;
210 }
211 dict->release();
212 nub->attach( this );
213 nub->registerService();
214 }
215 }
1c79356b 216
0a7de745 217 return true;
1c79356b
A
218}
219
0a7de745
A
220IOService *
221IOPlatformExpert::createNub( OSDictionary * from )
1c79356b 222{
0a7de745 223 IOService * nub;
1c79356b 224
0a7de745
A
225 nub = new IOPlatformDevice;
226 if (nub) {
227 if (!nub->init( from )) {
228 nub->release();
cb323159 229 nub = NULL;
0a7de745 230 }
1c79356b 231 }
0a7de745 232 return nub;
1c79356b
A
233}
234
0a7de745
A
235bool
236IOPlatformExpert::compareNubName( const IOService * nub,
237 OSString * name, OSString ** matched ) const
1c79356b 238{
0a7de745 239 return nub->IORegistryEntry::compareName( name, matched );
1c79356b
A
240}
241
0a7de745
A
242IOReturn
243IOPlatformExpert::getNubResources( IOService * nub )
1c79356b 244{
0a7de745 245 return kIOReturnSuccess;
1c79356b
A
246}
247
0a7de745
A
248long
249IOPlatformExpert::getBootROMType(void)
1c79356b 250{
0a7de745 251 return _peBootROMType;
1c79356b
A
252}
253
0a7de745
A
254long
255IOPlatformExpert::getChipSetType(void)
1c79356b 256{
0a7de745 257 return _peChipSetType;
1c79356b
A
258}
259
0a7de745
A
260long
261IOPlatformExpert::getMachineType(void)
1c79356b 262{
0a7de745 263 return _peMachineType;
1c79356b
A
264}
265
0a7de745
A
266void
267IOPlatformExpert::setBootROMType(long peBootROMType)
1c79356b 268{
0a7de745 269 _peBootROMType = peBootROMType;
1c79356b
A
270}
271
0a7de745
A
272void
273IOPlatformExpert::setChipSetType(long peChipSetType)
1c79356b 274{
0a7de745 275 _peChipSetType = peChipSetType;
1c79356b
A
276}
277
0a7de745
A
278void
279IOPlatformExpert::setMachineType(long peMachineType)
1c79356b 280{
0a7de745 281 _peMachineType = peMachineType;
1c79356b
A
282}
283
0a7de745
A
284bool
285IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
1c79356b 286{
0a7de745 287 return false;
1c79356b
A
288}
289
0a7de745
A
290bool
291IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
1c79356b 292{
0a7de745 293 return false;
1c79356b
A
294}
295
0a7de745
A
296OSString*
297IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
55e303ae 298{
0a7de745 299 return NULL;
55e303ae
A
300}
301
0a7de745
A
302IORangeAllocator *
303IOPlatformExpert::getPhysicalRangeAllocator(void)
1c79356b 304{
0a7de745
A
305 return OSDynamicCast(IORangeAllocator,
306 getProperty("Platform Memory Ranges"));
1c79356b
A
307}
308
cb323159 309int (*PE_halt_restart)(unsigned int type) = NULL;
1c79356b 310
0a7de745
A
311int
312IOPlatformExpert::haltRestart(unsigned int type)
1c79356b 313{
0a7de745
A
314 if (type == kPEPanicSync) {
315 return 0;
316 }
2d21ac55 317
0a7de745
A
318 if (type == kPEHangCPU) {
319 while (true) {
320 }
321 }
4452a7af 322
0a7de745
A
323 if (type == kPEUPSDelayHaltCPU) {
324 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
325 type = kPEHaltCPU;
326 }
2d21ac55 327
5ba3f43e 328#if !CONFIG_EMBEDDED
0a7de745
A
329 // On ARM kPEPanicRestartCPU is supported in the drivers
330 if (type == kPEPanicRestartCPU) {
331 type = kPERestartCPU;
332 }
5ba3f43e 333#endif
6d2010ae 334
0a7de745
A
335 if (PE_halt_restart) {
336 return (*PE_halt_restart)(type);
337 } else {
338 return -1;
339 }
1c79356b
A
340}
341
0a7de745
A
342void
343IOPlatformExpert::sleepKernel(void)
1c79356b
A
344{
345#if 0
0a7de745
A
346 long cnt;
347 boolean_t intState;
348
349 intState = ml_set_interrupts_enabled(false);
350
351 for (cnt = 0; cnt < 10000; cnt++) {
352 IODelay(1000);
353 }
354
355 ml_set_interrupts_enabled(intState);
1c79356b
A
356#else
357// PE_initialize_console(0, kPEDisableScreen);
0a7de745
A
358
359 IOCPUSleepKernel();
360
1c79356b
A
361// PE_initialize_console(0, kPEEnableScreen);
362#endif
363}
364
0a7de745
A
365long
366IOPlatformExpert::getGMTTimeOfDay(void)
1c79356b 367{
0a7de745 368 return 0;
1c79356b
A
369}
370
0a7de745
A
371void
372IOPlatformExpert::setGMTTimeOfDay(long secs)
1c79356b
A
373{
374}
375
376
0a7de745
A
377IOReturn
378IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
1c79356b 379{
0a7de745 380 return PE_current_console( consoleInfo);
1c79356b
A
381}
382
0a7de745
A
383IOReturn
384IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
385 unsigned int op)
1c79356b 386{
0a7de745 387 return PE_initialize_console( consoleInfo, op );
1c79356b
A
388}
389
0a7de745
A
390IOReturn
391IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
1c79356b 392{
0a7de745
A
393 IOLockLock(gIOInterruptControllersLock);
394
395 gIOInterruptControllers->setObject(name, interruptController);
396
397 IOLockWakeup(gIOInterruptControllersLock,
398 gIOInterruptControllers, /* one-thread */ false);
399
400 IOLockUnlock(gIOInterruptControllersLock);
9bccf70c 401
0a7de745 402 return kIOReturnSuccess;
1c79356b
A
403}
404
0a7de745
A
405IOReturn
406IOPlatformExpert::deregisterInterruptController(OSSymbol *name)
fe8ab488 407{
0a7de745
A
408 IOLockLock(gIOInterruptControllersLock);
409
410 gIOInterruptControllers->removeObject(name);
411
412 IOLockUnlock(gIOInterruptControllersLock);
413
414 return kIOReturnSuccess;
fe8ab488
A
415}
416
0a7de745
A
417IOInterruptController *
418IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
1c79356b 419{
0a7de745
A
420 OSObject *object;
421
422 IOLockLock(gIOInterruptControllersLock);
423 while (1) {
424 object = gIOInterruptControllers->getObject(name);
425
cb323159 426 if (object != NULL) {
0a7de745
A
427 break;
428 }
429
430 IOLockSleep(gIOInterruptControllersLock,
431 gIOInterruptControllers, THREAD_UNINT);
432 }
433
434 IOLockUnlock(gIOInterruptControllersLock);
435 return OSDynamicCast(IOInterruptController, object);
1c79356b
A
436}
437
438
0a7de745
A
439void
440IOPlatformExpert::setCPUInterruptProperties(IOService *service)
1c79356b 441{
0a7de745
A
442 IOCPUInterruptController *controller;
443
444 controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
445 if (controller) {
446 controller->setCPUInterruptProperties(service);
447 }
1c79356b
A
448}
449
0a7de745
A
450bool
451IOPlatformExpert::atInterruptLevel(void)
1c79356b 452{
0a7de745 453 return ml_at_interrupt_context();
1c79356b
A
454}
455
0a7de745
A
456bool
457IOPlatformExpert::platformAdjustService(IOService */*service*/)
1c79356b 458{
0a7de745 459 return true;
1c79356b
A
460}
461
0a7de745
A
462void
463IOPlatformExpert::getUTCTimeOfDay(clock_sec_t * secs, clock_nsec_t * nsecs)
fe8ab488 464{
0a7de745
A
465 *secs = getGMTTimeOfDay();
466 *nsecs = 0;
fe8ab488
A
467}
468
0a7de745
A
469void
470IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs, __unused clock_nsec_t nsecs)
fe8ab488 471{
0a7de745 472 setGMTTimeOfDay(secs);
fe8ab488
A
473}
474
1c79356b
A
475
476//*********************************************************************************
477// PMLog
478//
479//*********************************************************************************
480
0a7de745
A
481void
482IOPlatformExpert::
91447636 483PMLog(const char *who, unsigned long event,
0a7de745 484 unsigned long param1, unsigned long param2)
1c79356b 485{
b0d623f7
A
486 clock_sec_t nows;
487 clock_usec_t nowus;
91447636
A
488 clock_get_system_microtime(&nows, &nowus);
489 nowus += (nows % 1000) * 1000000;
490
0a7de745
A
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
1c79356b
A
494}
495
496
497//*********************************************************************************
498// PMInstantiatePowerDomains
499//
500// In this vanilla implementation, a Root Power Domain is instantiated.
501// All other objects which register will be children of this Root.
0a7de745 502// Where this is inappropriate, PMInstantiatePowerDomains is overridden
1c79356b
A
503// in a platform-specific subclass.
504//*********************************************************************************
505
0a7de745
A
506void
507IOPlatformExpert::PMInstantiatePowerDomains( void )
1c79356b 508{
0a7de745
A
509 root = new IOPMrootDomain;
510 root->init();
511 root->attach(this);
512 root->start(this);
1c79356b
A
513}
514
515
516//*********************************************************************************
517// PMRegisterDevice
518//
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//*********************************************************************************
522
0a7de745
A
523void
524IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
1c79356b 525{
0a7de745 526 root->addPowerChild( theDevice );
1c79356b
A
527}
528
529//*********************************************************************************
530// hasPMFeature
531//
532//*********************************************************************************
533
0a7de745
A
534bool
535IOPlatformExpert::hasPMFeature(unsigned long featureMask)
1c79356b 536{
0a7de745 537 return (_pePMFeatures & featureMask) != 0;
1c79356b
A
538}
539
540//*********************************************************************************
541// hasPrivPMFeature
542//
543//*********************************************************************************
544
0a7de745
A
545bool
546IOPlatformExpert::hasPrivPMFeature(unsigned long privFeatureMask)
1c79356b 547{
0a7de745 548 return (_pePrivPMFeatures & privFeatureMask) != 0;
1c79356b
A
549}
550
551//*********************************************************************************
552// numBatteriesSupported
553//
554//*********************************************************************************
555
0a7de745
A
556int
557IOPlatformExpert::numBatteriesSupported(void)
1c79356b 558{
0a7de745 559 return _peNumBatteriesSupported;
1c79356b
A
560}
561
562//*********************************************************************************
563// CheckSubTree
564//
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//*********************************************************************************
572
0a7de745
A
573bool
574IOPlatformExpert::CheckSubTree(OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
575{
576 unsigned int i;
577 unsigned int numPowerTreeNodes;
578 OSDictionary * entry;
579 OSDictionary * matchingDictionary;
580 OSDictionary * providerDictionary;
581 OSDictionary * deviceDictionary;
582 OSDictionary * nubDictionary;
583 OSArray * children;
584 bool nodeFound = false;
585 bool continueSearch = false;
586 bool deviceMatch = false;
587 bool providerMatch = false;
588 bool multiParentMatch = false;
589
590 if ((NULL == theDevice) || (NULL == inSubTree)) {
591 return false;
592 }
1c79356b 593
0a7de745
A
594 numPowerTreeNodes = inSubTree->getCount();
595
596 // iterate through the power tree to find a home for this device
597
598 for (i = 0; i < numPowerTreeNodes; i++) {
599 entry = (OSDictionary *) inSubTree->getObject(i);
600
601 matchingDictionary = (OSDictionary *) entry->getObject("device");
602 providerDictionary = (OSDictionary *) entry->getObject("provider");
603
604 deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
605 if (matchingDictionary) {
606 deviceMatch = false;
607 if (NULL != (deviceDictionary = theDevice->dictionaryWithProperties())) {
608 deviceMatch = deviceDictionary->isEqualTo( matchingDictionary, matchingDictionary );
609 deviceDictionary->release();
610 }
611 }
612
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();
619 }
620 }
621
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;
627 }
628 }
629
630 nodeFound = (deviceMatch && providerMatch && multiParentMatch);
631
632 // if the power tree specifies a provider dictionary but theNub is
633 // NULL then we cannot match with this entry.
634
635 if (theNub == NULL && providerDictionary != NULL) {
636 nodeFound = false;
637 }
638
639 // if this node is THE ONE...then register the device
640
641 if (nodeFound) {
642 if (RegisterServiceInTree(theDevice, entry, theParent, theNub)) {
643 if (kIOLogPower & gIOKitDebug) {
644 IOLog("PMRegisterDevice/CheckSubTree - service registered!\n");
645 }
646
647 numInstancesRegistered++;
648
649 // determine if we need to search for additional nodes for this item
650 multipleParentKeyValue = (OSNumber *) entry->getObject("multiple-parent");
651 } else {
652 nodeFound = false;
653 }
654 }
655
656 continueSearch = ((false == nodeFound) || (NULL != multipleParentKeyValue));
657
658 if (continueSearch && (NULL != (children = (OSArray *) entry->getObject("children")))) {
659 nodeFound = CheckSubTree( children, theNub, theDevice, entry );
660 continueSearch = ((false == nodeFound) || (NULL != multipleParentKeyValue));
661 }
662
663 if (false == continueSearch) {
664 break;
665 }
666 }
1c79356b 667
0a7de745 668 return nodeFound;
1c79356b
A
669}
670
671//*********************************************************************************
672// RegisterServiceInTree
673//
674// Register a device at the specified node of our power tree.
675//*********************************************************************************
676
0a7de745
A
677bool
678IOPlatformExpert::RegisterServiceInTree(IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
679{
680 IOService * aService;
681 bool registered = false;
682 OSArray * children;
683 unsigned int numChildren;
684 OSDictionary * child;
685
686 // make sure someone is not already registered here
687
688 if (NULL == theTreeNode->getObject("service")) {
689 if (theTreeNode->setObject("service", OSDynamicCast( OSObject, theService))) {
690 // 1. CHILDREN ------------------
691
692 // we registered the node in the tree...now if the node has children
693 // registered we must tell this service to add them.
694
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);
701 }
702 }
703 }
704 }
705
706 // 2. PARENT --------------------
707
708 // also we must notify the parent of this node (if a registered service
709 // exists there) of a new child.
710
711 if (theTreeParentNode) {
712 if (NULL != (aService = (IOService *) theTreeParentNode->getObject("service"))) {
713 if (aService != theProvider) {
714 aService->addPowerChild(theService);
715 }
716 }
717 }
718
719 registered = true;
720 }
721 }
1c79356b 722
0a7de745 723 return registered;
1c79356b
A
724}
725
726//*********************************************************************************
727// printDictionaryKeys
728//
729// Print the keys for the given dictionary and selected contents.
730//*********************************************************************************
0a7de745
A
731void
732printDictionaryKeys(OSDictionary * inDictionary, char * inMsg)
1c79356b 733{
0a7de745
A
734 OSCollectionIterator * mcoll = OSCollectionIterator::withCollection(inDictionary);
735 OSSymbol * mkey;
736 OSString * ioClass;
737 unsigned int i = 0;
1c79356b 738
0a7de745 739 mcoll->reset();
1c79356b 740
0a7de745 741 mkey = OSDynamicCast(OSSymbol, mcoll->getNextObject());
1c79356b 742
0a7de745
A
743 while (mkey) {
744 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
1c79356b 745
0a7de745 746 // if this is the IOClass key, print it's contents
1c79356b 747
0a7de745
A
748 if (mkey->isEqualTo("IOClass")) {
749 ioClass = (OSString *) inDictionary->getObject("IOClass");
750 if (ioClass) {
751 IOLog("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy());
752 }
753 }
1c79356b 754
0a7de745 755 // if this is an IOProviderClass key print it
1c79356b 756
0a7de745
A
757 if (mkey->isEqualTo("IOProviderClass")) {
758 ioClass = (OSString *) inDictionary->getObject("IOProviderClass");
759 if (ioClass) {
760 IOLog("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy());
761 }
762 }
1c79356b 763
0a7de745
A
764 // also print IONameMatch keys
765 if (mkey->isEqualTo("IONameMatch")) {
766 ioClass = (OSString *) inDictionary->getObject("IONameMatch");
767 if (ioClass) {
768 IOLog("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy());
769 }
770 }
1c79356b 771
0a7de745 772 // also print IONameMatched keys
1c79356b 773
0a7de745
A
774 if (mkey->isEqualTo("IONameMatched")) {
775 ioClass = (OSString *) inDictionary->getObject("IONameMatched");
776 if (ioClass) {
777 IOLog("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy());
778 }
779 }
1c79356b
A
780
781#if 0
0a7de745
A
782 // print clock-id
783
784 if (mkey->isEqualTo("AAPL,clock-id")) {
785 char * cstr;
786 cstr = getCStringForObject(inDictionary->getObject("AAPL,clock-id"));
787 if (cstr) {
788 kprintf(" ===> AAPL,clock-id is %s\n", cstr );
789 }
790 }
1c79356b
A
791#endif
792
0a7de745 793 // print name
1c79356b 794
0a7de745
A
795 if (mkey->isEqualTo("name")) {
796 char nameStr[64];
797 nameStr[0] = 0;
798 getCStringForObject(inDictionary->getObject("name"), nameStr,
799 sizeof(nameStr));
800 if (strlen(nameStr) > 0) {
801 IOLog("%s name is %s\n", inMsg, nameStr);
802 }
803 }
1c79356b 804
0a7de745 805 mkey = (OSSymbol *) mcoll->getNextObject();
1c79356b 806
0a7de745
A
807 i++;
808 }
1c79356b 809
0a7de745 810 mcoll->release();
1c79356b
A
811}
812
2d21ac55
A
813static void
814getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen)
1c79356b 815{
0a7de745
A
816 char * buffer;
817 unsigned int len, i;
1c79356b 818
0a7de745
A
819 if ((NULL == inObj) || (NULL == outStr)) {
820 return;
821 }
1c79356b 822
0a7de745
A
823 char * objString = (char *) (inObj->getMetaClass())->getClassName();
824
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];
834 }
835 outStr[len] = 0;
836 }
837 }
1c79356b
A
838}
839
0c530ab8 840/* IOShutdownNotificationsTimedOut
fa4905b1
A
841 * - Called from a timer installed by PEHaltRestart
842 */
cb323159
A
843#ifdef CONFIG_EMBEDDED
844__abortlike
845#endif
0a7de745
A
846static void
847IOShutdownNotificationsTimedOut(
848 thread_call_param_t p0,
849 thread_call_param_t p1)
fa4905b1 850{
5ba3f43e 851#ifdef CONFIG_EMBEDDED
0a7de745
A
852 /* 30 seconds has elapsed - panic */
853 panic("Halt/Restart Timed Out");
5ba3f43e
A
854
855#else /* ! CONFIG_EMBEDDED */
0a7de745
A
856 int type = (int)(long)p0;
857 uint32_t timeout = (uint32_t)(uintptr_t)p1;
858
859 IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain();
860 if (pmRootDomain) {
861 if ((PEGetCoprocessorVersion() >= kCoprocessorVersion2) || pmRootDomain->checkShutdownTimeout()) {
862 pmRootDomain->panicWithShutdownLog(timeout * 1000);
863 }
864 }
865
866 /* 30 seconds has elapsed - resume shutdown */
867 if (gIOPlatform) {
868 gIOPlatform->haltRestart(type);
869 }
5ba3f43e 870#endif /* CONFIG_EMBEDDED */
fa4905b1
A
871}
872
873
1c79356b 874extern "C" {
1c79356b
A
875/*
876 * Callouts from BSD for machine name & model
0a7de745
A
877 */
878
879boolean_t
880PEGetMachineName( char * name, int maxLength )
881{
882 if (gIOPlatform) {
883 return gIOPlatform->getMachineName( name, maxLength );
884 } else {
885 return false;
886 }
887}
888
889boolean_t
890PEGetModelName( char * name, int maxLength )
891{
892 if (gIOPlatform) {
893 return gIOPlatform->getModelName( name, maxLength );
894 } else {
895 return false;
896 }
897}
898
899int
900PEGetPlatformEpoch(void)
901{
902 if (gIOPlatform) {
903 return gIOPlatform->getBootROMType();
904 } else {
905 return -1;
906 }
907}
908
909int
910PEHaltRestart(unsigned int type)
911{
912 IOPMrootDomain *pmRootDomain;
913 AbsoluteTime deadline;
914 thread_call_t shutdown_hang;
915 IORegistryEntry *node;
916 OSData *data;
917 uint32_t timeout = kShutdownTimeout;
918 static boolean_t panic_begin_called = FALSE;
919
920 if (type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU) {
cb323159
A
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.
923 */
924 if (panic_begin_called) {
925 goto skip_to_haltRestart;
926 }
927
0a7de745
A
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()
932 */
933
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.
938 */
5ba3f43e
A
939#if CONFIG_EMBEDDED
940#define RESTART_NODE_PATH "/defaults"
941#else
fe8ab488 942#define RESTART_NODE_PATH "/chosen"
5ba3f43e 943#endif
0a7de745
A
944 node = IORegistryEntry::fromPath( RESTART_NODE_PATH, gIODTPlane );
945 if (node) {
946 data = OSDynamicCast( OSData, node->getProperty( "halt-restart-timeout" ));
947 if (data && data->getLength() == 4) {
948 timeout = *((uint32_t *) data->getBytesNoCopy());
949 }
950 }
951
cb323159
A
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;
957 }
958#endif
959
960 if (timeout) {
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 );
965 }
0a7de745
A
966
967 pmRootDomain->handlePlatformHaltRestart(type);
968 /* This notification should have few clients who all do
969 * their work synchronously.
970 *
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
974 * replies.
975 */
cb323159
A
976 } else if (type == kPEPanicRestartCPU || type == kPEPanicSync || type == kPEPanicRestartCPUNoPanicEndCallouts ||
977 type == kPEPanicRestartCPUNoCallouts) {
0a7de745
A
978 if (type == kPEPanicRestartCPU) {
979 // Notify any listeners that we're done collecting
980 // panic data before we call through to do the restart
a39ff7e2 981#if !CONFIG_EMBEDDED
0a7de745 982 if (coprocessor_cross_panic_enabled)
a39ff7e2 983#endif
0a7de745 984 IOCPURunPlatformPanicActions(kPEPanicEnd);
cb323159 985 }
0a7de745 986
cb323159 987 if ((type == kPEPanicRestartCPU) || (type == kPEPanicRestartCPUNoPanicEndCallouts)) {
0a7de745 988 // Callout to shutdown the disk driver once we've returned from the
cb323159
A
989 // kPEPanicEnd callbacks (if appropriate) and we know all coredumps
990 // on this system are complete).
0a7de745
A
991 IOCPURunPlatformPanicActions(kPEPanicDiskShutdown);
992 }
993
cb323159
A
994 if (type == kPEPanicRestartCPUNoPanicEndCallouts || type == kPEPanicRestartCPUNoCallouts) {
995 // Replace the wrapper type with the type drivers handle
996 type = kPEPanicRestartCPU;
997 }
998
0a7de745
A
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) {
cc8bc92a 1007#if !CONFIG_EMBEDDED
0a7de745 1008 if (coprocessor_cross_panic_enabled)
cc8bc92a 1009#endif
0a7de745
A
1010 IOCPURunPlatformPanicActions(type);
1011 } else if (type == kPEPanicBegin) {
cc8bc92a 1012#if !CONFIG_EMBEDDED
0a7de745 1013 if (coprocessor_cross_panic_enabled)
cc8bc92a 1014#endif
0a7de745
A
1015 {
1016 // Only call the kPEPanicBegin callout once
1017 if (!panic_begin_called) {
1018 panic_begin_called = TRUE;
1019 IOCPURunPlatformPanicActions(type);
1020 }
1021 }
1022 }
fa4905b1 1023
cb323159 1024skip_to_haltRestart:
0a7de745
A
1025 if (gIOPlatform) {
1026 return gIOPlatform->haltRestart(type);
1027 } else {
1028 return -1;
1029 }
1c79356b
A
1030}
1031
0a7de745
A
1032UInt32
1033PESavePanicInfo(UInt8 *buffer, UInt32 length)
9bccf70c 1034{
cb323159 1035 if (gIOPlatform != NULL) {
0a7de745
A
1036 return gIOPlatform->savePanicInfo(buffer, length);
1037 } else {
1038 return 0;
1039 }
9bccf70c
A
1040}
1041
0a7de745
A
1042void
1043PESavePanicInfoAction(void *buffer, UInt32 offset, UInt32 length)
5ba3f43e 1044{
5c9f4661 1045 IOCPURunPlatformPanicSyncAction(buffer, offset, length);
5ba3f43e
A
1046 return;
1047}
6d2010ae
A
1048
1049
0a7de745
A
1050inline static int
1051init_gIOOptionsEntry(void)
6d2010ae 1052{
0a7de745
A
1053 IORegistryEntry *entry;
1054 void *nvram_entry;
1055 volatile void **options;
1056 int ret = -1;
6d2010ae 1057
0a7de745
A
1058 if (gIOOptionsEntry) {
1059 return 0;
1060 }
6d2010ae 1061
0a7de745
A
1062 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1063 if (!entry) {
1064 return -1;
1065 }
6d2010ae 1066
0a7de745
A
1067 nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
1068 if (!nvram_entry) {
1069 goto release;
1070 }
6d2010ae 1071
0a7de745
A
1072 options = (volatile void **) &gIOOptionsEntry;
1073 if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
1074 ret = 0;
1075 goto release;
1076 }
6d2010ae 1077
0a7de745 1078 return 0;
6d2010ae
A
1079
1080release:
0a7de745
A
1081 entry->release();
1082 return ret;
6d2010ae
A
1083}
1084
1085/* pass in a NULL value if you just want to figure out the len */
0a7de745
A
1086boolean_t
1087PEReadNVRAMProperty(const char *symbol, void *value,
1088 unsigned int *len)
6d2010ae 1089{
0a7de745
A
1090 OSObject *obj;
1091 OSData *data;
1092 unsigned int vlen;
6d2010ae 1093
0a7de745
A
1094 if (!symbol || !len) {
1095 goto err;
1096 }
6d2010ae 1097
0a7de745
A
1098 if (init_gIOOptionsEntry() < 0) {
1099 goto err;
1100 }
6d2010ae 1101
0a7de745
A
1102 vlen = *len;
1103 *len = 0;
6d2010ae 1104
0a7de745
A
1105 obj = gIOOptionsEntry->getProperty(symbol);
1106 if (!obj) {
1107 goto err;
1108 }
6d2010ae 1109
0a7de745
A
1110 /* convert to data */
1111 data = OSDynamicCast(OSData, obj);
1112 if (!data) {
1113 goto err;
1114 }
6d2010ae 1115
0a7de745
A
1116 *len = data->getLength();
1117 vlen = min(vlen, *len);
1118 if (value && vlen) {
1119 memcpy((void *) value, data->getBytesNoCopy(), vlen);
1120 }
6d2010ae 1121
0a7de745 1122 return TRUE;
6d2010ae
A
1123
1124err:
0a7de745 1125 return FALSE;
6d2010ae
A
1126}
1127
3e170ce0
A
1128boolean_t
1129PEWriteNVRAMBooleanProperty(const char *symbol, boolean_t value)
1130{
1131 const OSSymbol *sym = NULL;
1132 OSBoolean *data = NULL;
1133 bool ret = false;
1134
1135 if (symbol == NULL) {
1136 goto exit;
1137 }
1138
1139 if (init_gIOOptionsEntry() < 0) {
1140 goto exit;
1141 }
1142
1143 if ((sym = OSSymbol::withCStringNoCopy(symbol)) == NULL) {
1144 goto exit;
1145 }
1146
1147 data = value ? kOSBooleanTrue : kOSBooleanFalse;
1148 ret = gIOOptionsEntry->setProperty(sym, data);
1149
1150 sym->release();
1151
1152 /* success, force the NVRAM to flush writes */
1153 if (ret == true) {
1154 gIOOptionsEntry->sync();
1155 }
1156
1157exit:
1158 return ret;
1159}
6d2010ae 1160
0a7de745
A
1161static boolean_t
1162PEWriteNVRAMPropertyInternal(const char *symbol, boolean_t copySymbol, const void *value,
1163 const unsigned int len)
6d2010ae 1164{
0a7de745
A
1165 const OSSymbol *sym;
1166 OSData *data;
1167 bool ret = false;
6d2010ae 1168
0a7de745
A
1169 if (!symbol || !value || !len) {
1170 goto err;
1171 }
6d2010ae 1172
0a7de745
A
1173 if (init_gIOOptionsEntry() < 0) {
1174 goto err;
1175 }
6d2010ae 1176
0a7de745
A
1177 if (copySymbol == TRUE) {
1178 sym = OSSymbol::withCString(symbol);
1179 } else {
1180 sym = OSSymbol::withCStringNoCopy(symbol);
1181 }
6d2010ae 1182
0a7de745
A
1183 if (!sym) {
1184 goto err;
1185 }
1186
1187 data = OSData::withBytes((void *) value, len);
1188 if (!data) {
1189 goto sym_done;
1190 }
6d2010ae 1191
0a7de745
A
1192 ret = gIOOptionsEntry->setProperty(sym, data);
1193 data->release();
6d2010ae
A
1194
1195sym_done:
0a7de745 1196 sym->release();
6d2010ae 1197
0a7de745
A
1198 if (ret == true) {
1199 gIOOptionsEntry->sync();
1200 return TRUE;
1201 }
6d2010ae
A
1202
1203err:
0a7de745 1204 return FALSE;
6d2010ae
A
1205}
1206
0a7de745
A
1207boolean_t
1208PEWriteNVRAMProperty(const char *symbol, const void *value,
1209 const unsigned int len)
1210{
1211 return PEWriteNVRAMPropertyInternal(symbol, FALSE, value, len);
1212}
6d2010ae 1213
0a7de745
A
1214boolean_t
1215PEWriteNVRAMPropertyWithCopy(const char *symbol, const void *value,
1216 const unsigned int len)
39236c6e 1217{
0a7de745
A
1218 return PEWriteNVRAMPropertyInternal(symbol, TRUE, value, len);
1219}
39236c6e 1220
0a7de745
A
1221boolean_t
1222PERemoveNVRAMProperty(const char *symbol)
1223{
1224 const OSSymbol *sym;
39236c6e 1225
0a7de745
A
1226 if (!symbol) {
1227 goto err;
1228 }
39236c6e 1229
0a7de745
A
1230 if (init_gIOOptionsEntry() < 0) {
1231 goto err;
1232 }
39236c6e 1233
0a7de745
A
1234 sym = OSSymbol::withCStringNoCopy(symbol);
1235 if (!sym) {
1236 goto err;
1237 }
39236c6e 1238
0a7de745 1239 gIOOptionsEntry->removeProperty(sym);
39236c6e 1240
0a7de745 1241 sym->release();
39236c6e 1242
0a7de745
A
1243 gIOOptionsEntry->sync();
1244 return TRUE;
39236c6e 1245
0a7de745
A
1246err:
1247 return FALSE;
39236c6e
A
1248}
1249
0a7de745
A
1250long
1251PEGetGMTTimeOfDay(void)
1c79356b 1252{
0a7de745
A
1253 clock_sec_t secs;
1254 clock_usec_t usecs;
0c530ab8 1255
0a7de745
A
1256 PEGetUTCTimeOfDay(&secs, &usecs);
1257 return secs;
1c79356b
A
1258}
1259
0a7de745
A
1260void
1261PESetGMTTimeOfDay(long secs)
1c79356b 1262{
0a7de745 1263 PESetUTCTimeOfDay(secs, 0);
fe8ab488
A
1264}
1265
0a7de745
A
1266void
1267PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs)
fe8ab488 1268{
0a7de745 1269 clock_nsec_t nsecs = 0;
fe8ab488 1270
0a7de745
A
1271 *secs = 0;
1272 if (gIOPlatform) {
1273 gIOPlatform->getUTCTimeOfDay(secs, &nsecs);
1274 }
fe8ab488 1275
0a7de745
A
1276 assert(nsecs < NSEC_PER_SEC);
1277 *usecs = nsecs / NSEC_PER_USEC;
fe8ab488
A
1278}
1279
0a7de745
A
1280void
1281PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs)
fe8ab488 1282{
0a7de745
A
1283 assert(usecs < USEC_PER_SEC);
1284 if (gIOPlatform) {
1285 gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC);
1286 }
1c79356b
A
1287}
1288
0a7de745
A
1289coprocessor_type_t
1290PEGetCoprocessorVersion( void )
5c9f4661 1291{
0a7de745 1292 coprocessor_type_t coprocessor_version = kCoprocessorVersionNone;
5c9f4661 1293#if !CONFIG_EMBEDDED
0a7de745
A
1294 IORegistryEntry *platform_entry = NULL;
1295 OSData *coprocessor_version_obj = NULL;
1296
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());
1302 }
1303 platform_entry->release();
1304 }
5c9f4661 1305#endif
0a7de745 1306 return coprocessor_version;
5c9f4661 1307}
1c79356b
A
1308} /* extern "C" */
1309
0a7de745
A
1310void
1311IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
1c79356b 1312{
0a7de745
A
1313 OSData * data;
1314 IORegistryEntry * entry;
cb323159 1315 OSString * string = NULL;
0a7de745 1316 uuid_string_t uuid;
2d21ac55 1317
5ba3f43e 1318#if CONFIG_EMBEDDED
0a7de745
A
1319 entry = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
1320 if (entry) {
1321 OSData * data1;
1322
1323 data1 = OSDynamicCast( OSData, entry->getProperty( "unique-chip-id" ));
1324 if (data1 && data1->getLength() == 8) {
1325 OSData * data2;
1326
1327 data2 = OSDynamicCast( OSData, entry->getProperty( "chip-id" ));
1328 if (data2 && data2->getLength() == 4) {
1329 SHA1_CTX context;
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 };
1332
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 );
1338
1339 digest[6] = (digest[6] & 0x0F) | 0x50;
1340 digest[8] = (digest[8] & 0x3F) | 0x80;
1341
1342 uuid_unparse( digest, uuid );
1343 string = OSString::withCString( uuid );
1344 }
1345 }
1346
1347 entry->release();
1348 }
cb323159
A
1349#endif /* CONFIG_EMBEDDED */
1350
1351#if defined(XNU_TARGET_OS_OSX)
0a7de745 1352 /*
cb323159 1353 * If we have panic debugging enabled and the bridgeOS panic SoC watchdog is enabled,
0a7de745
A
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.
1356 */
1357 if (panicDebugging) {
1358 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1359 if (entry) {
cb323159 1360 data = OSDynamicCast( OSData, entry->getProperty( APPLE_VENDOR_VARIABLE_GUID":BridgeOSPanicWatchdogEnabled" ));
0a7de745 1361 if (data && (data->getLength() == sizeof(UInt8))) {
cb323159 1362 UInt8 *panicWatchdogEnabled = (UInt8 *) data->getBytesNoCopy();
0a7de745 1363 UInt32 debug_flags = 0;
cb323159 1364 if (*panicWatchdogEnabled || (PE_i_can_has_debugger(&debug_flags) &&
0a7de745
A
1365 (debug_flags & DB_DISABLE_CROSS_PANIC))) {
1366 coprocessor_cross_panic_enabled = FALSE;
1367 }
1368 }
1369 entry->release();
1370 }
1371 }
1372
1373 entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
1374 if (entry) {
1375 data = OSDynamicCast( OSData, entry->getProperty( "system-id" ));
1376 if (data && data->getLength() == 16) {
1377 SHA1_CTX context;
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 };
4a3eedf9 1380
0a7de745
A
1381 SHA1Init( &context );
1382 SHA1Update( &context, space, sizeof(space));
1383 SHA1Update( &context, data->getBytesNoCopy(), data->getLength());
1384 SHA1Final( digest, &context );
4a3eedf9 1385
0a7de745
A
1386 digest[6] = (digest[6] & 0x0F) | 0x50;
1387 digest[8] = (digest[8] & 0x3F) | 0x80;
4a3eedf9 1388
0a7de745
A
1389 uuid_unparse( digest, uuid );
1390 string = OSString::withCString( uuid );
1391 }
2d21ac55 1392
0a7de745
A
1393 entry->release();
1394 }
cb323159 1395#endif /* defined(XNU_TARGET_OS_OSX) */
0a7de745 1396
cb323159 1397 if (string == NULL) {
0a7de745
A
1398 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1399 if (entry) {
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 );
1404 }
1405
1406 entry->release();
1407 }
1408 }
1409
1410 if (string) {
1411 getProvider()->setProperty( kIOPlatformUUIDKey, string );
1412 publishResource( kIOPlatformUUIDKey, string );
1413
1414 string->release();
1415 }
2d21ac55 1416
0a7de745 1417 publishResource("IONVRAM");
1c79356b
A
1418}
1419
0a7de745
A
1420IOReturn
1421IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
1422 bool waitForFunction,
1423 void *param1, void *param2,
1424 void *param3, void *param4)
1c79356b 1425{
0a7de745
A
1426 IOService *service, *_resources;
1427
cb323159
A
1428 if (functionName == gIOPlatformQuiesceActionKey ||
1429 functionName == gIOPlatformActiveActionKey) {
1430 /*
1431 * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction
1432 * must consume that event themselves, without passing it up to super/IOPlatformExpert.
1433 */
1434 if (gEnforceQuiesceSafety) {
1435 panic("Class %s passed the quiesce/active action to IOPlatformExpert",
1436 getMetaClass()->getClassName());
1437 }
1438 }
1439
0a7de745
A
1440 if (waitForFunction) {
1441 _resources = waitForService(resourceMatching(functionName));
1442 } else {
1443 _resources = getResourceService();
1444 }
cb323159 1445 if (_resources == NULL) {
0a7de745
A
1446 return kIOReturnUnsupported;
1447 }
1448
1449 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
cb323159 1450 if (service == NULL) {
0a7de745
A
1451 return kIOReturnUnsupported;
1452 }
1453
1454 return service->callPlatformFunction(functionName, waitForFunction,
1455 param1, param2, param3, param4);
1c79356b
A
1456}
1457
0a7de745
A
1458IOByteCount
1459IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
9bccf70c 1460{
0a7de745 1461 return 0;
9bccf70c 1462}
1c79356b
A
1463
1464/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1465
1466#undef super
1467#define super IOPlatformExpert
1468
1469OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
1470
0a7de745
A
1471OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
1472OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
1473OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
1474OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
1475OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
1476OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
1477OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
1478OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
1c79356b
A
1479
1480/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1481
0a7de745
A
1482IOService *
1483IODTPlatformExpert::probe( IOService * provider,
1484 SInt32 * score )
1c79356b 1485{
0a7de745 1486 if (!super::probe( provider, score)) {
cb323159 1487 return NULL;
0a7de745 1488 }
1c79356b 1489
0a7de745
A
1490 // check machine types
1491 if (!provider->compareNames( getProperty( gIONameMatchKey ))) {
cb323159 1492 return NULL;
0a7de745 1493 }
1c79356b 1494
0a7de745 1495 return this;
1c79356b
A
1496}
1497
0a7de745
A
1498bool
1499IODTPlatformExpert::configure( IOService * provider )
1c79356b 1500{
0a7de745
A
1501 if (!super::configure( provider)) {
1502 return false;
1503 }
1c79356b 1504
0a7de745 1505 processTopLevel( provider );
1c79356b 1506
0a7de745 1507 return true;
1c79356b
A
1508}
1509
0a7de745
A
1510IOService *
1511IODTPlatformExpert::createNub( IORegistryEntry * from )
1c79356b 1512{
0a7de745 1513 IOService * nub;
1c79356b 1514
0a7de745
A
1515 nub = new IOPlatformDevice;
1516 if (nub) {
1517 if (!nub->init( from, gIODTPlane )) {
1518 nub->free();
cb323159 1519 nub = NULL;
0a7de745 1520 }
1c79356b 1521 }
0a7de745 1522 return nub;
1c79356b
A
1523}
1524
0a7de745
A
1525bool
1526IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
1527{
1528 IORegistryEntry * next;
1529 IOService * nub;
1530 bool ok = true;
1531
1532 if (iter) {
1533 while ((next = (IORegistryEntry *) iter->getNextObject())) {
cb323159 1534 if (NULL == (nub = createNub( next ))) {
0a7de745
A
1535 continue;
1536 }
1537
1538 nub->attach( parent );
1539 nub->registerService();
1540 }
1541 iter->release();
1542 }
1c79356b 1543
0a7de745 1544 return ok;
1c79356b
A
1545}
1546
0a7de745
A
1547void
1548IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
1c79356b 1549{
0a7de745
A
1550 OSIterator * kids;
1551 IORegistryEntry * next;
1552 IORegistryEntry * cpus;
1553 IORegistryEntry * options;
1c79356b 1554
0a7de745
A
1555 // infanticide
1556 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList());
1557 if (kids) {
1558 while ((next = (IORegistryEntry *)kids->getNextObject())) {
1559 next->detachAll( gIODTPlane);
1560 }
1561 kids->release();
1c79356b 1562 }
1c79356b 1563
0a7de745
A
1564 // Publish an IODTNVRAM class on /options.
1565 options = rootEntry->childFromPath("options", gIODTPlane);
1566 if (options) {
1567 dtNVRAM = new IODTNVRAM;
1568 if (dtNVRAM) {
1569 if (!dtNVRAM->init(options, gIODTPlane)) {
1570 dtNVRAM->release();
cb323159 1571 dtNVRAM = NULL;
0a7de745
A
1572 } else {
1573 dtNVRAM->attach(this);
1574 dtNVRAM->registerService();
1575 options->release();
1576 }
1577 }
1c79356b 1578 }
1c79356b 1579
0a7de745
A
1580 // Publish the cpus.
1581 cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
1582 if (cpus) {
cb323159 1583 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, NULL));
0a7de745
A
1584 cpus->release();
1585 }
1c79356b 1586
0a7de745
A
1587 // publish top level, minus excludeList
1588 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
1c79356b
A
1589}
1590
0a7de745
A
1591IOReturn
1592IODTPlatformExpert::getNubResources( IOService * nub )
1c79356b 1593{
0a7de745
A
1594 if (nub->getDeviceMemory()) {
1595 return kIOReturnSuccess;
1596 }
1c79356b 1597
cb323159 1598 IODTResolveAddressing( nub, "reg", NULL);
1c79356b 1599
0a7de745 1600 return kIOReturnSuccess;
1c79356b
A
1601}
1602
0a7de745
A
1603bool
1604IODTPlatformExpert::compareNubName( const IOService * nub,
1605 OSString * name, OSString ** matched ) const
1c79356b 1606{
0a7de745
A
1607 return IODTCompareNubName( nub, name, matched )
1608 || super::compareNubName( nub, name, matched);
1c79356b
A
1609}
1610
0a7de745
A
1611bool
1612IODTPlatformExpert::getModelName( char * name, int maxLength )
1613{
1614 OSData * prop;
1615 const char * str;
1616 int len;
1617 char c;
1618 bool ok = false;
1619
1620 maxLength--;
1621
1622 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
1623 if (prop) {
1624 str = (const char *) prop->getBytesNoCopy();
1625
1626 if (0 == strncmp( str, "AAPL,", strlen( "AAPL," ))) {
1627 str += strlen( "AAPL," );
1628 }
1629
1630 len = 0;
1631 while ((c = *str++)) {
1632 if ((c == '/') || (c == ' ')) {
1633 c = '-';
1634 }
1635
1636 name[len++] = c;
1637 if (len >= maxLength) {
1638 break;
1639 }
1640 }
1641
1642 name[len] = 0;
1643 ok = true;
1c79356b 1644 }
0a7de745 1645 return ok;
1c79356b
A
1646}
1647
0a7de745
A
1648bool
1649IODTPlatformExpert::getMachineName( char * name, int maxLength )
1c79356b 1650{
0a7de745
A
1651 OSData * prop;
1652 bool ok = false;
1c79356b 1653
0a7de745
A
1654 maxLength--;
1655 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
cb323159 1656 ok = (NULL != prop);
1c79356b 1657
0a7de745
A
1658 if (ok) {
1659 strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
1660 }
1c79356b 1661
0a7de745 1662 return ok;
1c79356b
A
1663}
1664
1665/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1666
0a7de745
A
1667void
1668IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
1c79356b 1669{
0a7de745
A
1670 if (dtNVRAM) {
1671 dtNVRAM->registerNVRAMController(nvram);
1672 }
1673
1674 super::registerNVRAMController(nvram);
1c79356b
A
1675}
1676
0a7de745
A
1677int
1678IODTPlatformExpert::haltRestart(unsigned int type)
1c79356b 1679{
0a7de745
A
1680 if (dtNVRAM) {
1681 dtNVRAM->sync();
1682 }
1683
1684 return super::haltRestart(type);
1c79356b
A
1685}
1686
0a7de745
A
1687IOReturn
1688IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
1689 IOByteCount length)
1c79356b 1690{
0a7de745
A
1691 if (dtNVRAM) {
1692 return dtNVRAM->readXPRAM(offset, buffer, length);
1693 } else {
1694 return kIOReturnNotReady;
1695 }
1c79356b
A
1696}
1697
0a7de745
A
1698IOReturn
1699IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
1700 IOByteCount length)
1c79356b 1701{
0a7de745
A
1702 if (dtNVRAM) {
1703 return dtNVRAM->writeXPRAM(offset, buffer, length);
1704 } else {
1705 return kIOReturnNotReady;
1706 }
1c79356b
A
1707}
1708
0a7de745
A
1709IOReturn
1710IODTPlatformExpert::readNVRAMProperty(
1c79356b
A
1711 IORegistryEntry * entry,
1712 const OSSymbol ** name, OSData ** value )
1713{
0a7de745
A
1714 if (dtNVRAM) {
1715 return dtNVRAM->readNVRAMProperty(entry, name, value);
1716 } else {
1717 return kIOReturnNotReady;
1718 }
1c79356b
A
1719}
1720
0a7de745
A
1721IOReturn
1722IODTPlatformExpert::writeNVRAMProperty(
1c79356b
A
1723 IORegistryEntry * entry,
1724 const OSSymbol * name, OSData * value )
1725{
0a7de745
A
1726 if (dtNVRAM) {
1727 return dtNVRAM->writeNVRAMProperty(entry, name, value);
1728 } else {
1729 return kIOReturnNotReady;
1730 }
1c79356b
A
1731}
1732
0a7de745
A
1733OSDictionary *
1734IODTPlatformExpert::getNVRAMPartitions(void)
d52fe63f 1735{
0a7de745
A
1736 if (dtNVRAM) {
1737 return dtNVRAM->getNVRAMPartitions();
1738 } else {
cb323159 1739 return NULL;
0a7de745 1740 }
d52fe63f
A
1741}
1742
0a7de745
A
1743IOReturn
1744IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
1745 IOByteCount offset, UInt8 * buffer,
1746 IOByteCount length)
d52fe63f 1747{
0a7de745
A
1748 if (dtNVRAM) {
1749 return dtNVRAM->readNVRAMPartition(partitionID, offset,
1750 buffer, length);
1751 } else {
1752 return kIOReturnNotReady;
1753 }
d52fe63f
A
1754}
1755
0a7de745
A
1756IOReturn
1757IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
1758 IOByteCount offset, UInt8 * buffer,
1759 IOByteCount length)
d52fe63f 1760{
0a7de745
A
1761 if (dtNVRAM) {
1762 return dtNVRAM->writeNVRAMPartition(partitionID, offset,
1763 buffer, length);
1764 } else {
1765 return kIOReturnNotReady;
1766 }
d52fe63f
A
1767}
1768
0a7de745
A
1769IOByteCount
1770IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
9bccf70c 1771{
0a7de745
A
1772 IOByteCount lengthSaved = 0;
1773
1774 if (dtNVRAM) {
1775 lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
1776 }
1777
1778 if (lengthSaved == 0) {
1779 lengthSaved = super::savePanicInfo(buffer, length);
1780 }
d52fe63f 1781
0a7de745
A
1782 return lengthSaved;
1783}
1784
1785OSString*
1786IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
1787{
1788 UInt8* serialNumber;
1789 unsigned int serialNumberSize;
1790 unsigned short pos = 0;
1791 char* temp;
1792 char SerialNo[30];
1793
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] != '-') {
1801 pos++;
1802 }
1803
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);
1807 SerialNo[11] = '-';
1808 memcpy(&SerialNo[12], serialNumber + 3, 8);
1809 SerialNo[20] = 0;
1810 } else { // just a normal serial number
1811 memcpy(SerialNo, serialNumber + 13, 8);
1812 memcpy(&SerialNo[8], serialNumber, 3);
1813 SerialNo[11] = 0;
1814 }
1815 return OSString::withCString(SerialNo);
1816 }
1817 }
1818 return NULL;
55e303ae
A
1819}
1820
1821
1c79356b
A
1822/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1823
1824#undef super
1825#define super IOService
1826
1827OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
1828
0a7de745
A
1829OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
1830OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
1831OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
1832OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
1c79356b
A
1833
1834/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1835
0a7de745
A
1836bool
1837IOPlatformExpertDevice::compareName( OSString * name,
1838 OSString ** matched ) const
1c79356b 1839{
0a7de745 1840 return IODTCompareNubName( this, name, matched );
1c79356b
A
1841}
1842
1843bool
1844IOPlatformExpertDevice::initWithArgs(
0a7de745 1845 void * dtTop, void * p2, void * p3, void * p4 )
1c79356b 1846{
cb323159 1847 IORegistryEntry * dt = NULL;
0a7de745 1848 bool ok;
1c79356b 1849
0a7de745
A
1850 // dtTop may be zero on non- device tree systems
1851 if (dtTop && (dt = IODeviceTreeAlloc( dtTop ))) {
1852 ok = super::init( dt, gIODTPlane );
1853 } else {
1854 ok = super::init();
1855 }
1c79356b 1856
0a7de745
A
1857 if (!ok) {
1858 return false;
1859 }
1c79356b 1860
0a7de745
A
1861 workLoop = IOWorkLoop::workLoop();
1862 if (!workLoop) {
1863 return false;
1864 }
1c79356b 1865
0a7de745 1866 return true;
1c79356b
A
1867}
1868
0a7de745
A
1869IOWorkLoop *
1870IOPlatformExpertDevice::getWorkLoop() const
1c79356b 1871{
0a7de745 1872 return workLoop;
1c79356b
A
1873}
1874
0a7de745
A
1875IOReturn
1876IOPlatformExpertDevice::setProperties( OSObject * properties )
1c79356b 1877{
0a7de745 1878 return kIOReturnUnsupported;
1c79356b
A
1879}
1880
0a7de745
A
1881IOReturn
1882IOPlatformExpertDevice::newUserClient( task_t owningTask, void * securityID,
1883 UInt32 type, OSDictionary * properties,
1884 IOUserClient ** handler )
3e170ce0 1885{
0a7de745 1886 IOReturn err = kIOReturnSuccess;
cb323159
A
1887 IOUserClient * newConnect = NULL;
1888 IOUserClient * theConnect = NULL;
3e170ce0 1889
0a7de745
A
1890 switch (type) {
1891 case kIOKitDiagnosticsClientType:
1892 newConnect = IOKitDiagnosticsClient::withTask(owningTask);
1893 if (!newConnect) {
1894 err = kIOReturnNotPermitted;
1895 }
1896 break;
cb323159
A
1897 case kIOKitUserServerClientType:
1898 newConnect = IOUserServer::withTask(owningTask);
1899 if (!newConnect) {
1900 err = kIOReturnNotPermitted;
1901 }
1902 break;
0a7de745
A
1903 default:
1904 err = kIOReturnBadArgument;
1905 }
3e170ce0 1906
0a7de745
A
1907 if (newConnect) {
1908 if ((false == newConnect->attach(this))
1909 || (false == newConnect->start(this))) {
1910 newConnect->detach( this );
1911 newConnect->release();
1912 err = kIOReturnNotPermitted;
1913 } else {
1914 theConnect = newConnect;
1915 }
1916 }
3e170ce0 1917
0a7de745
A
1918 *handler = theConnect;
1919 return err;
3e170ce0
A
1920}
1921
0a7de745
A
1922void
1923IOPlatformExpertDevice::free()
0c530ab8 1924{
0a7de745
A
1925 if (workLoop) {
1926 workLoop->release();
1927 }
0c530ab8
A
1928}
1929
1c79356b
A
1930/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1931
1932#undef super
1933#define super IOService
1934
1935OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1936
0a7de745
A
1937OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1938OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1939OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1940OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1c79356b
A
1941
1942/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1943
0a7de745
A
1944bool
1945IOPlatformDevice::compareName( OSString * name,
1946 OSString ** matched ) const
1c79356b 1947{
0a7de745
A
1948 return ((IOPlatformExpert *)getProvider())->
1949 compareNubName( this, name, matched );
1c79356b
A
1950}
1951
0a7de745
A
1952IOService *
1953IOPlatformDevice::matchLocation( IOService * /* client */ )
1c79356b 1954{
0a7de745 1955 return this;
1c79356b
A
1956}
1957
0a7de745
A
1958IOReturn
1959IOPlatformDevice::getResources( void )
1c79356b 1960{
0a7de745 1961 return ((IOPlatformExpert *)getProvider())->getNubResources( this );
1c79356b
A
1962}
1963
1964/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1965
1966/*********************************************************************
1967* IOPanicPlatform class
1968*
1969* If no legitimate IOPlatformDevice matches, this one does and panics
1970* the kernel with a suitable message.
1971*********************************************************************/
1972
1973class IOPanicPlatform : IOPlatformExpert {
0a7de745 1974 OSDeclareDefaultStructors(IOPanicPlatform);
1c79356b
A
1975
1976public:
0a7de745 1977 bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
1c79356b
A
1978};
1979
1980
1981OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1982
1983
0a7de745
A
1984bool
1985IOPanicPlatform::start(IOService * provider)
1986{
1987 const char * platform_name = "(unknown platform name)";
1c79356b 1988
0a7de745
A
1989 if (provider) {
1990 platform_name = provider->getName();
1991 }
1c79356b 1992
0a7de745
A
1993 panic("Unable to find driver for this platform: \"%s\".\n",
1994 platform_name);
1c79356b 1995
0a7de745 1996 return false;
1c79356b 1997}