IOPlatformExpert.cpp [plain text]
#include <IOKit/IOCPU.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IOKitDebug.h>
#include <IOKit/IOMapper.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IONVRAM.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/IORangeAllocator.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOTimeStamp.h>
#include <IOKit/system.h>
#include <libkern/c++/OSContainers.h>
extern "C" {
#include <machine/machine_routines.h>
#include <pexpert/pexpert.h>
}
void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
static void getCStringForObject (OSObject * inObj, char * outStr);
#define super IOService
OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
OSMetaClassDefineReservedUsed(IOPlatformExpert, 1);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 2);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 3);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 4);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 5);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 6);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 7);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 8);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 9);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 10);
OSMetaClassDefineReservedUnused(IOPlatformExpert, 11);
static IOPlatformExpert * gIOPlatform;
static OSDictionary * gIOInterruptControllers;
static IOLock * gIOInterruptControllersLock;
OSSymbol * gPlatformInterruptControllerName;
bool IOPlatformExpert::attach( IOService * provider )
{
if( !super::attach( provider ))
return( false);
return( true);
}
bool IOPlatformExpert::start( IOService * provider )
{
IORangeAllocator * physicalRanges;
OSData * busFrequency;
if (!super::start(provider))
return false;
#if 1
IORegistryEntry * regEntry = IORegistryEntry::fromPath("/u3/dart", gIODTPlane);
if (!regEntry)
regEntry = IORegistryEntry::fromPath("/dart", gIODTPlane);
if (regEntry) {
int debugFlags;
if (!PE_parse_boot_arg("dart", &debugFlags) || debugFlags)
setProperty(kIOPlatformMapperPresentKey, kOSBooleanTrue);
regEntry->release();
}
#endif
IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey));
gIOInterruptControllers = OSDictionary::withCapacity(1);
gIOInterruptControllersLock = IOLockAlloc();
busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
provider->setProperty("clock-frequency", busFrequency);
busFrequency->release();
gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16,
IORangeAllocator::kLocking);
assert(physicalRanges);
setProperty("Platform Memory Ranges", physicalRanges);
setPlatform( this );
gIOPlatform = this;
PMInstantiatePowerDomains();
OSData* mydata = (OSData*) (provider->getProperty("serial-number"));
if (mydata != NULL) {
OSString *serNoString = createSystemSerialNumberString(mydata);
if (serNoString != NULL) {
provider->setProperty(kIOPlatformSerialNumberKey, serNoString);
serNoString->release();
}
}
return( configure(provider) );
}
bool IOPlatformExpert::configure( IOService * provider )
{
OSSet * topLevel;
OSDictionary * dict;
IOService * nub;
topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
if( topLevel) {
while( (dict = OSDynamicCast( OSDictionary,
topLevel->getAnyObject()))) {
dict->retain();
topLevel->removeObject( dict );
nub = createNub( dict );
if( 0 == nub)
continue;
dict->release();
nub->attach( this );
nub->registerService();
}
}
return( true );
}
IOService * IOPlatformExpert::createNub( OSDictionary * from )
{
IOService * nub;
nub = new IOPlatformDevice;
if(nub) {
if( !nub->init( from )) {
nub->release();
nub = 0;
}
}
return( nub);
}
bool IOPlatformExpert::compareNubName( const IOService * nub,
OSString * name, OSString ** matched ) const
{
return( nub->IORegistryEntry::compareName( name, matched ));
}
IOReturn IOPlatformExpert::getNubResources( IOService * nub )
{
return( kIOReturnSuccess );
}
long IOPlatformExpert::getBootROMType(void)
{
return _peBootROMType;
}
long IOPlatformExpert::getChipSetType(void)
{
return _peChipSetType;
}
long IOPlatformExpert::getMachineType(void)
{
return _peMachineType;
}
void IOPlatformExpert::setBootROMType(long peBootROMType)
{
_peBootROMType = peBootROMType;
}
void IOPlatformExpert::setChipSetType(long peChipSetType)
{
_peChipSetType = peChipSetType;
}
void IOPlatformExpert::setMachineType(long peMachineType)
{
_peMachineType = peMachineType;
}
bool IOPlatformExpert::getMachineName( char * , int )
{
return( false );
}
bool IOPlatformExpert::getModelName( char * , int )
{
return( false );
}
OSString* IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
{
return NULL;
}
IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void)
{
return(OSDynamicCast(IORangeAllocator,
getProperty("Platform Memory Ranges")));
}
int (*PE_halt_restart)(unsigned int type) = 0;
int IOPlatformExpert::haltRestart(unsigned int type)
{
IOPMrootDomain *rd = getPMRootDomain();
OSBoolean *b = 0;
if(rd) b = (OSBoolean *)OSDynamicCast(OSBoolean, rd->getProperty(OSString::withCString("StallSystemAtHalt")));
if (type == kPEHangCPU) while (1);
if (kOSBooleanTrue == b) {
IOSleep(1000*60*5);
type = kPERestartCPU;
}
if (PE_halt_restart) return (*PE_halt_restart)(type);
else return -1;
}
void IOPlatformExpert::sleepKernel(void)
{
#if 0
long cnt;
boolean_t intState;
intState = ml_set_interrupts_enabled(false);
for (cnt = 0; cnt < 10000; cnt++) {
IODelay(1000);
}
ml_set_interrupts_enabled(intState);
#else
IOCPUSleepKernel();
#endif
}
long IOPlatformExpert::getGMTTimeOfDay(void)
{
return(0);
}
void IOPlatformExpert::setGMTTimeOfDay(long secs)
{
}
IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
{
return( PE_current_console( consoleInfo));
}
IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
unsigned int op)
{
return( PE_initialize_console( consoleInfo, op ));
}
IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
{
IOLockLock(gIOInterruptControllersLock);
gIOInterruptControllers->setObject(name, interruptController);
IOLockWakeup(gIOInterruptControllersLock,
gIOInterruptControllers, false);
IOLockUnlock(gIOInterruptControllersLock);
return kIOReturnSuccess;
}
IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
{
OSObject *object;
IOLockLock(gIOInterruptControllersLock);
while (1) {
object = gIOInterruptControllers->getObject(name);
if (object != 0)
break;
IOLockSleep(gIOInterruptControllersLock,
gIOInterruptControllers, THREAD_UNINT);
}
IOLockUnlock(gIOInterruptControllersLock);
return OSDynamicCast(IOInterruptController, object);
}
void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
{
IOCPUInterruptController *controller;
controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
if (controller) controller->setCPUInterruptProperties(service);
}
bool IOPlatformExpert::atInterruptLevel(void)
{
return ml_at_interrupt_context();
}
bool IOPlatformExpert::platformAdjustService(IOService *)
{
return true;
}
void IOPlatformExpert::
PMLog(const char *who, unsigned long event,
unsigned long param1, unsigned long param2)
{
UInt32 debugFlags = gIOKitDebug;
if (debugFlags & kIOLogPower) {
uint32_t nows, nowus;
clock_get_system_microtime(&nows, &nowus);
nowus += (nows % 1000) * 1000000;
kprintf("pm%u %x %.30s %d %x %x\n",
nowus, (unsigned) current_thread(), who, (int) event, param1, param2);
if (debugFlags & kIOLogTracePower) {
static const UInt32 sStartStopBitField[] =
{ 0x00000000, 0x00000040 };
UInt32 sgnevent = ((long) event >> 31);
UInt32 absevent = sgnevent ^ (event + sgnevent);
UInt32 code = IODBG_POWER(absevent);
UInt32 bit = 1 << (absevent & 0x1f);
if (absevent < sizeof(sStartStopBitField) * 8
&& (sStartStopBitField[absevent >> 5] & bit) ) {
code |= DBG_FUNC_START - sgnevent;
}
IOTimeStampConstant(code, (UInt32) who, event, param1, param2);
}
}
}
void IOPlatformExpert::PMInstantiatePowerDomains ( void )
{
root = new IOPMrootDomain;
root->init();
root->attach(this);
root->start(this);
root->youAreRoot();
}
void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
{
root->addPowerChild ( theDevice );
}
bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
{
return ((_pePMFeatures & featureMask) != 0);
}
bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
{
return ((_pePrivPMFeatures & privFeatureMask) != 0);
}
int IOPlatformExpert::numBatteriesSupported (void)
{
return (_peNumBatteriesSupported);
}
bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
{
unsigned int i;
unsigned int numPowerTreeNodes;
OSDictionary * entry;
OSDictionary * matchingDictionary;
OSDictionary * providerDictionary;
OSDictionary * deviceDictionary;
OSDictionary * nubDictionary;
OSArray * children;
bool nodeFound = false;
bool continueSearch = false;
bool deviceMatch = false;
bool providerMatch = false;
bool multiParentMatch = false;
if ( (NULL == theDevice) || (NULL == inSubTree) )
return false;
numPowerTreeNodes = inSubTree->getCount ();
for ( i = 0; i < numPowerTreeNodes; i++ ) {
entry = (OSDictionary *) inSubTree->getObject (i);
matchingDictionary = (OSDictionary *) entry->getObject ("device");
providerDictionary = (OSDictionary *) entry->getObject ("provider");
deviceMatch = true; if ( matchingDictionary ) {
deviceMatch = false;
if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) {
deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary );
deviceDictionary->release ();
}
}
providerMatch = true; if ( theNub && providerDictionary ) {
providerMatch = false;
if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) {
providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary );
nubDictionary->release ();
}
}
multiParentMatch = true; if (deviceMatch && providerMatch) {
if (NULL != multipleParentKeyValue) {
OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent");
multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false;
}
}
nodeFound = (deviceMatch && providerMatch && multiParentMatch);
if ( theNub == NULL && providerDictionary != NULL )
nodeFound = false;
if ( nodeFound ) {
if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
if ( kIOLogPower & gIOKitDebug)
IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
numInstancesRegistered++;
multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
}
else
nodeFound = false;
}
continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
}
if ( false == continueSearch )
break;
}
return ( nodeFound );
}
bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
{
IOService * aService;
bool registered = false;
OSArray * children;
unsigned int numChildren;
OSDictionary * child;
if ( NULL == theTreeNode->getObject ("service") ) {
if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) {
numChildren = children->getCount ();
for ( unsigned int i = 0; i < numChildren; i++ ) {
if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) {
if ( NULL != (aService = (IOService *) child->getObject ("service")) )
theService->addPowerChild (aService);
}
}
}
if ( theTreeParentNode ) {
if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
if (aService != theProvider)
aService->addPowerChild (theService);
}
registered = true;
}
}
return registered;
}
void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
{
OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
OSSymbol * mkey;
OSString * ioClass;
unsigned int i = 0;
mcoll->reset ();
mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
while (mkey) {
if ( mkey->isEqualTo ("IOClass") ) {
ioClass = (OSString *) inDictionary->getObject ("IOClass");
if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
}
if ( mkey->isEqualTo ("IOProviderClass") ) {
ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
}
if ( mkey->isEqualTo ("IONameMatch") ) {
ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
}
if ( mkey->isEqualTo ("IONameMatched") ) {
ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
}
#if 0
if ( mkey->isEqualTo ("AAPL,clock-id") ) {
char * cstr;
cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id"));
if (cstr)
kprintf (" ===> AAPL,clock-id is %s\n", cstr );
}
#endif
if ( mkey->isEqualTo ("name") ) {
char nameStr[64];
nameStr[0] = 0;
getCStringForObject (inDictionary->getObject ("name"), nameStr );
if (strlen(nameStr) > 0)
IOLog ("%s name is %s\n", inMsg, nameStr);
}
mkey = (OSSymbol *) mcoll->getNextObject ();
i++;
}
mcoll->release ();
}
static void getCStringForObject (OSObject * inObj, char * outStr)
{
char * buffer;
unsigned int len, i;
if ( (NULL == inObj) || (NULL == outStr))
return;
char * objString = (char *) (inObj->getMetaClass())->getClassName();
if ((0 == strcmp(objString,"OSString")) || (0 == strcmp (objString, "OSSymbol")))
strcpy (outStr, ((OSString *)inObj)->getCStringNoCopy());
else if (0 == strcmp(objString,"OSData")) {
len = ((OSData *)inObj)->getLength();
buffer = (char *)((OSData *)inObj)->getBytesNoCopy();
if (buffer && (len > 0)) {
for (i=0; i < len; i++) {
outStr[i] = buffer[i];
}
outStr[len] = 0;
}
}
}
static void IOPMPanicOnShutdownHang(thread_call_param_t p0, thread_call_param_t p1)
{
int type = (int)p0;
gIOPlatform->haltRestart(type);
}
extern "C" {
boolean_t PEGetMachineName( char * name, int maxLength )
{
if( gIOPlatform)
return( gIOPlatform->getMachineName( name, maxLength ));
else
return( false );
}
boolean_t PEGetModelName( char * name, int maxLength )
{
if( gIOPlatform)
return( gIOPlatform->getModelName( name, maxLength ));
else
return( false );
}
int PEGetPlatformEpoch(void)
{
if( gIOPlatform)
return( gIOPlatform->getBootROMType());
else
return( -1 );
}
int PEHaltRestart(unsigned int type)
{
IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain();
bool noWaitForResponses;
AbsoluteTime deadline;
thread_call_t shutdown_hang;
if(type == kPEHaltCPU || type == kPERestartCPU)
{
shutdown_hang = thread_call_allocate( &IOPMPanicOnShutdownHang, (thread_call_param_t) type);
clock_interval_to_deadline( 30, kSecondScale, &deadline );
thread_call_enter1_delayed( shutdown_hang, 0, deadline );
noWaitForResponses = pmRootDomain->tellChangeDown2(type);
}
if (gIOPlatform) return gIOPlatform->haltRestart(type);
else return -1;
}
UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
{
if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
else return 0;
}
long PEGetGMTTimeOfDay(void)
{
if( gIOPlatform)
return( gIOPlatform->getGMTTimeOfDay());
else
return( 0 );
}
void PESetGMTTimeOfDay(long secs)
{
if( gIOPlatform)
gIOPlatform->setGMTTimeOfDay(secs);
}
}
void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
{
publishResource("IONVRAM");
}
IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
bool waitForFunction,
void *param1, void *param2,
void *param3, void *param4)
{
IOService *service, *_resources;
if (waitForFunction) {
_resources = waitForService(resourceMatching(functionName));
} else {
_resources = resources();
}
if (_resources == 0) return kIOReturnUnsupported;
service = OSDynamicCast(IOService, _resources->getProperty(functionName));
if (service == 0) return kIOReturnUnsupported;
return service->callPlatformFunction(functionName, waitForFunction,
param1, param2, param3, param4);
}
IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
{
return 0;
}
#undef super
#define super IOPlatformExpert
OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
IOService * IODTPlatformExpert::probe( IOService * provider,
SInt32 * score )
{
if( !super::probe( provider, score))
return( 0 );
if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
return( 0 );
return( this);
}
bool IODTPlatformExpert::configure( IOService * provider )
{
if( !super::configure( provider))
return( false);
processTopLevel( provider );
return( true );
}
IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
{
IOService * nub;
nub = new IOPlatformDevice;
if( nub) {
if( !nub->init( from, gIODTPlane )) {
nub->free();
nub = 0;
}
}
return( nub);
}
bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
{
IORegistryEntry * next;
IOService * nub;
bool ok = true;
if( iter) {
while( (next = (IORegistryEntry *) iter->getNextObject())) {
if( 0 == (nub = createNub( next )))
continue;
nub->attach( parent );
nub->registerService();
}
iter->release();
}
return( ok );
}
void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
{
OSIterator * kids;
IORegistryEntry * next;
IORegistryEntry * cpus;
IORegistryEntry * options;
kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
if( kids) {
while( (next = (IORegistryEntry *)kids->getNextObject())) {
next->detachAll( gIODTPlane);
}
kids->release();
}
options = rootEntry->childFromPath("options", gIODTPlane);
if (options) {
dtNVRAM = new IODTNVRAM;
if (dtNVRAM) {
if (!dtNVRAM->init(options, gIODTPlane)) {
dtNVRAM->release();
dtNVRAM = 0;
} else {
dtNVRAM->attach(this);
dtNVRAM->registerService();
}
}
}
cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
if ( cpus)
createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
}
IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
{
if( nub->getDeviceMemory())
return( kIOReturnSuccess );
IODTResolveAddressing( nub, "reg", 0);
return( kIOReturnSuccess);
}
bool IODTPlatformExpert::compareNubName( const IOService * nub,
OSString * name, OSString ** matched ) const
{
return( IODTCompareNubName( nub, name, matched )
|| super::compareNubName( nub, name, matched) );
}
bool IODTPlatformExpert::getModelName( char * name, int maxLength )
{
OSData * prop;
const char * str;
int len;
char c;
bool ok = false;
maxLength--;
prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
if( prop ) {
str = (const char *) prop->getBytesNoCopy();
if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
str += strlen( "AAPL," );
len = 0;
while( (c = *str++)) {
if( (c == '/') || (c == ' '))
c = '-';
name[ len++ ] = c;
if( len >= maxLength)
break;
}
name[ len ] = 0;
ok = true;
}
return( ok );
}
bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
{
OSData * prop;
bool ok = false;
maxLength--;
prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
ok = (0 != prop);
if( ok )
strncpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
return( ok );
}
void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
{
if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
super::registerNVRAMController(nvram);
}
int IODTPlatformExpert::haltRestart(unsigned int type)
{
if (dtNVRAM) dtNVRAM->sync();
return super::haltRestart(type);
}
IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
IOByteCount length)
{
if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
else return kIOReturnNotReady;
}
IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
IOByteCount length)
{
if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
else return kIOReturnNotReady;
}
IOReturn IODTPlatformExpert::readNVRAMProperty(
IORegistryEntry * entry,
const OSSymbol ** name, OSData ** value )
{
if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
else return kIOReturnNotReady;
}
IOReturn IODTPlatformExpert::writeNVRAMProperty(
IORegistryEntry * entry,
const OSSymbol * name, OSData * value )
{
if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
else return kIOReturnNotReady;
}
OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
{
if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
else return 0;
}
IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
IOByteCount offset, UInt8 * buffer,
IOByteCount length)
{
if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
buffer, length);
else return kIOReturnNotReady;
}
IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
IOByteCount offset, UInt8 * buffer,
IOByteCount length)
{
if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
buffer, length);
else return kIOReturnNotReady;
}
IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
{
IOByteCount lengthSaved = 0;
if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
return lengthSaved;
}
OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) {
UInt8* serialNumber;
unsigned int serialNumberSize;
unsigned short pos = 0;
char* temp;
char SerialNo[30];
if (myProperty != NULL) {
serialNumberSize = myProperty->getLength();
serialNumber = (UInt8*)(myProperty->getBytesNoCopy());
temp = (char*)serialNumber;
if (serialNumberSize > 0) {
while (pos < serialNumberSize && temp[pos] != '-') pos++;
if (pos < serialNumberSize) { memcpy(SerialNo, serialNumber + 12, 8);
memcpy(&SerialNo[8], serialNumber, 3);
SerialNo[11] = '-';
memcpy(&SerialNo[12], serialNumber + 3, 8);
SerialNo[20] = 0;
} else { memcpy(SerialNo, serialNumber + 13, 8);
memcpy(&SerialNo[8], serialNumber, 3);
SerialNo[11] = 0;
}
return OSString::withCString(SerialNo);
}
}
return NULL;
}
#undef super
#define super IOService
OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
bool IOPlatformExpertDevice::compareName( OSString * name,
OSString ** matched ) const
{
return( IODTCompareNubName( this, name, matched ));
}
bool
IOPlatformExpertDevice::initWithArgs(
void * dtTop, void * p2, void * p3, void * p4 )
{
IORegistryEntry * dt = 0;
void * argsData[ 4 ];
bool ok;
if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
ok = super::init( dt, gIODTPlane );
else
ok = super::init();
if( !ok)
return( false);
workLoop = IOWorkLoop::workLoop();
if (!workLoop)
return false;
argsData[ 0 ] = dtTop;
argsData[ 1 ] = p2;
argsData[ 2 ] = p3;
argsData[ 3 ] = p4;
setProperty("IOPlatformArgs", (void *)argsData, sizeof( argsData));
return( true);
}
IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
{
return workLoop;
}
void IOPlatformExpertDevice::free()
{
if (workLoop)
workLoop->release();
}
#undef super
#define super IOService
OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
bool IOPlatformDevice::compareName( OSString * name,
OSString ** matched ) const
{
return( ((IOPlatformExpert *)getProvider())->
compareNubName( this, name, matched ));
}
IOService * IOPlatformDevice::matchLocation( IOService * )
{
return( this );
}
IOReturn IOPlatformDevice::getResources( void )
{
return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
}
class IOPanicPlatform : IOPlatformExpert {
OSDeclareDefaultStructors(IOPanicPlatform);
public:
bool start(IOService * provider);
};
OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
bool IOPanicPlatform::start(IOService * provider) {
const char * platform_name = "(unknown platform name)";
if (provider) platform_name = provider->getName();
panic("Unable to find driver for this platform: \"%s\".\n",
platform_name);
return false;
}