]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPlatformExpert.cpp
xnu-2422.90.20.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
1 /*
2 * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
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
43 #include <IOKit/system.h>
44
45 #include <libkern/c++/OSContainers.h>
46 #include <libkern/crypto/sha1.h>
47 #include <libkern/OSAtomic.h>
48
49 extern "C" {
50 #include <machine/machine_routines.h>
51 #include <pexpert/pexpert.h>
52 #include <uuid/uuid.h>
53 }
54
55 void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
56 static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen);
57
58 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59
60 #define super IOService
61
62 OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
63
64 OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
65
66 OSMetaClassDefineReservedUsed(IOPlatformExpert, 1);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert, 2);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert, 3);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert, 4);
70 OSMetaClassDefineReservedUnused(IOPlatformExpert, 5);
71 OSMetaClassDefineReservedUnused(IOPlatformExpert, 6);
72 OSMetaClassDefineReservedUnused(IOPlatformExpert, 7);
73 OSMetaClassDefineReservedUnused(IOPlatformExpert, 8);
74 OSMetaClassDefineReservedUnused(IOPlatformExpert, 9);
75 OSMetaClassDefineReservedUnused(IOPlatformExpert, 10);
76 OSMetaClassDefineReservedUnused(IOPlatformExpert, 11);
77
78 static IOPlatformExpert * gIOPlatform;
79 static OSDictionary * gIOInterruptControllers;
80 static IOLock * gIOInterruptControllersLock;
81 static IODTNVRAM *gIOOptionsEntry;
82
83 OSSymbol * gPlatformInterruptControllerName;
84
85 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
86
87 bool IOPlatformExpert::attach( IOService * provider )
88 {
89
90 if( !super::attach( provider ))
91 return( false);
92
93 return( true);
94 }
95
96 bool IOPlatformExpert::start( IOService * provider )
97 {
98 IORangeAllocator * physicalRanges;
99 OSData * busFrequency;
100 uint32_t debugFlags;
101
102 if (!super::start(provider))
103 return false;
104
105 // Override the mapper present flag is requested by boot arguments.
106 if (PE_parse_boot_argn("dart", &debugFlags, sizeof (debugFlags)) && (debugFlags == 0))
107 removeProperty(kIOPlatformMapperPresentKey);
108 if (PE_parse_boot_argn("-x", &debugFlags, sizeof (debugFlags)))
109 removeProperty(kIOPlatformMapperPresentKey);
110
111 // Register the presence or lack thereof a system
112 // PCI address mapper with the IOMapper class
113 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey));
114
115 gIOInterruptControllers = OSDictionary::withCapacity(1);
116 gIOInterruptControllersLock = IOLockAlloc();
117
118 // Correct the bus frequency in the device tree.
119 busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
120 provider->setProperty("clock-frequency", busFrequency);
121 busFrequency->release();
122
123 gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
124
125 physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16,
126 IORangeAllocator::kLocking);
127 assert(physicalRanges);
128 setProperty("Platform Memory Ranges", physicalRanges);
129
130 setPlatform( this );
131 gIOPlatform = this;
132
133 PMInstantiatePowerDomains();
134
135 // Parse the serial-number data and publish a user-readable string
136 OSData* mydata = (OSData*) (provider->getProperty("serial-number"));
137 if (mydata != NULL) {
138 OSString *serNoString = createSystemSerialNumberString(mydata);
139 if (serNoString != NULL) {
140 provider->setProperty(kIOPlatformSerialNumberKey, serNoString);
141 serNoString->release();
142 }
143 }
144
145 return( configure(provider) );
146 }
147
148 bool IOPlatformExpert::configure( IOService * provider )
149 {
150 OSSet * topLevel;
151 OSDictionary * dict;
152 IOService * nub;
153
154 topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
155
156 if( topLevel) {
157 while( (dict = OSDynamicCast( OSDictionary,
158 topLevel->getAnyObject()))) {
159 dict->retain();
160 topLevel->removeObject( dict );
161 nub = createNub( dict );
162 if( 0 == nub)
163 continue;
164 dict->release();
165 nub->attach( this );
166 nub->registerService();
167 }
168 }
169
170 return( true );
171 }
172
173 IOService * IOPlatformExpert::createNub( OSDictionary * from )
174 {
175 IOService * nub;
176
177 nub = new IOPlatformDevice;
178 if(nub) {
179 if( !nub->init( from )) {
180 nub->release();
181 nub = 0;
182 }
183 }
184 return( nub);
185 }
186
187 bool IOPlatformExpert::compareNubName( const IOService * nub,
188 OSString * name, OSString ** matched ) const
189 {
190 return( nub->IORegistryEntry::compareName( name, matched ));
191 }
192
193 IOReturn IOPlatformExpert::getNubResources( IOService * nub )
194 {
195 return( kIOReturnSuccess );
196 }
197
198 long IOPlatformExpert::getBootROMType(void)
199 {
200 return _peBootROMType;
201 }
202
203 long IOPlatformExpert::getChipSetType(void)
204 {
205 return _peChipSetType;
206 }
207
208 long IOPlatformExpert::getMachineType(void)
209 {
210 return _peMachineType;
211 }
212
213 void IOPlatformExpert::setBootROMType(long peBootROMType)
214 {
215 _peBootROMType = peBootROMType;
216 }
217
218 void IOPlatformExpert::setChipSetType(long peChipSetType)
219 {
220 _peChipSetType = peChipSetType;
221 }
222
223 void IOPlatformExpert::setMachineType(long peMachineType)
224 {
225 _peMachineType = peMachineType;
226 }
227
228 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
229 {
230 return( false );
231 }
232
233 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
234 {
235 return( false );
236 }
237
238 OSString* IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
239 {
240 return NULL;
241 }
242
243 IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void)
244 {
245 return(OSDynamicCast(IORangeAllocator,
246 getProperty("Platform Memory Ranges")));
247 }
248
249 int (*PE_halt_restart)(unsigned int type) = 0;
250
251 int IOPlatformExpert::haltRestart(unsigned int type)
252 {
253 if (type == kPEPanicSync) return 0;
254
255 if (type == kPEHangCPU) while (true) {}
256
257 if (type == kPEUPSDelayHaltCPU) {
258 // RestartOnPowerLoss feature was turned on, proceed with shutdown.
259 type = kPEHaltCPU;
260 }
261
262 // On ARM kPEPanicRestartCPU is supported in the drivers
263 if (type == kPEPanicRestartCPU)
264 type = kPERestartCPU;
265
266 if (PE_halt_restart) return (*PE_halt_restart)(type);
267 else return -1;
268 }
269
270 void IOPlatformExpert::sleepKernel(void)
271 {
272 #if 0
273 long cnt;
274 boolean_t intState;
275
276 intState = ml_set_interrupts_enabled(false);
277
278 for (cnt = 0; cnt < 10000; cnt++) {
279 IODelay(1000);
280 }
281
282 ml_set_interrupts_enabled(intState);
283 #else
284 // PE_initialize_console(0, kPEDisableScreen);
285
286 IOCPUSleepKernel();
287
288 // PE_initialize_console(0, kPEEnableScreen);
289 #endif
290 }
291
292 long IOPlatformExpert::getGMTTimeOfDay(void)
293 {
294 return(0);
295 }
296
297 void IOPlatformExpert::setGMTTimeOfDay(long secs)
298 {
299 }
300
301
302 IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
303 {
304 return( PE_current_console( consoleInfo));
305 }
306
307 IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
308 unsigned int op)
309 {
310 return( PE_initialize_console( consoleInfo, op ));
311 }
312
313 IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
314 {
315 IOLockLock(gIOInterruptControllersLock);
316
317 gIOInterruptControllers->setObject(name, interruptController);
318
319 IOLockWakeup(gIOInterruptControllersLock,
320 gIOInterruptControllers, /* one-thread */ false);
321
322 IOLockUnlock(gIOInterruptControllersLock);
323
324 return kIOReturnSuccess;
325 }
326
327 IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
328 {
329 OSObject *object;
330
331 IOLockLock(gIOInterruptControllersLock);
332 while (1) {
333
334 object = gIOInterruptControllers->getObject(name);
335
336 if (object != 0)
337 break;
338
339 IOLockSleep(gIOInterruptControllersLock,
340 gIOInterruptControllers, THREAD_UNINT);
341 }
342
343 IOLockUnlock(gIOInterruptControllersLock);
344 return OSDynamicCast(IOInterruptController, object);
345 }
346
347
348 void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
349 {
350 IOCPUInterruptController *controller;
351
352 controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
353 if (controller) controller->setCPUInterruptProperties(service);
354 }
355
356 bool IOPlatformExpert::atInterruptLevel(void)
357 {
358 return ml_at_interrupt_context();
359 }
360
361 bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
362 {
363 return true;
364 }
365
366
367 //*********************************************************************************
368 // PMLog
369 //
370 //*********************************************************************************
371
372 void IOPlatformExpert::
373 PMLog(const char *who, unsigned long event,
374 unsigned long param1, unsigned long param2)
375 {
376 clock_sec_t nows;
377 clock_usec_t nowus;
378 clock_get_system_microtime(&nows, &nowus);
379 nowus += (nows % 1000) * 1000000;
380
381 kprintf("pm%u %p %.30s %d %lx %lx\n",
382 nowus, current_thread(), who, // Identity
383 (int) event, (long) param1, (long) param2); // Args
384 }
385
386
387 //*********************************************************************************
388 // PMInstantiatePowerDomains
389 //
390 // In this vanilla implementation, a Root Power Domain is instantiated.
391 // All other objects which register will be children of this Root.
392 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
393 // in a platform-specific subclass.
394 //*********************************************************************************
395
396 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
397 {
398 root = new IOPMrootDomain;
399 root->init();
400 root->attach(this);
401 root->start(this);
402 }
403
404
405 //*********************************************************************************
406 // PMRegisterDevice
407 //
408 // In this vanilla implementation, all callers are made children of the root power domain.
409 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
410 //*********************************************************************************
411
412 void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
413 {
414 root->addPowerChild ( theDevice );
415 }
416
417 //*********************************************************************************
418 // hasPMFeature
419 //
420 //*********************************************************************************
421
422 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
423 {
424 return ((_pePMFeatures & featureMask) != 0);
425 }
426
427 //*********************************************************************************
428 // hasPrivPMFeature
429 //
430 //*********************************************************************************
431
432 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
433 {
434 return ((_pePrivPMFeatures & privFeatureMask) != 0);
435 }
436
437 //*********************************************************************************
438 // numBatteriesSupported
439 //
440 //*********************************************************************************
441
442 int IOPlatformExpert::numBatteriesSupported (void)
443 {
444 return (_peNumBatteriesSupported);
445 }
446
447 //*********************************************************************************
448 // CheckSubTree
449 //
450 // This method is called by the instantiated sublass of the platform expert to
451 // determine how a device should be inserted into the Power Domain. The subclass
452 // provides an XML power tree description against which a device is matched based
453 // on class and provider. If a match is found this routine returns true in addition
454 // to flagging the description tree at the appropriate node that a device has been
455 // registered for the given service.
456 //*********************************************************************************
457
458 bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
459 {
460 unsigned int i;
461 unsigned int numPowerTreeNodes;
462 OSDictionary * entry;
463 OSDictionary * matchingDictionary;
464 OSDictionary * providerDictionary;
465 OSDictionary * deviceDictionary;
466 OSDictionary * nubDictionary;
467 OSArray * children;
468 bool nodeFound = false;
469 bool continueSearch = false;
470 bool deviceMatch = false;
471 bool providerMatch = false;
472 bool multiParentMatch = false;
473
474 if ( (NULL == theDevice) || (NULL == inSubTree) )
475 return false;
476
477 numPowerTreeNodes = inSubTree->getCount ();
478
479 // iterate through the power tree to find a home for this device
480
481 for ( i = 0; i < numPowerTreeNodes; i++ ) {
482
483 entry = (OSDictionary *) inSubTree->getObject (i);
484
485 matchingDictionary = (OSDictionary *) entry->getObject ("device");
486 providerDictionary = (OSDictionary *) entry->getObject ("provider");
487
488 deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
489 if ( matchingDictionary ) {
490 deviceMatch = false;
491 if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) {
492 deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary );
493 deviceDictionary->release ();
494 }
495 }
496
497 providerMatch = true; // we indicate a match if there is no nub or provider
498 if ( theNub && providerDictionary ) {
499 providerMatch = false;
500 if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) {
501 providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary );
502 nubDictionary->release ();
503 }
504 }
505
506 multiParentMatch = true; // again we indicate a match if there is no multi-parent node
507 if (deviceMatch && providerMatch) {
508 if (NULL != multipleParentKeyValue) {
509 OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent");
510 multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false;
511 }
512 }
513
514 nodeFound = (deviceMatch && providerMatch && multiParentMatch);
515
516 // if the power tree specifies a provider dictionary but theNub is
517 // NULL then we cannot match with this entry.
518
519 if ( theNub == NULL && providerDictionary != NULL )
520 nodeFound = false;
521
522 // if this node is THE ONE...then register the device
523
524 if ( nodeFound ) {
525 if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
526
527 if ( kIOLogPower & gIOKitDebug)
528 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
529
530 numInstancesRegistered++;
531
532 // determine if we need to search for additional nodes for this item
533 multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
534 }
535 else
536 nodeFound = false;
537 }
538
539 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
540
541 if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
542 nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
543 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
544 }
545
546 if ( false == continueSearch )
547 break;
548 }
549
550 return ( nodeFound );
551 }
552
553 //*********************************************************************************
554 // RegisterServiceInTree
555 //
556 // Register a device at the specified node of our power tree.
557 //*********************************************************************************
558
559 bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
560 {
561 IOService * aService;
562 bool registered = false;
563 OSArray * children;
564 unsigned int numChildren;
565 OSDictionary * child;
566
567 // make sure someone is not already registered here
568
569 if ( NULL == theTreeNode->getObject ("service") ) {
570
571 if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
572
573 // 1. CHILDREN ------------------
574
575 // we registered the node in the tree...now if the node has children
576 // registered we must tell this service to add them.
577
578 if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) {
579 numChildren = children->getCount ();
580 for ( unsigned int i = 0; i < numChildren; i++ ) {
581 if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) {
582 if ( NULL != (aService = (IOService *) child->getObject ("service")) )
583 theService->addPowerChild (aService);
584 }
585 }
586 }
587
588 // 2. PARENT --------------------
589
590 // also we must notify the parent of this node (if a registered service
591 // exists there) of a new child.
592
593 if ( theTreeParentNode ) {
594 if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
595 if (aService != theProvider)
596 aService->addPowerChild (theService);
597 }
598
599 registered = true;
600 }
601 }
602
603 return registered;
604 }
605
606 //*********************************************************************************
607 // printDictionaryKeys
608 //
609 // Print the keys for the given dictionary and selected contents.
610 //*********************************************************************************
611 void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
612 {
613 OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
614 OSSymbol * mkey;
615 OSString * ioClass;
616 unsigned int i = 0;
617
618 mcoll->reset ();
619
620 mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
621
622 while (mkey) {
623
624 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
625
626 // if this is the IOClass key, print it's contents
627
628 if ( mkey->isEqualTo ("IOClass") ) {
629 ioClass = (OSString *) inDictionary->getObject ("IOClass");
630 if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
631 }
632
633 // if this is an IOProviderClass key print it
634
635 if ( mkey->isEqualTo ("IOProviderClass") ) {
636 ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
637 if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
638
639 }
640
641 // also print IONameMatch keys
642 if ( mkey->isEqualTo ("IONameMatch") ) {
643 ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
644 if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
645 }
646
647 // also print IONameMatched keys
648
649 if ( mkey->isEqualTo ("IONameMatched") ) {
650 ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
651 if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
652 }
653
654 #if 0
655 // print clock-id
656
657 if ( mkey->isEqualTo ("AAPL,clock-id") ) {
658 char * cstr;
659 cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id"));
660 if (cstr)
661 kprintf (" ===> AAPL,clock-id is %s\n", cstr );
662 }
663 #endif
664
665 // print name
666
667 if ( mkey->isEqualTo ("name") ) {
668 char nameStr[64];
669 nameStr[0] = 0;
670 getCStringForObject(inDictionary->getObject("name"), nameStr,
671 sizeof(nameStr));
672 if (strlen(nameStr) > 0)
673 IOLog ("%s name is %s\n", inMsg, nameStr);
674 }
675
676 mkey = (OSSymbol *) mcoll->getNextObject ();
677
678 i++;
679 }
680
681 mcoll->release ();
682 }
683
684 static void
685 getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen)
686 {
687 char * buffer;
688 unsigned int len, i;
689
690 if ( (NULL == inObj) || (NULL == outStr))
691 return;
692
693 char * objString = (char *) (inObj->getMetaClass())->getClassName();
694
695 if ((0 == strncmp(objString, "OSString", sizeof("OSString"))) ||
696 (0 == strncmp(objString, "OSSymbol", sizeof("OSSymbol"))))
697 strlcpy(outStr, ((OSString *)inObj)->getCStringNoCopy(), outStrLen);
698
699 else if (0 == strncmp(objString, "OSData", sizeof("OSData"))) {
700 len = ((OSData *)inObj)->getLength();
701 buffer = (char *)((OSData *)inObj)->getBytesNoCopy();
702 if (buffer && (len > 0)) {
703 for (i=0; i < len; i++) {
704 outStr[i] = buffer[i];
705 }
706 outStr[len] = 0;
707 }
708 }
709 }
710
711 /* IOShutdownNotificationsTimedOut
712 * - Called from a timer installed by PEHaltRestart
713 */
714 static void IOShutdownNotificationsTimedOut(
715 thread_call_param_t p0,
716 thread_call_param_t p1)
717 {
718 int type = (int)(long)p0;
719
720 /* 30 seconds has elapsed - resume shutdown */
721 if(gIOPlatform) gIOPlatform->haltRestart(type);
722 }
723
724
725 extern "C" {
726
727 /*
728 * Callouts from BSD for machine name & model
729 */
730
731 boolean_t PEGetMachineName( char * name, int maxLength )
732 {
733 if( gIOPlatform)
734 return( gIOPlatform->getMachineName( name, maxLength ));
735 else
736 return( false );
737 }
738
739 boolean_t PEGetModelName( char * name, int maxLength )
740 {
741 if( gIOPlatform)
742 return( gIOPlatform->getModelName( name, maxLength ));
743 else
744 return( false );
745 }
746
747 int PEGetPlatformEpoch(void)
748 {
749 if( gIOPlatform)
750 return( gIOPlatform->getBootROMType());
751 else
752 return( -1 );
753 }
754
755 int PEHaltRestart(unsigned int type)
756 {
757 IOPMrootDomain *pmRootDomain;
758 AbsoluteTime deadline;
759 thread_call_t shutdown_hang;
760
761 if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU)
762 {
763 pmRootDomain = IOService::getPMRootDomain();
764 /* Notify IOKit PM clients of shutdown/restart
765 Clients subscribe to this message with a call to
766 IOService::registerInterest()
767 */
768
769 /* Spawn a thread that will panic in 30 seconds.
770 If all goes well the machine will be off by the time
771 the timer expires.
772 */
773 shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut,
774 (thread_call_param_t)(uintptr_t) type);
775 clock_interval_to_deadline( 30, kSecondScale, &deadline );
776 thread_call_enter1_delayed( shutdown_hang, 0, deadline );
777
778 pmRootDomain->handlePlatformHaltRestart(type);
779 /* This notification should have few clients who all do
780 their work synchronously.
781
782 In this "shutdown notification" context we don't give
783 drivers the option of working asynchronously and responding
784 later. PM internals make it very hard to wait for asynchronous
785 replies.
786 */
787 }
788
789 if (gIOPlatform) return gIOPlatform->haltRestart(type);
790 else return -1;
791 }
792
793 UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
794 {
795 if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
796 else return 0;
797 }
798
799
800
801 inline static int init_gIOOptionsEntry(void)
802 {
803 IORegistryEntry *entry;
804 void *nvram_entry;
805 volatile void **options;
806 int ret = -1;
807
808 if (gIOOptionsEntry)
809 return 0;
810
811 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
812 if (!entry)
813 return -1;
814
815 nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
816 if (!nvram_entry)
817 goto release;
818
819 options = (volatile void **) &gIOOptionsEntry;
820 if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
821 ret = 0;
822 goto release;
823 }
824
825 return 0;
826
827 release:
828 entry->release();
829 return ret;
830
831 }
832
833 /* pass in a NULL value if you just want to figure out the len */
834 boolean_t PEReadNVRAMProperty(const char *symbol, void *value,
835 unsigned int *len)
836 {
837 OSObject *obj;
838 OSData *data;
839 unsigned int vlen;
840
841 if (!symbol || !len)
842 goto err;
843
844 if (init_gIOOptionsEntry() < 0)
845 goto err;
846
847 vlen = *len;
848 *len = 0;
849
850 obj = gIOOptionsEntry->getProperty(symbol);
851 if (!obj)
852 goto err;
853
854 /* convert to data */
855 data = OSDynamicCast(OSData, obj);
856 if (!data)
857 goto err;
858
859 *len = data->getLength();
860 vlen = min(vlen, *len);
861 if (value && vlen)
862 memcpy((void *) value, data->getBytesNoCopy(), vlen);
863
864 return TRUE;
865
866 err:
867 return FALSE;
868 }
869
870
871 boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value,
872 const unsigned int len)
873 {
874 const OSSymbol *sym;
875 OSData *data;
876 bool ret = false;
877
878 if (!symbol || !value || !len)
879 goto err;
880
881 if (init_gIOOptionsEntry() < 0)
882 goto err;
883
884 sym = OSSymbol::withCStringNoCopy(symbol);
885 if (!sym)
886 goto err;
887
888 data = OSData::withBytes((void *) value, len);
889 if (!data)
890 goto sym_done;
891
892 ret = gIOOptionsEntry->setProperty(sym, data);
893 data->release();
894
895 sym_done:
896 sym->release();
897
898 if (ret == true) {
899 gIOOptionsEntry->sync();
900 return TRUE;
901 }
902
903 err:
904 return FALSE;
905 }
906
907
908 boolean_t PERemoveNVRAMProperty(const char *symbol)
909 {
910 const OSSymbol *sym;
911
912 if (!symbol)
913 goto err;
914
915 if (init_gIOOptionsEntry() < 0)
916 goto err;
917
918 sym = OSSymbol::withCStringNoCopy(symbol);
919 if (!sym)
920 goto err;
921
922 gIOOptionsEntry->removeProperty(sym);
923
924 sym->release();
925
926 gIOOptionsEntry->sync();
927 return TRUE;
928
929 err:
930 return FALSE;
931
932 }
933
934 long PEGetGMTTimeOfDay(void)
935 {
936 long result = 0;
937
938 if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay();
939
940 return (result);
941 }
942
943 void PESetGMTTimeOfDay(long secs)
944 {
945 if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(secs);
946 }
947
948 } /* extern "C" */
949
950 void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
951 {
952 OSData * data;
953 IORegistryEntry * entry;
954 OSString * string = 0;
955 uuid_string_t uuid;
956
957 entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
958 if ( entry )
959 {
960 data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) );
961 if ( data && data->getLength( ) == 16 )
962 {
963 SHA1_CTX context;
964 uint8_t digest[ SHA_DIGEST_LENGTH ];
965 const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
966
967 SHA1Init( &context );
968 SHA1Update( &context, space, sizeof( space ) );
969 SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) );
970 SHA1Final( digest, &context );
971
972 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50;
973 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80;
974
975 uuid_unparse( digest, uuid );
976 string = OSString::withCString( uuid );
977 }
978
979 entry->release( );
980 }
981
982 if ( string == 0 )
983 {
984 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
985 if ( entry )
986 {
987 data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) );
988 if ( data && data->getLength( ) == sizeof( uuid_t ) )
989 {
990 uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid );
991 string = OSString::withCString( uuid );
992 }
993
994 entry->release( );
995 }
996 }
997
998 if ( string )
999 {
1000 getProvider( )->setProperty( kIOPlatformUUIDKey, string );
1001 publishResource( kIOPlatformUUIDKey, string );
1002
1003 string->release( );
1004 }
1005
1006 publishResource("IONVRAM");
1007 }
1008
1009 IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
1010 bool waitForFunction,
1011 void *param1, void *param2,
1012 void *param3, void *param4)
1013 {
1014 IOService *service, *_resources;
1015
1016 if (waitForFunction) {
1017 _resources = waitForService(resourceMatching(functionName));
1018 } else {
1019 _resources = getResourceService();
1020 }
1021 if (_resources == 0) return kIOReturnUnsupported;
1022
1023 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
1024 if (service == 0) return kIOReturnUnsupported;
1025
1026 return service->callPlatformFunction(functionName, waitForFunction,
1027 param1, param2, param3, param4);
1028 }
1029
1030 IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1031 {
1032 return 0;
1033 }
1034
1035 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1036
1037 #undef super
1038 #define super IOPlatformExpert
1039
1040 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
1041
1042 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
1043 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
1044 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
1045 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
1046 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
1047 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
1048 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
1049 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
1050
1051 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1052
1053 IOService * IODTPlatformExpert::probe( IOService * provider,
1054 SInt32 * score )
1055 {
1056 if( !super::probe( provider, score))
1057 return( 0 );
1058
1059 // check machine types
1060 if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
1061 return( 0 );
1062
1063 return( this);
1064 }
1065
1066 bool IODTPlatformExpert::configure( IOService * provider )
1067 {
1068 if( !super::configure( provider))
1069 return( false);
1070
1071 processTopLevel( provider );
1072
1073 return( true );
1074 }
1075
1076 IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
1077 {
1078 IOService * nub;
1079
1080 nub = new IOPlatformDevice;
1081 if( nub) {
1082 if( !nub->init( from, gIODTPlane )) {
1083 nub->free();
1084 nub = 0;
1085 }
1086 }
1087 return( nub);
1088 }
1089
1090 bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
1091 {
1092 IORegistryEntry * next;
1093 IOService * nub;
1094 bool ok = true;
1095
1096 if( iter) {
1097 while( (next = (IORegistryEntry *) iter->getNextObject())) {
1098
1099 if( 0 == (nub = createNub( next )))
1100 continue;
1101
1102 nub->attach( parent );
1103 nub->registerService();
1104 }
1105 iter->release();
1106 }
1107
1108 return( ok );
1109 }
1110
1111 void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
1112 {
1113 OSIterator * kids;
1114 IORegistryEntry * next;
1115 IORegistryEntry * cpus;
1116 IORegistryEntry * options;
1117
1118 // infanticide
1119 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
1120 if( kids) {
1121 while( (next = (IORegistryEntry *)kids->getNextObject())) {
1122 next->detachAll( gIODTPlane);
1123 }
1124 kids->release();
1125 }
1126
1127 // Publish an IODTNVRAM class on /options.
1128 options = rootEntry->childFromPath("options", gIODTPlane);
1129 if (options) {
1130 dtNVRAM = new IODTNVRAM;
1131 if (dtNVRAM) {
1132 if (!dtNVRAM->init(options, gIODTPlane)) {
1133 dtNVRAM->release();
1134 dtNVRAM = 0;
1135 } else {
1136 dtNVRAM->attach(this);
1137 dtNVRAM->registerService();
1138 }
1139 }
1140 }
1141
1142 // Publish the cpus.
1143 cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
1144 if ( cpus)
1145 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
1146
1147 // publish top level, minus excludeList
1148 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
1149 }
1150
1151 IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
1152 {
1153 if( nub->getDeviceMemory())
1154 return( kIOReturnSuccess );
1155
1156 IODTResolveAddressing( nub, "reg", 0);
1157
1158 return( kIOReturnSuccess);
1159 }
1160
1161 bool IODTPlatformExpert::compareNubName( const IOService * nub,
1162 OSString * name, OSString ** matched ) const
1163 {
1164 return( IODTCompareNubName( nub, name, matched )
1165 || super::compareNubName( nub, name, matched) );
1166 }
1167
1168 bool IODTPlatformExpert::getModelName( char * name, int maxLength )
1169 {
1170 OSData * prop;
1171 const char * str;
1172 int len;
1173 char c;
1174 bool ok = false;
1175
1176 maxLength--;
1177
1178 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
1179 if( prop ) {
1180 str = (const char *) prop->getBytesNoCopy();
1181
1182 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
1183 str += strlen( "AAPL," );
1184
1185 len = 0;
1186 while( (c = *str++)) {
1187 if( (c == '/') || (c == ' '))
1188 c = '-';
1189
1190 name[ len++ ] = c;
1191 if( len >= maxLength)
1192 break;
1193 }
1194
1195 name[ len ] = 0;
1196 ok = true;
1197 }
1198 return( ok );
1199 }
1200
1201 bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
1202 {
1203 OSData * prop;
1204 bool ok = false;
1205
1206 maxLength--;
1207 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
1208 ok = (0 != prop);
1209
1210 if( ok )
1211 strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
1212
1213 return( ok );
1214 }
1215
1216 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1217
1218 void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
1219 {
1220 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
1221
1222 super::registerNVRAMController(nvram);
1223 }
1224
1225 int IODTPlatformExpert::haltRestart(unsigned int type)
1226 {
1227 if (dtNVRAM) dtNVRAM->sync();
1228
1229 return super::haltRestart(type);
1230 }
1231
1232 IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
1233 IOByteCount length)
1234 {
1235 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
1236 else return kIOReturnNotReady;
1237 }
1238
1239 IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
1240 IOByteCount length)
1241 {
1242 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
1243 else return kIOReturnNotReady;
1244 }
1245
1246 IOReturn IODTPlatformExpert::readNVRAMProperty(
1247 IORegistryEntry * entry,
1248 const OSSymbol ** name, OSData ** value )
1249 {
1250 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
1251 else return kIOReturnNotReady;
1252 }
1253
1254 IOReturn IODTPlatformExpert::writeNVRAMProperty(
1255 IORegistryEntry * entry,
1256 const OSSymbol * name, OSData * value )
1257 {
1258 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
1259 else return kIOReturnNotReady;
1260 }
1261
1262 OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
1263 {
1264 if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
1265 else return 0;
1266 }
1267
1268 IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
1269 IOByteCount offset, UInt8 * buffer,
1270 IOByteCount length)
1271 {
1272 if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
1273 buffer, length);
1274 else return kIOReturnNotReady;
1275 }
1276
1277 IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
1278 IOByteCount offset, UInt8 * buffer,
1279 IOByteCount length)
1280 {
1281 if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
1282 buffer, length);
1283 else return kIOReturnNotReady;
1284 }
1285
1286 IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1287 {
1288 IOByteCount lengthSaved = 0;
1289
1290 if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
1291
1292 if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
1293
1294 return lengthSaved;
1295 }
1296
1297 OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) {
1298 UInt8* serialNumber;
1299 unsigned int serialNumberSize;
1300 unsigned short pos = 0;
1301 char* temp;
1302 char SerialNo[30];
1303
1304 if (myProperty != NULL) {
1305 serialNumberSize = myProperty->getLength();
1306 serialNumber = (UInt8*)(myProperty->getBytesNoCopy());
1307 temp = (char*)serialNumber;
1308 if (serialNumberSize > 0) {
1309 // check to see if this is a CTO serial number...
1310 while (pos < serialNumberSize && temp[pos] != '-') pos++;
1311
1312 if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number
1313 memcpy(SerialNo, serialNumber + 12, 8);
1314 memcpy(&SerialNo[8], serialNumber, 3);
1315 SerialNo[11] = '-';
1316 memcpy(&SerialNo[12], serialNumber + 3, 8);
1317 SerialNo[20] = 0;
1318 } else { // just a normal serial number
1319 memcpy(SerialNo, serialNumber + 13, 8);
1320 memcpy(&SerialNo[8], serialNumber, 3);
1321 SerialNo[11] = 0;
1322 }
1323 return OSString::withCString(SerialNo);
1324 }
1325 }
1326 return NULL;
1327 }
1328
1329
1330 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1331
1332 #undef super
1333 #define super IOService
1334
1335 OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
1336
1337 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
1338 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
1339 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
1340 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
1341
1342 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1343
1344 bool IOPlatformExpertDevice::compareName( OSString * name,
1345 OSString ** matched ) const
1346 {
1347 return( IODTCompareNubName( this, name, matched ));
1348 }
1349
1350 bool
1351 IOPlatformExpertDevice::initWithArgs(
1352 void * dtTop, void * p2, void * p3, void * p4 )
1353 {
1354 IORegistryEntry * dt = 0;
1355 void * argsData[ 4 ];
1356 bool ok;
1357
1358 // dtTop may be zero on non- device tree systems
1359 if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
1360 ok = super::init( dt, gIODTPlane );
1361 else
1362 ok = super::init();
1363
1364 if( !ok)
1365 return( false);
1366
1367 reserved = NULL;
1368 workLoop = IOWorkLoop::workLoop();
1369 if (!workLoop)
1370 return false;
1371
1372 argsData[ 0 ] = dtTop;
1373 argsData[ 1 ] = p2;
1374 argsData[ 2 ] = p3;
1375 argsData[ 3 ] = p4;
1376
1377 setProperty("IOPlatformArgs", (void *)argsData, sizeof(argsData));
1378
1379 return( true);
1380 }
1381
1382 IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
1383 {
1384 return workLoop;
1385 }
1386
1387 IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties )
1388 {
1389 OSDictionary * dictionary;
1390 OSObject * object;
1391 IOReturn status;
1392
1393 status = super::setProperties( properties );
1394 if ( status != kIOReturnUnsupported ) return status;
1395
1396 status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator );
1397 if ( status != kIOReturnSuccess ) return status;
1398
1399 dictionary = OSDynamicCast( OSDictionary, properties );
1400 if ( dictionary == 0 ) return kIOReturnBadArgument;
1401
1402 object = dictionary->getObject( kIOPlatformUUIDKey );
1403 if ( object )
1404 {
1405 IORegistryEntry * entry;
1406 OSString * string;
1407 uuid_t uuid;
1408
1409 string = ( OSString * ) getProperty( kIOPlatformUUIDKey );
1410 if ( string ) return kIOReturnNotPermitted;
1411
1412 string = OSDynamicCast( OSString, object );
1413 if ( string == 0 ) return kIOReturnBadArgument;
1414
1415 status = uuid_parse( string->getCStringNoCopy( ), uuid );
1416 if ( status != 0 ) return kIOReturnBadArgument;
1417
1418 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1419 if ( entry )
1420 {
1421 entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) );
1422 entry->release( );
1423 }
1424
1425 setProperty( kIOPlatformUUIDKey, string );
1426 publishResource( kIOPlatformUUIDKey, string );
1427
1428 return kIOReturnSuccess;
1429 }
1430
1431 return kIOReturnUnsupported;
1432 }
1433
1434 void IOPlatformExpertDevice::free()
1435 {
1436 if (workLoop)
1437 workLoop->release();
1438 }
1439
1440 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1441
1442 #undef super
1443 #define super IOService
1444
1445 OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1446
1447 OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1448 OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1449 OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1450 OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1451
1452 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1453
1454 bool IOPlatformDevice::compareName( OSString * name,
1455 OSString ** matched ) const
1456 {
1457 return( ((IOPlatformExpert *)getProvider())->
1458 compareNubName( this, name, matched ));
1459 }
1460
1461 IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
1462 {
1463 return( this );
1464 }
1465
1466 IOReturn IOPlatformDevice::getResources( void )
1467 {
1468 return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
1469 }
1470
1471 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1472
1473 /*********************************************************************
1474 * IOPanicPlatform class
1475 *
1476 * If no legitimate IOPlatformDevice matches, this one does and panics
1477 * the kernel with a suitable message.
1478 *********************************************************************/
1479
1480 class IOPanicPlatform : IOPlatformExpert {
1481 OSDeclareDefaultStructors(IOPanicPlatform);
1482
1483 public:
1484 bool start(IOService * provider);
1485 };
1486
1487
1488 OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1489
1490
1491 bool IOPanicPlatform::start(IOService * provider) {
1492 const char * platform_name = "(unknown platform name)";
1493
1494 if (provider) platform_name = provider->getName();
1495
1496 panic("Unable to find driver for this platform: \"%s\".\n",
1497 platform_name);
1498
1499 return false;
1500 }
1501