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