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