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