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