]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPlatformExpert.cpp
xnu-2050.24.15.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 #ifdef CONFIG_EMBEDDED
719 /* 30 seconds has elapsed - panic */
720 panic("Halt/Restart Timed Out");
721
722 #else /* ! CONFIG_EMBEDDED */
723 int type = (int)(long)p0;
724
725 /* 30 seconds has elapsed - resume shutdown */
726 if(gIOPlatform) gIOPlatform->haltRestart(type);
727 #endif /* CONFIG_EMBEDDED */
728 }
729
730
731 extern "C" {
732
733 /*
734 * Callouts from BSD for machine name & model
735 */
736
737 boolean_t PEGetMachineName( char * name, int maxLength )
738 {
739 if( gIOPlatform)
740 return( gIOPlatform->getMachineName( name, maxLength ));
741 else
742 return( false );
743 }
744
745 boolean_t PEGetModelName( char * name, int maxLength )
746 {
747 if( gIOPlatform)
748 return( gIOPlatform->getModelName( name, maxLength ));
749 else
750 return( false );
751 }
752
753 int PEGetPlatformEpoch(void)
754 {
755 if( gIOPlatform)
756 return( gIOPlatform->getBootROMType());
757 else
758 return( -1 );
759 }
760
761 int PEHaltRestart(unsigned int type)
762 {
763 IOPMrootDomain *pmRootDomain;
764 AbsoluteTime deadline;
765 thread_call_t shutdown_hang;
766
767 if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU)
768 {
769 pmRootDomain = IOService::getPMRootDomain();
770 /* Notify IOKit PM clients of shutdown/restart
771 Clients subscribe to this message with a call to
772 IOService::registerInterest()
773 */
774
775 /* Spawn a thread that will panic in 30 seconds.
776 If all goes well the machine will be off by the time
777 the timer expires.
778 */
779 shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut,
780 (thread_call_param_t) type);
781 clock_interval_to_deadline( 30, kSecondScale, &deadline );
782 thread_call_enter1_delayed( shutdown_hang, 0, deadline );
783
784 pmRootDomain->handlePlatformHaltRestart(type);
785 /* This notification should have few clients who all do
786 their work synchronously.
787
788 In this "shutdown notification" context we don't give
789 drivers the option of working asynchronously and responding
790 later. PM internals make it very hard to wait for asynchronous
791 replies.
792 */
793 }
794
795 if (gIOPlatform) return gIOPlatform->haltRestart(type);
796 else return -1;
797 }
798
799 UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
800 {
801 if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
802 else return 0;
803 }
804
805
806
807 inline static int init_gIOOptionsEntry(void)
808 {
809 IORegistryEntry *entry;
810 void *nvram_entry;
811 volatile void **options;
812 int ret = -1;
813
814 if (gIOOptionsEntry)
815 return 0;
816
817 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
818 if (!entry)
819 return -1;
820
821 nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
822 if (!nvram_entry)
823 goto release;
824
825 options = (volatile void **) &gIOOptionsEntry;
826 if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
827 ret = 0;
828 goto release;
829 }
830
831 return 0;
832
833 release:
834 entry->release();
835 return ret;
836
837 }
838
839 /* pass in a NULL value if you just want to figure out the len */
840 boolean_t PEReadNVRAMProperty(const char *symbol, void *value,
841 unsigned int *len)
842 {
843 OSObject *obj;
844 OSData *data;
845 unsigned int vlen;
846
847 if (!symbol || !len)
848 goto err;
849
850 if (init_gIOOptionsEntry() < 0)
851 goto err;
852
853 vlen = *len;
854 *len = 0;
855
856 obj = gIOOptionsEntry->getProperty(symbol);
857 if (!obj)
858 goto err;
859
860 /* convert to data */
861 data = OSDynamicCast(OSData, obj);
862 if (!data)
863 goto err;
864
865 *len = data->getLength();
866 vlen = min(vlen, *len);
867 if (vlen)
868 memcpy((void *) value, data->getBytesNoCopy(), vlen);
869
870 return TRUE;
871
872 err:
873 return FALSE;
874 }
875
876
877 boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value,
878 const unsigned int len)
879 {
880 const OSSymbol *sym;
881 OSData *data;
882 bool ret = false;
883
884 if (!symbol || !value || !len)
885 goto err;
886
887 if (init_gIOOptionsEntry() < 0)
888 goto err;
889
890 sym = OSSymbol::withCStringNoCopy(symbol);
891 if (!sym)
892 goto err;
893
894 data = OSData::withBytes((void *) value, len);
895 if (!data)
896 goto sym_done;
897
898 ret = gIOOptionsEntry->setProperty(sym, data);
899 data->release();
900
901 sym_done:
902 sym->release();
903
904 if (ret == true) {
905 gIOOptionsEntry->sync();
906 return TRUE;
907 }
908
909 err:
910 return FALSE;
911 }
912
913
914 long PEGetGMTTimeOfDay(void)
915 {
916 long result = 0;
917
918 if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay();
919
920 return (result);
921 }
922
923 void PESetGMTTimeOfDay(long secs)
924 {
925 if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(secs);
926 }
927
928 } /* extern "C" */
929
930 void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
931 {
932 OSData * data;
933 IORegistryEntry * entry;
934 OSString * string = 0;
935 uuid_string_t uuid;
936
937 #if CONFIG_EMBEDDED
938 entry = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
939 if ( entry )
940 {
941 OSData * data1;
942
943 data1 = OSDynamicCast( OSData, entry->getProperty( "unique-chip-id" ) );
944 if ( data1 && data1->getLength( ) == 8 )
945 {
946 OSData * data2;
947
948 data2 = OSDynamicCast( OSData, entry->getProperty( "chip-id" ) );
949 if ( data2 && data2->getLength( ) == 4 )
950 {
951 SHA1_CTX context;
952 uint8_t digest[ SHA_DIGEST_LENGTH ];
953 const uuid_t space = { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
954
955 SHA1Init( &context );
956 SHA1Update( &context, space, sizeof( space ) );
957 SHA1Update( &context, data1->getBytesNoCopy( ), data1->getLength( ) );
958 SHA1Update( &context, data2->getBytesNoCopy( ), data2->getLength( ) );
959 SHA1Final( digest, &context );
960
961 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50;
962 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80;
963
964 uuid_unparse( digest, uuid );
965 string = OSString::withCString( uuid );
966 }
967 }
968
969 entry->release( );
970 }
971 #else /* !CONFIG_EMBEDDED */
972 entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
973 if ( entry )
974 {
975 data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) );
976 if ( data && data->getLength( ) == 16 )
977 {
978 SHA1_CTX context;
979 uint8_t digest[ SHA_DIGEST_LENGTH ];
980 const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
981
982 SHA1Init( &context );
983 SHA1Update( &context, space, sizeof( space ) );
984 SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) );
985 SHA1Final( digest, &context );
986
987 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50;
988 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80;
989
990 uuid_unparse( digest, uuid );
991 string = OSString::withCString( uuid );
992 }
993
994 entry->release( );
995 }
996 #endif /* !CONFIG_EMBEDDED */
997
998 if ( string == 0 )
999 {
1000 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1001 if ( entry )
1002 {
1003 data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) );
1004 if ( data && data->getLength( ) == sizeof( uuid_t ) )
1005 {
1006 uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid );
1007 string = OSString::withCString( uuid );
1008 }
1009
1010 entry->release( );
1011 }
1012 }
1013
1014 if ( string )
1015 {
1016 getProvider( )->setProperty( kIOPlatformUUIDKey, string );
1017 publishResource( kIOPlatformUUIDKey, string );
1018
1019 string->release( );
1020 }
1021
1022 publishResource("IONVRAM");
1023 }
1024
1025 IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
1026 bool waitForFunction,
1027 void *param1, void *param2,
1028 void *param3, void *param4)
1029 {
1030 IOService *service, *_resources;
1031
1032 if (waitForFunction) {
1033 _resources = waitForService(resourceMatching(functionName));
1034 } else {
1035 _resources = getResourceService();
1036 }
1037 if (_resources == 0) return kIOReturnUnsupported;
1038
1039 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
1040 if (service == 0) return kIOReturnUnsupported;
1041
1042 return service->callPlatformFunction(functionName, waitForFunction,
1043 param1, param2, param3, param4);
1044 }
1045
1046 IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1047 {
1048 return 0;
1049 }
1050
1051 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1052
1053 #undef super
1054 #define super IOPlatformExpert
1055
1056 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
1057
1058 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
1059 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
1060 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
1061 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
1062 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
1063 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
1064 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
1065 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
1066
1067 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1068
1069 IOService * IODTPlatformExpert::probe( IOService * provider,
1070 SInt32 * score )
1071 {
1072 if( !super::probe( provider, score))
1073 return( 0 );
1074
1075 // check machine types
1076 if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
1077 return( 0 );
1078
1079 return( this);
1080 }
1081
1082 bool IODTPlatformExpert::configure( IOService * provider )
1083 {
1084 if( !super::configure( provider))
1085 return( false);
1086
1087 processTopLevel( provider );
1088
1089 return( true );
1090 }
1091
1092 IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
1093 {
1094 IOService * nub;
1095
1096 nub = new IOPlatformDevice;
1097 if( nub) {
1098 if( !nub->init( from, gIODTPlane )) {
1099 nub->free();
1100 nub = 0;
1101 }
1102 }
1103 return( nub);
1104 }
1105
1106 bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
1107 {
1108 IORegistryEntry * next;
1109 IOService * nub;
1110 bool ok = true;
1111
1112 if( iter) {
1113 while( (next = (IORegistryEntry *) iter->getNextObject())) {
1114
1115 if( 0 == (nub = createNub( next )))
1116 continue;
1117
1118 nub->attach( parent );
1119 nub->registerService();
1120 }
1121 iter->release();
1122 }
1123
1124 return( ok );
1125 }
1126
1127 void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
1128 {
1129 OSIterator * kids;
1130 IORegistryEntry * next;
1131 IORegistryEntry * cpus;
1132 IORegistryEntry * options;
1133
1134 // infanticide
1135 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
1136 if( kids) {
1137 while( (next = (IORegistryEntry *)kids->getNextObject())) {
1138 next->detachAll( gIODTPlane);
1139 }
1140 kids->release();
1141 }
1142
1143 // Publish an IODTNVRAM class on /options.
1144 options = rootEntry->childFromPath("options", gIODTPlane);
1145 if (options) {
1146 dtNVRAM = new IODTNVRAM;
1147 if (dtNVRAM) {
1148 if (!dtNVRAM->init(options, gIODTPlane)) {
1149 dtNVRAM->release();
1150 dtNVRAM = 0;
1151 } else {
1152 dtNVRAM->attach(this);
1153 dtNVRAM->registerService();
1154 }
1155 }
1156 }
1157
1158 // Publish the cpus.
1159 cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
1160 if ( cpus)
1161 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
1162
1163 // publish top level, minus excludeList
1164 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
1165 }
1166
1167 IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
1168 {
1169 if( nub->getDeviceMemory())
1170 return( kIOReturnSuccess );
1171
1172 IODTResolveAddressing( nub, "reg", 0);
1173
1174 return( kIOReturnSuccess);
1175 }
1176
1177 bool IODTPlatformExpert::compareNubName( const IOService * nub,
1178 OSString * name, OSString ** matched ) const
1179 {
1180 return( IODTCompareNubName( nub, name, matched )
1181 || super::compareNubName( nub, name, matched) );
1182 }
1183
1184 bool IODTPlatformExpert::getModelName( char * name, int maxLength )
1185 {
1186 OSData * prop;
1187 const char * str;
1188 int len;
1189 char c;
1190 bool ok = false;
1191
1192 maxLength--;
1193
1194 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
1195 if( prop ) {
1196 str = (const char *) prop->getBytesNoCopy();
1197
1198 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
1199 str += strlen( "AAPL," );
1200
1201 len = 0;
1202 while( (c = *str++)) {
1203 if( (c == '/') || (c == ' '))
1204 c = '-';
1205
1206 name[ len++ ] = c;
1207 if( len >= maxLength)
1208 break;
1209 }
1210
1211 name[ len ] = 0;
1212 ok = true;
1213 }
1214 return( ok );
1215 }
1216
1217 bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
1218 {
1219 OSData * prop;
1220 bool ok = false;
1221
1222 maxLength--;
1223 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
1224 ok = (0 != prop);
1225
1226 if( ok )
1227 strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
1228
1229 return( ok );
1230 }
1231
1232 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1233
1234 void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
1235 {
1236 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
1237
1238 super::registerNVRAMController(nvram);
1239 }
1240
1241 int IODTPlatformExpert::haltRestart(unsigned int type)
1242 {
1243 if (dtNVRAM) dtNVRAM->sync();
1244
1245 return super::haltRestart(type);
1246 }
1247
1248 IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
1249 IOByteCount length)
1250 {
1251 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
1252 else return kIOReturnNotReady;
1253 }
1254
1255 IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
1256 IOByteCount length)
1257 {
1258 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
1259 else return kIOReturnNotReady;
1260 }
1261
1262 IOReturn IODTPlatformExpert::readNVRAMProperty(
1263 IORegistryEntry * entry,
1264 const OSSymbol ** name, OSData ** value )
1265 {
1266 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
1267 else return kIOReturnNotReady;
1268 }
1269
1270 IOReturn IODTPlatformExpert::writeNVRAMProperty(
1271 IORegistryEntry * entry,
1272 const OSSymbol * name, OSData * value )
1273 {
1274 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
1275 else return kIOReturnNotReady;
1276 }
1277
1278 OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
1279 {
1280 if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
1281 else return 0;
1282 }
1283
1284 IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
1285 IOByteCount offset, UInt8 * buffer,
1286 IOByteCount length)
1287 {
1288 if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
1289 buffer, length);
1290 else return kIOReturnNotReady;
1291 }
1292
1293 IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
1294 IOByteCount offset, UInt8 * buffer,
1295 IOByteCount length)
1296 {
1297 if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
1298 buffer, length);
1299 else return kIOReturnNotReady;
1300 }
1301
1302 IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1303 {
1304 IOByteCount lengthSaved = 0;
1305
1306 if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
1307
1308 if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
1309
1310 return lengthSaved;
1311 }
1312
1313 OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) {
1314 UInt8* serialNumber;
1315 unsigned int serialNumberSize;
1316 unsigned short pos = 0;
1317 char* temp;
1318 char SerialNo[30];
1319
1320 if (myProperty != NULL) {
1321 serialNumberSize = myProperty->getLength();
1322 serialNumber = (UInt8*)(myProperty->getBytesNoCopy());
1323 temp = (char*)serialNumber;
1324 if (serialNumberSize > 0) {
1325 // check to see if this is a CTO serial number...
1326 while (pos < serialNumberSize && temp[pos] != '-') pos++;
1327
1328 if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number
1329 memcpy(SerialNo, serialNumber + 12, 8);
1330 memcpy(&SerialNo[8], serialNumber, 3);
1331 SerialNo[11] = '-';
1332 memcpy(&SerialNo[12], serialNumber + 3, 8);
1333 SerialNo[20] = 0;
1334 } else { // just a normal serial number
1335 memcpy(SerialNo, serialNumber + 13, 8);
1336 memcpy(&SerialNo[8], serialNumber, 3);
1337 SerialNo[11] = 0;
1338 }
1339 return OSString::withCString(SerialNo);
1340 }
1341 }
1342 return NULL;
1343 }
1344
1345
1346 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1347
1348 #undef super
1349 #define super IOService
1350
1351 OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
1352
1353 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
1354 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
1355 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
1356 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
1357
1358 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1359
1360 bool IOPlatformExpertDevice::compareName( OSString * name,
1361 OSString ** matched ) const
1362 {
1363 return( IODTCompareNubName( this, name, matched ));
1364 }
1365
1366 bool
1367 IOPlatformExpertDevice::initWithArgs(
1368 void * dtTop, void * p2, void * p3, void * p4 )
1369 {
1370 IORegistryEntry * dt = 0;
1371 void * argsData[ 4 ];
1372 bool ok;
1373
1374 // dtTop may be zero on non- device tree systems
1375 if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
1376 ok = super::init( dt, gIODTPlane );
1377 else
1378 ok = super::init();
1379
1380 if( !ok)
1381 return( false);
1382
1383 workLoop = IOWorkLoop::workLoop();
1384 if (!workLoop)
1385 return false;
1386
1387 argsData[ 0 ] = dtTop;
1388 argsData[ 1 ] = p2;
1389 argsData[ 2 ] = p3;
1390 argsData[ 3 ] = p4;
1391
1392 setProperty("IOPlatformArgs", (void *)argsData, sizeof(argsData));
1393
1394 return( true);
1395 }
1396
1397 IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
1398 {
1399 return workLoop;
1400 }
1401
1402 IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties )
1403 {
1404 OSDictionary * dictionary;
1405 OSObject * object;
1406 IOReturn status;
1407
1408 status = super::setProperties( properties );
1409 if ( status != kIOReturnUnsupported ) return status;
1410
1411 status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator );
1412 if ( status != kIOReturnSuccess ) return status;
1413
1414 dictionary = OSDynamicCast( OSDictionary, properties );
1415 if ( dictionary == 0 ) return kIOReturnBadArgument;
1416
1417 object = dictionary->getObject( kIOPlatformUUIDKey );
1418 if ( object )
1419 {
1420 IORegistryEntry * entry;
1421 OSString * string;
1422 uuid_t uuid;
1423
1424 string = ( OSString * ) getProperty( kIOPlatformUUIDKey );
1425 if ( string ) return kIOReturnNotPermitted;
1426
1427 string = OSDynamicCast( OSString, object );
1428 if ( string == 0 ) return kIOReturnBadArgument;
1429
1430 status = uuid_parse( string->getCStringNoCopy( ), uuid );
1431 if ( status != 0 ) return kIOReturnBadArgument;
1432
1433 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1434 if ( entry )
1435 {
1436 entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) );
1437 entry->release( );
1438 }
1439
1440 setProperty( kIOPlatformUUIDKey, string );
1441 publishResource( kIOPlatformUUIDKey, string );
1442
1443 return kIOReturnSuccess;
1444 }
1445
1446 return kIOReturnUnsupported;
1447 }
1448
1449 void IOPlatformExpertDevice::free()
1450 {
1451 if (workLoop)
1452 workLoop->release();
1453 }
1454
1455 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1456
1457 #undef super
1458 #define super IOService
1459
1460 OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1461
1462 OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1463 OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1464 OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1465 OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1466
1467 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1468
1469 bool IOPlatformDevice::compareName( OSString * name,
1470 OSString ** matched ) const
1471 {
1472 return( ((IOPlatformExpert *)getProvider())->
1473 compareNubName( this, name, matched ));
1474 }
1475
1476 IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
1477 {
1478 return( this );
1479 }
1480
1481 IOReturn IOPlatformDevice::getResources( void )
1482 {
1483 return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
1484 }
1485
1486 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1487
1488 /*********************************************************************
1489 * IOPanicPlatform class
1490 *
1491 * If no legitimate IOPlatformDevice matches, this one does and panics
1492 * the kernel with a suitable message.
1493 *********************************************************************/
1494
1495 class IOPanicPlatform : IOPlatformExpert {
1496 OSDeclareDefaultStructors(IOPanicPlatform);
1497
1498 public:
1499 bool start(IOService * provider);
1500 };
1501
1502
1503 OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1504
1505
1506 bool IOPanicPlatform::start(IOService * provider) {
1507 const char * platform_name = "(unknown platform name)";
1508
1509 if (provider) platform_name = provider->getName();
1510
1511 panic("Unable to find driver for this platform: \"%s\".\n",
1512 platform_name);
1513
1514 return false;
1515 }
1516