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