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