]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPlatformExpert.cpp
xnu-2050.22.13.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 UInt32 debugFlags = gIOKitDebug;
377 UInt32 traceFlags = gIOKitTrace;
378 uintptr_t name = 0;
379 UInt32 i = 0;
380
381 if (debugFlags & kIOLogPower) {
382
383 clock_sec_t nows;
384 clock_usec_t nowus;
385 clock_get_system_microtime(&nows, &nowus);
386 nowus += (nows % 1000) * 1000000;
387
388 kprintf("pm%u %p %.30s %d %lx %lx\n",
389 nowus, current_thread(), who, // Identity
390 (int) event, (long) param1, (long) param2); // Args
391
392 if (traceFlags & kIOTracePowerMgmt) {
393 static const UInt32 sStartStopBitField[] =
394 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
395
396 // Arcane formula from Hacker's Delight by Warren
397 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
398 UInt32 sgnevent = ((long) event >> 31);
399 UInt32 absevent = sgnevent ^ (event + sgnevent);
400 UInt32 code = IODBG_POWER(absevent);
401
402 UInt32 bit = 1 << (absevent & 0x1f);
403 if (absevent < sizeof(sStartStopBitField) * 8
404 && (sStartStopBitField[absevent >> 5] & bit) ) {
405 // Or in the START or END bits, Start = 1 & END = 2
406 // If sgnevent == 0 then START - 0 => START
407 // else if sgnevent == -1 then START - -1 => END
408 code |= DBG_FUNC_START - sgnevent;
409 }
410
411 // Get first 8 characters of the name
412 while ( i < sizeof(uintptr_t) && who[i] != 0)
413 { ((char *)&name)[sizeof(uintptr_t)-i-1]=who[i]; i++; }
414 // Record the timestamp.
415 IOTimeStampConstant(code, name, event, param1, param2);
416 }
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
430 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
431 {
432 root = new IOPMrootDomain;
433 root->init();
434 root->attach(this);
435 root->start(this);
436 }
437
438
439 //*********************************************************************************
440 // PMRegisterDevice
441 //
442 // In this vanilla implementation, all callers are made children of the root power domain.
443 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
444 //*********************************************************************************
445
446 void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
447 {
448 root->addPowerChild ( theDevice );
449 }
450
451 //*********************************************************************************
452 // hasPMFeature
453 //
454 //*********************************************************************************
455
456 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
457 {
458 return ((_pePMFeatures & featureMask) != 0);
459 }
460
461 //*********************************************************************************
462 // hasPrivPMFeature
463 //
464 //*********************************************************************************
465
466 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
467 {
468 return ((_pePrivPMFeatures & privFeatureMask) != 0);
469 }
470
471 //*********************************************************************************
472 // numBatteriesSupported
473 //
474 //*********************************************************************************
475
476 int IOPlatformExpert::numBatteriesSupported (void)
477 {
478 return (_peNumBatteriesSupported);
479 }
480
481 //*********************************************************************************
482 // CheckSubTree
483 //
484 // This method is called by the instantiated sublass of the platform expert to
485 // determine how a device should be inserted into the Power Domain. The subclass
486 // provides an XML power tree description against which a device is matched based
487 // on class and provider. If a match is found this routine returns true in addition
488 // to flagging the description tree at the appropriate node that a device has been
489 // registered for the given service.
490 //*********************************************************************************
491
492 bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
493 {
494 unsigned int i;
495 unsigned int numPowerTreeNodes;
496 OSDictionary * entry;
497 OSDictionary * matchingDictionary;
498 OSDictionary * providerDictionary;
499 OSDictionary * deviceDictionary;
500 OSDictionary * nubDictionary;
501 OSArray * children;
502 bool nodeFound = false;
503 bool continueSearch = false;
504 bool deviceMatch = false;
505 bool providerMatch = false;
506 bool multiParentMatch = false;
507
508 if ( (NULL == theDevice) || (NULL == inSubTree) )
509 return false;
510
511 numPowerTreeNodes = inSubTree->getCount ();
512
513 // iterate through the power tree to find a home for this device
514
515 for ( i = 0; i < numPowerTreeNodes; i++ ) {
516
517 entry = (OSDictionary *) inSubTree->getObject (i);
518
519 matchingDictionary = (OSDictionary *) entry->getObject ("device");
520 providerDictionary = (OSDictionary *) entry->getObject ("provider");
521
522 deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
523 if ( matchingDictionary ) {
524 deviceMatch = false;
525 if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) {
526 deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary );
527 deviceDictionary->release ();
528 }
529 }
530
531 providerMatch = true; // we indicate a match if there is no nub or provider
532 if ( theNub && providerDictionary ) {
533 providerMatch = false;
534 if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) {
535 providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary );
536 nubDictionary->release ();
537 }
538 }
539
540 multiParentMatch = true; // again we indicate a match if there is no multi-parent node
541 if (deviceMatch && providerMatch) {
542 if (NULL != multipleParentKeyValue) {
543 OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent");
544 multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false;
545 }
546 }
547
548 nodeFound = (deviceMatch && providerMatch && multiParentMatch);
549
550 // if the power tree specifies a provider dictionary but theNub is
551 // NULL then we cannot match with this entry.
552
553 if ( theNub == NULL && providerDictionary != NULL )
554 nodeFound = false;
555
556 // if this node is THE ONE...then register the device
557
558 if ( nodeFound ) {
559 if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
560
561 if ( kIOLogPower & gIOKitDebug)
562 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
563
564 numInstancesRegistered++;
565
566 // determine if we need to search for additional nodes for this item
567 multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
568 }
569 else
570 nodeFound = false;
571 }
572
573 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
574
575 if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
576 nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
577 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
578 }
579
580 if ( false == continueSearch )
581 break;
582 }
583
584 return ( nodeFound );
585 }
586
587 //*********************************************************************************
588 // RegisterServiceInTree
589 //
590 // Register a device at the specified node of our power tree.
591 //*********************************************************************************
592
593 bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
594 {
595 IOService * aService;
596 bool registered = false;
597 OSArray * children;
598 unsigned int numChildren;
599 OSDictionary * child;
600
601 // make sure someone is not already registered here
602
603 if ( NULL == theTreeNode->getObject ("service") ) {
604
605 if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
606
607 // 1. CHILDREN ------------------
608
609 // we registered the node in the tree...now if the node has children
610 // registered we must tell this service to add them.
611
612 if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) {
613 numChildren = children->getCount ();
614 for ( unsigned int i = 0; i < numChildren; i++ ) {
615 if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) {
616 if ( NULL != (aService = (IOService *) child->getObject ("service")) )
617 theService->addPowerChild (aService);
618 }
619 }
620 }
621
622 // 2. PARENT --------------------
623
624 // also we must notify the parent of this node (if a registered service
625 // exists there) of a new child.
626
627 if ( theTreeParentNode ) {
628 if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
629 if (aService != theProvider)
630 aService->addPowerChild (theService);
631 }
632
633 registered = true;
634 }
635 }
636
637 return registered;
638 }
639
640 //*********************************************************************************
641 // printDictionaryKeys
642 //
643 // Print the keys for the given dictionary and selected contents.
644 //*********************************************************************************
645 void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
646 {
647 OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
648 OSSymbol * mkey;
649 OSString * ioClass;
650 unsigned int i = 0;
651
652 mcoll->reset ();
653
654 mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
655
656 while (mkey) {
657
658 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
659
660 // if this is the IOClass key, print it's contents
661
662 if ( mkey->isEqualTo ("IOClass") ) {
663 ioClass = (OSString *) inDictionary->getObject ("IOClass");
664 if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
665 }
666
667 // if this is an IOProviderClass key print it
668
669 if ( mkey->isEqualTo ("IOProviderClass") ) {
670 ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
671 if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
672
673 }
674
675 // also print IONameMatch keys
676 if ( mkey->isEqualTo ("IONameMatch") ) {
677 ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
678 if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
679 }
680
681 // also print IONameMatched keys
682
683 if ( mkey->isEqualTo ("IONameMatched") ) {
684 ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
685 if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
686 }
687
688 #if 0
689 // print clock-id
690
691 if ( mkey->isEqualTo ("AAPL,clock-id") ) {
692 char * cstr;
693 cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id"));
694 if (cstr)
695 kprintf (" ===> AAPL,clock-id is %s\n", cstr );
696 }
697 #endif
698
699 // print name
700
701 if ( mkey->isEqualTo ("name") ) {
702 char nameStr[64];
703 nameStr[0] = 0;
704 getCStringForObject(inDictionary->getObject("name"), nameStr,
705 sizeof(nameStr));
706 if (strlen(nameStr) > 0)
707 IOLog ("%s name is %s\n", inMsg, nameStr);
708 }
709
710 mkey = (OSSymbol *) mcoll->getNextObject ();
711
712 i++;
713 }
714
715 mcoll->release ();
716 }
717
718 static void
719 getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen)
720 {
721 char * buffer;
722 unsigned int len, i;
723
724 if ( (NULL == inObj) || (NULL == outStr))
725 return;
726
727 char * objString = (char *) (inObj->getMetaClass())->getClassName();
728
729 if ((0 == strncmp(objString, "OSString", sizeof("OSString"))) ||
730 (0 == strncmp(objString, "OSSymbol", sizeof("OSSymbol"))))
731 strlcpy(outStr, ((OSString *)inObj)->getCStringNoCopy(), outStrLen);
732
733 else if (0 == strncmp(objString, "OSData", sizeof("OSData"))) {
734 len = ((OSData *)inObj)->getLength();
735 buffer = (char *)((OSData *)inObj)->getBytesNoCopy();
736 if (buffer && (len > 0)) {
737 for (i=0; i < len; i++) {
738 outStr[i] = buffer[i];
739 }
740 outStr[len] = 0;
741 }
742 }
743 }
744
745 /* IOShutdownNotificationsTimedOut
746 * - Called from a timer installed by PEHaltRestart
747 */
748 static void IOShutdownNotificationsTimedOut(
749 thread_call_param_t p0,
750 thread_call_param_t p1)
751 {
752 #ifdef CONFIG_EMBEDDED
753 /* 30 seconds has elapsed - panic */
754 panic("Halt/Restart Timed Out");
755
756 #else /* ! CONFIG_EMBEDDED */
757 int type = (int)(long)p0;
758
759 /* 30 seconds has elapsed - resume shutdown */
760 if(gIOPlatform) gIOPlatform->haltRestart(type);
761 #endif /* CONFIG_EMBEDDED */
762 }
763
764
765 extern "C" {
766
767 /*
768 * Callouts from BSD for machine name & model
769 */
770
771 boolean_t PEGetMachineName( char * name, int maxLength )
772 {
773 if( gIOPlatform)
774 return( gIOPlatform->getMachineName( name, maxLength ));
775 else
776 return( false );
777 }
778
779 boolean_t PEGetModelName( char * name, int maxLength )
780 {
781 if( gIOPlatform)
782 return( gIOPlatform->getModelName( name, maxLength ));
783 else
784 return( false );
785 }
786
787 int PEGetPlatformEpoch(void)
788 {
789 if( gIOPlatform)
790 return( gIOPlatform->getBootROMType());
791 else
792 return( -1 );
793 }
794
795 int PEHaltRestart(unsigned int type)
796 {
797 IOPMrootDomain *pmRootDomain;
798 AbsoluteTime deadline;
799 thread_call_t shutdown_hang;
800
801 if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU)
802 {
803 pmRootDomain = IOService::getPMRootDomain();
804 /* Notify IOKit PM clients of shutdown/restart
805 Clients subscribe to this message with a call to
806 IOService::registerInterest()
807 */
808
809 /* Spawn a thread that will panic in 30 seconds.
810 If all goes well the machine will be off by the time
811 the timer expires.
812 */
813 shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut,
814 (thread_call_param_t) type);
815 clock_interval_to_deadline( 30, kSecondScale, &deadline );
816 thread_call_enter1_delayed( shutdown_hang, 0, deadline );
817
818 pmRootDomain->handlePlatformHaltRestart(type);
819 /* This notification should have few clients who all do
820 their work synchronously.
821
822 In this "shutdown notification" context we don't give
823 drivers the option of working asynchronously and responding
824 later. PM internals make it very hard to wait for asynchronous
825 replies.
826 */
827 }
828
829 if (gIOPlatform) return gIOPlatform->haltRestart(type);
830 else return -1;
831 }
832
833 UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
834 {
835 if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
836 else return 0;
837 }
838
839
840
841 inline static int init_gIOOptionsEntry(void)
842 {
843 IORegistryEntry *entry;
844 void *nvram_entry;
845 volatile void **options;
846 int ret = -1;
847
848 if (gIOOptionsEntry)
849 return 0;
850
851 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
852 if (!entry)
853 return -1;
854
855 nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
856 if (!nvram_entry)
857 goto release;
858
859 options = (volatile void **) &gIOOptionsEntry;
860 if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
861 ret = 0;
862 goto release;
863 }
864
865 return 0;
866
867 release:
868 entry->release();
869 return ret;
870
871 }
872
873 /* pass in a NULL value if you just want to figure out the len */
874 boolean_t PEReadNVRAMProperty(const char *symbol, void *value,
875 unsigned int *len)
876 {
877 OSObject *obj;
878 OSData *data;
879 unsigned int vlen;
880
881 if (!symbol || !len)
882 goto err;
883
884 if (init_gIOOptionsEntry() < 0)
885 goto err;
886
887 vlen = *len;
888 *len = 0;
889
890 obj = gIOOptionsEntry->getProperty(symbol);
891 if (!obj)
892 goto err;
893
894 /* convert to data */
895 data = OSDynamicCast(OSData, obj);
896 if (!data)
897 goto err;
898
899 *len = data->getLength();
900 vlen = min(vlen, *len);
901 if (vlen)
902 memcpy((void *) value, data->getBytesNoCopy(), vlen);
903
904 return TRUE;
905
906 err:
907 return FALSE;
908 }
909
910
911 boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value,
912 const unsigned int len)
913 {
914 const OSSymbol *sym;
915 OSData *data;
916 bool ret = false;
917
918 if (!symbol || !value || !len)
919 goto err;
920
921 if (init_gIOOptionsEntry() < 0)
922 goto err;
923
924 sym = OSSymbol::withCStringNoCopy(symbol);
925 if (!sym)
926 goto err;
927
928 data = OSData::withBytes((void *) value, len);
929 if (!data)
930 goto sym_done;
931
932 ret = gIOOptionsEntry->setProperty(sym, data);
933 data->release();
934
935 sym_done:
936 sym->release();
937
938 if (ret == true) {
939 gIOOptionsEntry->sync();
940 return TRUE;
941 }
942
943 err:
944 return FALSE;
945 }
946
947
948 long PEGetGMTTimeOfDay(void)
949 {
950 long result = 0;
951
952 if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay();
953
954 return (result);
955 }
956
957 void PESetGMTTimeOfDay(long secs)
958 {
959 if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(secs);
960 }
961
962 } /* extern "C" */
963
964 void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
965 {
966 OSData * data;
967 IORegistryEntry * entry;
968 OSString * string = 0;
969 uuid_string_t uuid;
970
971 #if CONFIG_EMBEDDED
972 entry = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
973 if ( entry )
974 {
975 OSData * data1;
976
977 data1 = OSDynamicCast( OSData, entry->getProperty( "unique-chip-id" ) );
978 if ( data1 && data1->getLength( ) == 8 )
979 {
980 OSData * data2;
981
982 data2 = OSDynamicCast( OSData, entry->getProperty( "chip-id" ) );
983 if ( data2 && data2->getLength( ) == 4 )
984 {
985 SHA1_CTX context;
986 uint8_t digest[ SHA_DIGEST_LENGTH ];
987 const uuid_t space = { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
988
989 SHA1Init( &context );
990 SHA1Update( &context, space, sizeof( space ) );
991 SHA1Update( &context, data1->getBytesNoCopy( ), data1->getLength( ) );
992 SHA1Update( &context, data2->getBytesNoCopy( ), data2->getLength( ) );
993 SHA1Final( digest, &context );
994
995 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50;
996 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80;
997
998 uuid_unparse( digest, uuid );
999 string = OSString::withCString( uuid );
1000 }
1001 }
1002
1003 entry->release( );
1004 }
1005 #else /* !CONFIG_EMBEDDED */
1006 entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
1007 if ( entry )
1008 {
1009 data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) );
1010 if ( data && data->getLength( ) == 16 )
1011 {
1012 SHA1_CTX context;
1013 uint8_t digest[ SHA_DIGEST_LENGTH ];
1014 const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
1015
1016 SHA1Init( &context );
1017 SHA1Update( &context, space, sizeof( space ) );
1018 SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) );
1019 SHA1Final( digest, &context );
1020
1021 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50;
1022 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80;
1023
1024 uuid_unparse( digest, uuid );
1025 string = OSString::withCString( uuid );
1026 }
1027
1028 entry->release( );
1029 }
1030 #endif /* !CONFIG_EMBEDDED */
1031
1032 if ( string == 0 )
1033 {
1034 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1035 if ( entry )
1036 {
1037 data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) );
1038 if ( data && data->getLength( ) == sizeof( uuid_t ) )
1039 {
1040 uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid );
1041 string = OSString::withCString( uuid );
1042 }
1043
1044 entry->release( );
1045 }
1046 }
1047
1048 if ( string )
1049 {
1050 getProvider( )->setProperty( kIOPlatformUUIDKey, string );
1051 publishResource( kIOPlatformUUIDKey, string );
1052
1053 string->release( );
1054 }
1055
1056 publishResource("IONVRAM");
1057 }
1058
1059 IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
1060 bool waitForFunction,
1061 void *param1, void *param2,
1062 void *param3, void *param4)
1063 {
1064 IOService *service, *_resources;
1065
1066 if (waitForFunction) {
1067 _resources = waitForService(resourceMatching(functionName));
1068 } else {
1069 _resources = getResourceService();
1070 }
1071 if (_resources == 0) return kIOReturnUnsupported;
1072
1073 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
1074 if (service == 0) return kIOReturnUnsupported;
1075
1076 return service->callPlatformFunction(functionName, waitForFunction,
1077 param1, param2, param3, param4);
1078 }
1079
1080 IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1081 {
1082 return 0;
1083 }
1084
1085 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1086
1087 #undef super
1088 #define super IOPlatformExpert
1089
1090 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
1091
1092 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
1093 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
1094 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
1095 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
1096 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
1097 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
1098 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
1099 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
1100
1101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1102
1103 IOService * IODTPlatformExpert::probe( IOService * provider,
1104 SInt32 * score )
1105 {
1106 if( !super::probe( provider, score))
1107 return( 0 );
1108
1109 // check machine types
1110 if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
1111 return( 0 );
1112
1113 return( this);
1114 }
1115
1116 bool IODTPlatformExpert::configure( IOService * provider )
1117 {
1118 if( !super::configure( provider))
1119 return( false);
1120
1121 processTopLevel( provider );
1122
1123 return( true );
1124 }
1125
1126 IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
1127 {
1128 IOService * nub;
1129
1130 nub = new IOPlatformDevice;
1131 if( nub) {
1132 if( !nub->init( from, gIODTPlane )) {
1133 nub->free();
1134 nub = 0;
1135 }
1136 }
1137 return( nub);
1138 }
1139
1140 bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
1141 {
1142 IORegistryEntry * next;
1143 IOService * nub;
1144 bool ok = true;
1145
1146 if( iter) {
1147 while( (next = (IORegistryEntry *) iter->getNextObject())) {
1148
1149 if( 0 == (nub = createNub( next )))
1150 continue;
1151
1152 nub->attach( parent );
1153 nub->registerService();
1154 }
1155 iter->release();
1156 }
1157
1158 return( ok );
1159 }
1160
1161 void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
1162 {
1163 OSIterator * kids;
1164 IORegistryEntry * next;
1165 IORegistryEntry * cpus;
1166 IORegistryEntry * options;
1167
1168 // infanticide
1169 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
1170 if( kids) {
1171 while( (next = (IORegistryEntry *)kids->getNextObject())) {
1172 next->detachAll( gIODTPlane);
1173 }
1174 kids->release();
1175 }
1176
1177 // Publish an IODTNVRAM class on /options.
1178 options = rootEntry->childFromPath("options", gIODTPlane);
1179 if (options) {
1180 dtNVRAM = new IODTNVRAM;
1181 if (dtNVRAM) {
1182 if (!dtNVRAM->init(options, gIODTPlane)) {
1183 dtNVRAM->release();
1184 dtNVRAM = 0;
1185 } else {
1186 dtNVRAM->attach(this);
1187 dtNVRAM->registerService();
1188 }
1189 }
1190 }
1191
1192 // Publish the cpus.
1193 cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
1194 if ( cpus)
1195 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
1196
1197 // publish top level, minus excludeList
1198 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
1199 }
1200
1201 IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
1202 {
1203 if( nub->getDeviceMemory())
1204 return( kIOReturnSuccess );
1205
1206 IODTResolveAddressing( nub, "reg", 0);
1207
1208 return( kIOReturnSuccess);
1209 }
1210
1211 bool IODTPlatformExpert::compareNubName( const IOService * nub,
1212 OSString * name, OSString ** matched ) const
1213 {
1214 return( IODTCompareNubName( nub, name, matched )
1215 || super::compareNubName( nub, name, matched) );
1216 }
1217
1218 bool IODTPlatformExpert::getModelName( char * name, int maxLength )
1219 {
1220 OSData * prop;
1221 const char * str;
1222 int len;
1223 char c;
1224 bool ok = false;
1225
1226 maxLength--;
1227
1228 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
1229 if( prop ) {
1230 str = (const char *) prop->getBytesNoCopy();
1231
1232 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
1233 str += strlen( "AAPL," );
1234
1235 len = 0;
1236 while( (c = *str++)) {
1237 if( (c == '/') || (c == ' '))
1238 c = '-';
1239
1240 name[ len++ ] = c;
1241 if( len >= maxLength)
1242 break;
1243 }
1244
1245 name[ len ] = 0;
1246 ok = true;
1247 }
1248 return( ok );
1249 }
1250
1251 bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
1252 {
1253 OSData * prop;
1254 bool ok = false;
1255
1256 maxLength--;
1257 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
1258 ok = (0 != prop);
1259
1260 if( ok )
1261 strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
1262
1263 return( ok );
1264 }
1265
1266 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1267
1268 void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
1269 {
1270 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
1271
1272 super::registerNVRAMController(nvram);
1273 }
1274
1275 int IODTPlatformExpert::haltRestart(unsigned int type)
1276 {
1277 if (dtNVRAM) dtNVRAM->sync();
1278
1279 return super::haltRestart(type);
1280 }
1281
1282 IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
1283 IOByteCount length)
1284 {
1285 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
1286 else return kIOReturnNotReady;
1287 }
1288
1289 IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
1290 IOByteCount length)
1291 {
1292 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
1293 else return kIOReturnNotReady;
1294 }
1295
1296 IOReturn IODTPlatformExpert::readNVRAMProperty(
1297 IORegistryEntry * entry,
1298 const OSSymbol ** name, OSData ** value )
1299 {
1300 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
1301 else return kIOReturnNotReady;
1302 }
1303
1304 IOReturn IODTPlatformExpert::writeNVRAMProperty(
1305 IORegistryEntry * entry,
1306 const OSSymbol * name, OSData * value )
1307 {
1308 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
1309 else return kIOReturnNotReady;
1310 }
1311
1312 OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
1313 {
1314 if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
1315 else return 0;
1316 }
1317
1318 IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
1319 IOByteCount offset, UInt8 * buffer,
1320 IOByteCount length)
1321 {
1322 if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
1323 buffer, length);
1324 else return kIOReturnNotReady;
1325 }
1326
1327 IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
1328 IOByteCount offset, UInt8 * buffer,
1329 IOByteCount length)
1330 {
1331 if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
1332 buffer, length);
1333 else return kIOReturnNotReady;
1334 }
1335
1336 IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1337 {
1338 IOByteCount lengthSaved = 0;
1339
1340 if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
1341
1342 if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
1343
1344 return lengthSaved;
1345 }
1346
1347 OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) {
1348 UInt8* serialNumber;
1349 unsigned int serialNumberSize;
1350 unsigned short pos = 0;
1351 char* temp;
1352 char SerialNo[30];
1353
1354 if (myProperty != NULL) {
1355 serialNumberSize = myProperty->getLength();
1356 serialNumber = (UInt8*)(myProperty->getBytesNoCopy());
1357 temp = (char*)serialNumber;
1358 if (serialNumberSize > 0) {
1359 // check to see if this is a CTO serial number...
1360 while (pos < serialNumberSize && temp[pos] != '-') pos++;
1361
1362 if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number
1363 memcpy(SerialNo, serialNumber + 12, 8);
1364 memcpy(&SerialNo[8], serialNumber, 3);
1365 SerialNo[11] = '-';
1366 memcpy(&SerialNo[12], serialNumber + 3, 8);
1367 SerialNo[20] = 0;
1368 } else { // just a normal serial number
1369 memcpy(SerialNo, serialNumber + 13, 8);
1370 memcpy(&SerialNo[8], serialNumber, 3);
1371 SerialNo[11] = 0;
1372 }
1373 return OSString::withCString(SerialNo);
1374 }
1375 }
1376 return NULL;
1377 }
1378
1379
1380 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1381
1382 #undef super
1383 #define super IOService
1384
1385 OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
1386
1387 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
1388 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
1389 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
1390 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
1391
1392 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1393
1394 bool IOPlatformExpertDevice::compareName( OSString * name,
1395 OSString ** matched ) const
1396 {
1397 return( IODTCompareNubName( this, name, matched ));
1398 }
1399
1400 bool
1401 IOPlatformExpertDevice::initWithArgs(
1402 void * dtTop, void * p2, void * p3, void * p4 )
1403 {
1404 IORegistryEntry * dt = 0;
1405 void * argsData[ 4 ];
1406 bool ok;
1407
1408 // dtTop may be zero on non- device tree systems
1409 if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
1410 ok = super::init( dt, gIODTPlane );
1411 else
1412 ok = super::init();
1413
1414 if( !ok)
1415 return( false);
1416
1417 workLoop = IOWorkLoop::workLoop();
1418 if (!workLoop)
1419 return false;
1420
1421 argsData[ 0 ] = dtTop;
1422 argsData[ 1 ] = p2;
1423 argsData[ 2 ] = p3;
1424 argsData[ 3 ] = p4;
1425
1426 setProperty("IOPlatformArgs", (void *)argsData, sizeof(argsData));
1427
1428 return( true);
1429 }
1430
1431 IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
1432 {
1433 return workLoop;
1434 }
1435
1436 IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties )
1437 {
1438 OSDictionary * dictionary;
1439 OSObject * object;
1440 IOReturn status;
1441
1442 status = super::setProperties( properties );
1443 if ( status != kIOReturnUnsupported ) return status;
1444
1445 status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator );
1446 if ( status != kIOReturnSuccess ) return status;
1447
1448 dictionary = OSDynamicCast( OSDictionary, properties );
1449 if ( dictionary == 0 ) return kIOReturnBadArgument;
1450
1451 object = dictionary->getObject( kIOPlatformUUIDKey );
1452 if ( object )
1453 {
1454 IORegistryEntry * entry;
1455 OSString * string;
1456 uuid_t uuid;
1457
1458 string = ( OSString * ) getProperty( kIOPlatformUUIDKey );
1459 if ( string ) return kIOReturnNotPermitted;
1460
1461 string = OSDynamicCast( OSString, object );
1462 if ( string == 0 ) return kIOReturnBadArgument;
1463
1464 status = uuid_parse( string->getCStringNoCopy( ), uuid );
1465 if ( status != 0 ) return kIOReturnBadArgument;
1466
1467 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1468 if ( entry )
1469 {
1470 entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) );
1471 entry->release( );
1472 }
1473
1474 setProperty( kIOPlatformUUIDKey, string );
1475 publishResource( kIOPlatformUUIDKey, string );
1476
1477 return kIOReturnSuccess;
1478 }
1479
1480 return kIOReturnUnsupported;
1481 }
1482
1483 void IOPlatformExpertDevice::free()
1484 {
1485 if (workLoop)
1486 workLoop->release();
1487 }
1488
1489 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1490
1491 #undef super
1492 #define super IOService
1493
1494 OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1495
1496 OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1497 OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1498 OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1499 OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1500
1501 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1502
1503 bool IOPlatformDevice::compareName( OSString * name,
1504 OSString ** matched ) const
1505 {
1506 return( ((IOPlatformExpert *)getProvider())->
1507 compareNubName( this, name, matched ));
1508 }
1509
1510 IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
1511 {
1512 return( this );
1513 }
1514
1515 IOReturn IOPlatformDevice::getResources( void )
1516 {
1517 return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
1518 }
1519
1520 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1521
1522 /*********************************************************************
1523 * IOPanicPlatform class
1524 *
1525 * If no legitimate IOPlatformDevice matches, this one does and panics
1526 * the kernel with a suitable message.
1527 *********************************************************************/
1528
1529 class IOPanicPlatform : IOPlatformExpert {
1530 OSDeclareDefaultStructors(IOPanicPlatform);
1531
1532 public:
1533 bool start(IOService * provider);
1534 };
1535
1536
1537 OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1538
1539
1540 bool IOPanicPlatform::start(IOService * provider) {
1541 const char * platform_name = "(unknown platform name)";
1542
1543 if (provider) platform_name = provider->getName();
1544
1545 panic("Unable to find driver for this platform: \"%s\".\n",
1546 platform_name);
1547
1548 return false;
1549 }
1550