]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOPlatformExpert.cpp
xnu-3789.51.2.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 {
d190cdc3
A
825 // Do an initial sync to flush as much panic data as possible,
826 // in case we have a problem in one of the platorm panic handlers.
827 // After running the platform handlers, do a final sync w/
828 // platform hardware quiesced for the panic.
829 PE_sync_panic_buffers();
830 IOCPURunPlatformPanicActions(type);
831 PE_sync_panic_buffers();
3e170ce0 832 }
fa4905b1 833
1c79356b
A
834 if (gIOPlatform) return gIOPlatform->haltRestart(type);
835 else return -1;
836}
837
9bccf70c
A
838UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
839{
840 if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
841 else return 0;
842}
843
6d2010ae
A
844
845
846inline static int init_gIOOptionsEntry(void)
847{
848 IORegistryEntry *entry;
849 void *nvram_entry;
850 volatile void **options;
851 int ret = -1;
852
853 if (gIOOptionsEntry)
854 return 0;
855
856 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
857 if (!entry)
858 return -1;
859
860 nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
861 if (!nvram_entry)
862 goto release;
863
864 options = (volatile void **) &gIOOptionsEntry;
865 if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
866 ret = 0;
867 goto release;
868 }
869
870 return 0;
871
872release:
873 entry->release();
874 return ret;
875
876}
877
878/* pass in a NULL value if you just want to figure out the len */
879boolean_t PEReadNVRAMProperty(const char *symbol, void *value,
880 unsigned int *len)
881{
882 OSObject *obj;
883 OSData *data;
884 unsigned int vlen;
885
886 if (!symbol || !len)
887 goto err;
888
889 if (init_gIOOptionsEntry() < 0)
890 goto err;
891
892 vlen = *len;
893 *len = 0;
894
895 obj = gIOOptionsEntry->getProperty(symbol);
896 if (!obj)
897 goto err;
898
899 /* convert to data */
900 data = OSDynamicCast(OSData, obj);
901 if (!data)
902 goto err;
903
904 *len = data->getLength();
905 vlen = min(vlen, *len);
39236c6e 906 if (value && vlen)
6d2010ae
A
907 memcpy((void *) value, data->getBytesNoCopy(), vlen);
908
909 return TRUE;
910
911err:
912 return FALSE;
913}
914
3e170ce0
A
915boolean_t
916PEWriteNVRAMBooleanProperty(const char *symbol, boolean_t value)
917{
918 const OSSymbol *sym = NULL;
919 OSBoolean *data = NULL;
920 bool ret = false;
921
922 if (symbol == NULL) {
923 goto exit;
924 }
925
926 if (init_gIOOptionsEntry() < 0) {
927 goto exit;
928 }
929
930 if ((sym = OSSymbol::withCStringNoCopy(symbol)) == NULL) {
931 goto exit;
932 }
933
934 data = value ? kOSBooleanTrue : kOSBooleanFalse;
935 ret = gIOOptionsEntry->setProperty(sym, data);
936
937 sym->release();
938
939 /* success, force the NVRAM to flush writes */
940 if (ret == true) {
941 gIOOptionsEntry->sync();
942 }
943
944exit:
945 return ret;
946}
6d2010ae
A
947
948boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value,
949 const unsigned int len)
950{
951 const OSSymbol *sym;
952 OSData *data;
953 bool ret = false;
954
955 if (!symbol || !value || !len)
956 goto err;
957
958 if (init_gIOOptionsEntry() < 0)
959 goto err;
960
961 sym = OSSymbol::withCStringNoCopy(symbol);
962 if (!sym)
963 goto err;
964
965 data = OSData::withBytes((void *) value, len);
966 if (!data)
967 goto sym_done;
968
969 ret = gIOOptionsEntry->setProperty(sym, data);
970 data->release();
971
972sym_done:
973 sym->release();
974
975 if (ret == true) {
976 gIOOptionsEntry->sync();
977 return TRUE;
978 }
979
980err:
981 return FALSE;
982}
983
984
39236c6e
A
985boolean_t PERemoveNVRAMProperty(const char *symbol)
986{
987 const OSSymbol *sym;
988
989 if (!symbol)
990 goto err;
991
992 if (init_gIOOptionsEntry() < 0)
993 goto err;
994
995 sym = OSSymbol::withCStringNoCopy(symbol);
996 if (!sym)
997 goto err;
998
999 gIOOptionsEntry->removeProperty(sym);
1000
1001 sym->release();
1002
1003 gIOOptionsEntry->sync();
1004 return TRUE;
1005
1006err:
1007 return FALSE;
1008
1009}
1010
1c79356b
A
1011long PEGetGMTTimeOfDay(void)
1012{
fe8ab488
A
1013 clock_sec_t secs;
1014 clock_usec_t usecs;
0c530ab8 1015
fe8ab488
A
1016 PEGetUTCTimeOfDay(&secs, &usecs);
1017 return secs;
1c79356b
A
1018}
1019
1020void PESetGMTTimeOfDay(long secs)
1021{
fe8ab488
A
1022 PESetUTCTimeOfDay(secs, 0);
1023}
1024
1025void PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs)
1026{
1027 clock_nsec_t nsecs = 0;
1028
1029 *secs = 0;
1030 if (gIOPlatform)
1031 gIOPlatform->getUTCTimeOfDay(secs, &nsecs);
1032
1033 assert(nsecs < NSEC_PER_SEC);
1034 *usecs = nsecs / NSEC_PER_USEC;
1035}
1036
1037void PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs)
1038{
1039 assert(usecs < USEC_PER_SEC);
1040 if (gIOPlatform)
1041 gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC);
1c79356b
A
1042}
1043
1044} /* extern "C" */
1045
1046void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
1047{
2d21ac55 1048 OSData * data;
4a3eedf9
A
1049 IORegistryEntry * entry;
1050 OSString * string = 0;
b0d623f7 1051 uuid_string_t uuid;
2d21ac55 1052
4a3eedf9
A
1053 entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
1054 if ( entry )
2d21ac55 1055 {
4a3eedf9
A
1056 data = OSDynamicCast( OSData, entry->getProperty( "system-id" ) );
1057 if ( data && data->getLength( ) == 16 )
2d21ac55 1058 {
4a3eedf9
A
1059 SHA1_CTX context;
1060 uint8_t digest[ SHA_DIGEST_LENGTH ];
1061 const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
2d21ac55 1062
4a3eedf9
A
1063 SHA1Init( &context );
1064 SHA1Update( &context, space, sizeof( space ) );
1065 SHA1Update( &context, data->getBytesNoCopy( ), data->getLength( ) );
1066 SHA1Final( digest, &context );
1067
1068 digest[ 6 ] = ( digest[ 6 ] & 0x0F ) | 0x50;
1069 digest[ 8 ] = ( digest[ 8 ] & 0x3F ) | 0x80;
1070
1071 uuid_unparse( digest, uuid );
2d21ac55 1072 string = OSString::withCString( uuid );
4a3eedf9 1073 }
2d21ac55 1074
4a3eedf9
A
1075 entry->release( );
1076 }
1077
1078 if ( string == 0 )
1079 {
1080 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1081 if ( entry )
1082 {
1083 data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ) );
1084 if ( data && data->getLength( ) == sizeof( uuid_t ) )
1085 {
1086 uuid_unparse( ( uint8_t * ) data->getBytesNoCopy( ), uuid );
1087 string = OSString::withCString( uuid );
2d21ac55 1088 }
4a3eedf9
A
1089
1090 entry->release( );
2d21ac55 1091 }
4a3eedf9
A
1092 }
1093
1094 if ( string )
1095 {
1096 getProvider( )->setProperty( kIOPlatformUUIDKey, string );
1097 publishResource( kIOPlatformUUIDKey, string );
2d21ac55 1098
4a3eedf9 1099 string->release( );
2d21ac55
A
1100 }
1101
1c79356b
A
1102 publishResource("IONVRAM");
1103}
1104
1105IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
1106 bool waitForFunction,
1107 void *param1, void *param2,
1108 void *param3, void *param4)
1109{
1110 IOService *service, *_resources;
1111
1112 if (waitForFunction) {
1113 _resources = waitForService(resourceMatching(functionName));
1114 } else {
b0d623f7 1115 _resources = getResourceService();
1c79356b
A
1116 }
1117 if (_resources == 0) return kIOReturnUnsupported;
1118
1119 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
1120 if (service == 0) return kIOReturnUnsupported;
1121
1122 return service->callPlatformFunction(functionName, waitForFunction,
1123 param1, param2, param3, param4);
1124}
1125
9bccf70c
A
1126IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1127{
1128 return 0;
1129}
1c79356b
A
1130
1131/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1132
1133#undef super
1134#define super IOPlatformExpert
1135
1136OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
1137
1138OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
1139OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
1140OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
1141OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
1142OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
1143OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
1144OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
1145OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
1146
1147/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1148
1149IOService * IODTPlatformExpert::probe( IOService * provider,
1150 SInt32 * score )
1151{
1152 if( !super::probe( provider, score))
1153 return( 0 );
1154
1155 // check machine types
1156 if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
1157 return( 0 );
1158
1159 return( this);
1160}
1161
1162bool IODTPlatformExpert::configure( IOService * provider )
1163{
1164 if( !super::configure( provider))
1165 return( false);
1166
1167 processTopLevel( provider );
1168
1169 return( true );
1170}
1171
1172IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
1173{
1174 IOService * nub;
1175
1176 nub = new IOPlatformDevice;
1177 if( nub) {
1178 if( !nub->init( from, gIODTPlane )) {
1179 nub->free();
1180 nub = 0;
1181 }
1182 }
1183 return( nub);
1184}
1185
1186bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
1187{
1188 IORegistryEntry * next;
1189 IOService * nub;
1190 bool ok = true;
1191
1192 if( iter) {
1193 while( (next = (IORegistryEntry *) iter->getNextObject())) {
1194
1195 if( 0 == (nub = createNub( next )))
1196 continue;
1197
1198 nub->attach( parent );
1199 nub->registerService();
1200 }
1201 iter->release();
1202 }
1203
1204 return( ok );
1205}
1206
91447636 1207void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
1c79356b
A
1208{
1209 OSIterator * kids;
1210 IORegistryEntry * next;
1211 IORegistryEntry * cpus;
1212 IORegistryEntry * options;
1213
1214 // infanticide
91447636 1215 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
1c79356b
A
1216 if( kids) {
1217 while( (next = (IORegistryEntry *)kids->getNextObject())) {
1218 next->detachAll( gIODTPlane);
1219 }
1220 kids->release();
1221 }
1222
1223 // Publish an IODTNVRAM class on /options.
91447636 1224 options = rootEntry->childFromPath("options", gIODTPlane);
1c79356b
A
1225 if (options) {
1226 dtNVRAM = new IODTNVRAM;
1227 if (dtNVRAM) {
1228 if (!dtNVRAM->init(options, gIODTPlane)) {
1229 dtNVRAM->release();
1230 dtNVRAM = 0;
1231 } else {
1232 dtNVRAM->attach(this);
1233 dtNVRAM->registerService();
3e170ce0 1234 options->release();
1c79356b
A
1235 }
1236 }
1237 }
1238
1239 // Publish the cpus.
91447636 1240 cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
1c79356b 1241 if ( cpus)
3e170ce0 1242 {
1c79356b 1243 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
3e170ce0
A
1244 cpus->release();
1245 }
1c79356b
A
1246
1247 // publish top level, minus excludeList
91447636 1248 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
1c79356b
A
1249}
1250
1251IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
1252{
1253 if( nub->getDeviceMemory())
1254 return( kIOReturnSuccess );
1255
1256 IODTResolveAddressing( nub, "reg", 0);
1257
1258 return( kIOReturnSuccess);
1259}
1260
1261bool IODTPlatformExpert::compareNubName( const IOService * nub,
1262 OSString * name, OSString ** matched ) const
1263{
1264 return( IODTCompareNubName( nub, name, matched )
1265 || super::compareNubName( nub, name, matched) );
1266}
1267
1268bool IODTPlatformExpert::getModelName( char * name, int maxLength )
1269{
1270 OSData * prop;
1271 const char * str;
1272 int len;
1273 char c;
1274 bool ok = false;
1275
1276 maxLength--;
1277
1278 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
1279 if( prop ) {
1280 str = (const char *) prop->getBytesNoCopy();
1281
1282 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
1283 str += strlen( "AAPL," );
1284
1285 len = 0;
1286 while( (c = *str++)) {
1287 if( (c == '/') || (c == ' '))
1288 c = '-';
1289
1290 name[ len++ ] = c;
1291 if( len >= maxLength)
1292 break;
1293 }
1294
1295 name[ len ] = 0;
1296 ok = true;
1297 }
1298 return( ok );
1299}
1300
1301bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
1302{
1303 OSData * prop;
1304 bool ok = false;
1305
1306 maxLength--;
1307 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
1308 ok = (0 != prop);
1309
1310 if( ok )
2d21ac55 1311 strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
1c79356b
A
1312
1313 return( ok );
1314}
1315
1316/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1317
1318void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
1319{
1320 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
1321
1322 super::registerNVRAMController(nvram);
1323}
1324
1325int IODTPlatformExpert::haltRestart(unsigned int type)
1326{
1327 if (dtNVRAM) dtNVRAM->sync();
1328
1329 return super::haltRestart(type);
1330}
1331
1332IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
1333 IOByteCount length)
1334{
1335 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
1336 else return kIOReturnNotReady;
1337}
1338
1339IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
1340 IOByteCount length)
1341{
1342 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
1343 else return kIOReturnNotReady;
1344}
1345
1346IOReturn IODTPlatformExpert::readNVRAMProperty(
1347 IORegistryEntry * entry,
1348 const OSSymbol ** name, OSData ** value )
1349{
1350 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
1351 else return kIOReturnNotReady;
1352}
1353
1354IOReturn IODTPlatformExpert::writeNVRAMProperty(
1355 IORegistryEntry * entry,
1356 const OSSymbol * name, OSData * value )
1357{
1358 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
1359 else return kIOReturnNotReady;
1360}
1361
d52fe63f
A
1362OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
1363{
1364 if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
1365 else return 0;
1366}
1367
1368IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
1369 IOByteCount offset, UInt8 * buffer,
1370 IOByteCount length)
1371{
1372 if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
1373 buffer, length);
1374 else return kIOReturnNotReady;
1375}
1376
1377IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
1378 IOByteCount offset, UInt8 * buffer,
1379 IOByteCount length)
1380{
1381 if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
1382 buffer, length);
1383 else return kIOReturnNotReady;
1384}
1385
9bccf70c
A
1386IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1387{
1388 IOByteCount lengthSaved = 0;
1389
1390 if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
1391
1392 if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
1393
1394 return lengthSaved;
1395}
d52fe63f 1396
55e303ae
A
1397OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) {
1398 UInt8* serialNumber;
1399 unsigned int serialNumberSize;
91447636 1400 unsigned short pos = 0;
55e303ae
A
1401 char* temp;
1402 char SerialNo[30];
1403
1404 if (myProperty != NULL) {
1405 serialNumberSize = myProperty->getLength();
1406 serialNumber = (UInt8*)(myProperty->getBytesNoCopy());
91447636 1407 temp = (char*)serialNumber;
55e303ae
A
1408 if (serialNumberSize > 0) {
1409 // check to see if this is a CTO serial number...
1410 while (pos < serialNumberSize && temp[pos] != '-') pos++;
1411
1412 if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number
1413 memcpy(SerialNo, serialNumber + 12, 8);
1414 memcpy(&SerialNo[8], serialNumber, 3);
1415 SerialNo[11] = '-';
1416 memcpy(&SerialNo[12], serialNumber + 3, 8);
1417 SerialNo[20] = 0;
1418 } else { // just a normal serial number
1419 memcpy(SerialNo, serialNumber + 13, 8);
1420 memcpy(&SerialNo[8], serialNumber, 3);
1421 SerialNo[11] = 0;
1422 }
1423 return OSString::withCString(SerialNo);
1424 }
1425 }
1426 return NULL;
1427}
1428
1429
1c79356b
A
1430/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1431
1432#undef super
1433#define super IOService
1434
1435OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
1436
1437OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
1438OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
1439OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
1440OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
1441
1442/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1443
1444bool IOPlatformExpertDevice::compareName( OSString * name,
55e303ae 1445 OSString ** matched ) const
1c79356b
A
1446{
1447 return( IODTCompareNubName( this, name, matched ));
1448}
1449
1450bool
1451IOPlatformExpertDevice::initWithArgs(
1452 void * dtTop, void * p2, void * p3, void * p4 )
1453{
1454 IORegistryEntry * dt = 0;
1c79356b
A
1455 bool ok;
1456
1457 // dtTop may be zero on non- device tree systems
1458 if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
1459 ok = super::init( dt, gIODTPlane );
1460 else
1461 ok = super::init();
1462
1463 if( !ok)
1464 return( false);
1465
39236c6e 1466 reserved = NULL;
1c79356b
A
1467 workLoop = IOWorkLoop::workLoop();
1468 if (!workLoop)
1469 return false;
1470
1c79356b
A
1471 return( true);
1472}
1473
1474IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
1475{
1476 return workLoop;
1477}
1478
2d21ac55 1479IOReturn IOPlatformExpertDevice::setProperties( OSObject * properties )
1c79356b 1480{
2d21ac55
A
1481 OSDictionary * dictionary;
1482 OSObject * object;
1483 IOReturn status;
1484
1485 status = super::setProperties( properties );
1486 if ( status != kIOReturnUnsupported ) return status;
1487
1488 status = IOUserClient::clientHasPrivilege( current_task( ), kIOClientPrivilegeAdministrator );
1489 if ( status != kIOReturnSuccess ) return status;
1490
1491 dictionary = OSDynamicCast( OSDictionary, properties );
1492 if ( dictionary == 0 ) return kIOReturnBadArgument;
1493
1494 object = dictionary->getObject( kIOPlatformUUIDKey );
1495 if ( object )
1496 {
4a3eedf9 1497 IORegistryEntry * entry;
2d21ac55
A
1498 OSString * string;
1499 uuid_t uuid;
1500
1501 string = ( OSString * ) getProperty( kIOPlatformUUIDKey );
1502 if ( string ) return kIOReturnNotPermitted;
1503
1504 string = OSDynamicCast( OSString, object );
1505 if ( string == 0 ) return kIOReturnBadArgument;
1506
1507 status = uuid_parse( string->getCStringNoCopy( ), uuid );
1508 if ( status != 0 ) return kIOReturnBadArgument;
1509
4a3eedf9
A
1510 entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
1511 if ( entry )
2d21ac55 1512 {
4a3eedf9
A
1513 entry->setProperty( "platform-uuid", uuid, sizeof( uuid_t ) );
1514 entry->release( );
2d21ac55
A
1515 }
1516
1517 setProperty( kIOPlatformUUIDKey, string );
1518 publishResource( kIOPlatformUUIDKey, string );
1519
1520 return kIOReturnSuccess;
1521 }
1522
1523 return kIOReturnUnsupported;
1c79356b
A
1524}
1525
3e170ce0
A
1526IOReturn IOPlatformExpertDevice::newUserClient( task_t owningTask, void * securityID,
1527 UInt32 type, OSDictionary * properties,
1528 IOUserClient ** handler )
1529{
1530 IOReturn err = kIOReturnSuccess;
1531 IOUserClient * newConnect = 0;
1532 IOUserClient * theConnect = 0;
1533
1534 switch (type)
1535 {
1536 case kIOKitDiagnosticsClientType:
1537 newConnect = IOKitDiagnosticsClient::withTask(owningTask);
1538 if (!newConnect) err = kIOReturnNotPermitted;
1539 break;
1540 default:
1541 err = kIOReturnBadArgument;
1542 }
1543
1544 if (newConnect)
1545 {
1546 if ((false == newConnect->attach(this))
1547 || (false == newConnect->start(this)))
1548 {
1549 newConnect->detach( this );
1550 newConnect->release();
39037602 1551 err = kIOReturnNotPermitted;
3e170ce0
A
1552 }
1553 else
1554 theConnect = newConnect;
1555 }
1556
1557 *handler = theConnect;
1558 return (err);
1559}
1560
2d21ac55 1561void IOPlatformExpertDevice::free()
0c530ab8 1562{
2d21ac55
A
1563 if (workLoop)
1564 workLoop->release();
0c530ab8
A
1565}
1566
1c79356b
A
1567/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1568
1569#undef super
1570#define super IOService
1571
1572OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1573
1574OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1575OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1576OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1577OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1578
1579/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1580
1581bool IOPlatformDevice::compareName( OSString * name,
55e303ae 1582 OSString ** matched ) const
1c79356b
A
1583{
1584 return( ((IOPlatformExpert *)getProvider())->
1585 compareNubName( this, name, matched ));
1586}
1587
1588IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
1589{
1590 return( this );
1591}
1592
1593IOReturn IOPlatformDevice::getResources( void )
1594{
1595 return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
1596}
1597
1598/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1599
1600/*********************************************************************
1601* IOPanicPlatform class
1602*
1603* If no legitimate IOPlatformDevice matches, this one does and panics
1604* the kernel with a suitable message.
1605*********************************************************************/
1606
1607class IOPanicPlatform : IOPlatformExpert {
1608 OSDeclareDefaultStructors(IOPanicPlatform);
1609
1610public:
3e170ce0 1611 bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
1c79356b
A
1612};
1613
1614
1615OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1616
1617
1618bool IOPanicPlatform::start(IOService * provider) {
1619 const char * platform_name = "(unknown platform name)";
1620
1621 if (provider) platform_name = provider->getName();
1622
1623 panic("Unable to find driver for this platform: \"%s\".\n",
1624 platform_name);
1625
1626 return false;
1627}
b0d623f7 1628