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