/*
- * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
- *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * HISTORY
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-
+
#include <IOKit/IOCPU.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IOKitDebug.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/IOUserClient.h>
+#include <IOKit/IOKitDiagnosticsUserClient.h>
+#include <IOKit/IOUserServer.h>
#include <IOKit/system.h>
+#include <sys/csr.h>
#include <libkern/c++/OSContainers.h>
-
+#include <libkern/crypto/sha1.h>
+#include <libkern/OSAtomic.h>
extern "C" {
#include <machine/machine_routines.h>
#include <pexpert/pexpert.h>
+#include <uuid/uuid.h>
}
-void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
-static void getCStringForObject (OSObject * inObj, char * outStr);
+#define kShutdownTimeout 30 //in secs
+
+#if defined(XNU_TARGET_OS_OSX)
+
+boolean_t coprocessor_cross_panic_enabled = TRUE;
+#define APPLE_VENDOR_VARIABLE_GUID "4d1ede05-38c7-4a6a-9cc6-4bcca8b38c14"
+#endif /* defined(XNU_TARGET_OS_OSX) */
+
+void printDictionaryKeys(OSDictionary * inDictionary, char * inMsg);
+static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen);
+
+/*
+ * There are drivers which take mutexes in the quiesce callout or pass
+ * the quiesce/active action to super. Even though it sometimes panics,
+ * because it doesn't *always* panic, they get away with it.
+ * We need a chicken bit to diagnose and fix them all before this
+ * can be enabled by default.
+ *
+ * <rdar://problem/33831837> tracks turning this on by default.
+ */
+uint32_t gEnforceQuiesceSafety = 0;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
-OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
-
-OSMetaClassDefineReservedUnused(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);
+OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
+OSMetaClassDefineReservedUsed(IOPlatformExpert, 1);
+OSMetaClassDefineReservedUsed(IOPlatformExpert, 2);
+OSMetaClassDefineReservedUsed(IOPlatformExpert, 3);
+OSMetaClassDefineReservedUsed(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;
+static IODTNVRAM *gIOOptionsEntry;
OSSymbol * gPlatformInterruptControllerName;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-bool IOPlatformExpert::attach( IOService * provider )
+bool
+IOPlatformExpert::attach( IOService * provider )
{
+ if (!super::attach( provider )) {
+ return false;
+ }
- if( !super::attach( provider ))
- return( false);
-
- return( true);
+ return true;
}
-bool IOPlatformExpert::start( IOService * provider )
+bool
+IOPlatformExpert::start( IOService * provider )
{
- IORangeAllocator * physicalRanges;
- OSData * busFrequency;
-
- if (!super::start(provider))
- return false;
+ IORangeAllocator * physicalRanges;
+ OSData * busFrequency;
+ uint32_t debugFlags;
- // Register the presence or lack thereof a system
- // PCI address mapper with the IOMapper class
-#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
+ if (!super::start(provider)) {
+ return false;
+ }
- IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey));
-
- gIOInterruptControllers = OSDictionary::withCapacity(1);
- gIOInterruptControllersLock = IOLockAlloc();
-
- // Correct the bus frequency in the device tree.
- 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();
-
- return( configure(provider) );
-}
+ // Override the mapper present flag is requested by boot arguments, if SIP disabled.
+#if CONFIG_CSR
+ if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) == 0)
+#endif /* CONFIG_CSR */
+ {
+ if (PE_parse_boot_argn("dart", &debugFlags, sizeof(debugFlags)) && (debugFlags == 0)) {
+ removeProperty(kIOPlatformMapperPresentKey);
+ }
+#if DEBUG || DEVELOPMENT
+ if (PE_parse_boot_argn("-x", &debugFlags, sizeof(debugFlags))) {
+ removeProperty(kIOPlatformMapperPresentKey);
+ }
+#endif /* DEBUG || DEVELOPMENT */
+ }
-bool IOPlatformExpert::configure( IOService * provider )
-{
- OSSet * topLevel;
- OSDictionary * dict;
- IOService * nub;
+ // Register the presence or lack thereof a system
+ // PCI address mapper with the IOMapper class
+ IOMapper::setMapperRequired(NULL != getProperty(kIOPlatformMapperPresentKey));
+
+ gIOInterruptControllers = OSDictionary::withCapacity(1);
+ gIOInterruptControllersLock = IOLockAlloc();
- topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
+ // Correct the bus frequency in the device tree.
+ busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
+ provider->setProperty("clock-frequency", busFrequency);
+ busFrequency->release();
- 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();
- }
- }
+ 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();
+
+ // Parse the serial-number data and publish a user-readable string
+ OSData* mydata = (OSData*) (provider->getProperty("serial-number"));
+ if (mydata != NULL) {
+ OSString *serNoString = createSystemSerialNumberString(mydata);
+ if (serNoString != NULL) {
+ provider->setProperty(kIOPlatformSerialNumberKey, serNoString);
+ serNoString->release();
+ }
+ }
+
+#if !CONFIG_EMBEDDED
+ if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
+ coprocessor_paniclog_flush = TRUE;
+ extended_debug_log_init();
+ }
+#endif
+
+ PE_parse_boot_argn("enforce_quiesce_safety", &gEnforceQuiesceSafety,
+ sizeof(gEnforceQuiesceSafety));
+
+ 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 (NULL == nub) {
+ continue;
+ }
+ dict->release();
+ nub->attach( this );
+ nub->registerService();
+ }
+ }
- return( true );
+ return true;
}
-IOService * IOPlatformExpert::createNub( OSDictionary * from )
+IOService *
+IOPlatformExpert::createNub( OSDictionary * from )
{
- IOService * nub;
+ IOService * nub;
- nub = new IOPlatformDevice;
- if(nub) {
- if( !nub->init( from )) {
- nub->release();
- nub = 0;
+ nub = new IOPlatformDevice;
+ if (nub) {
+ if (!nub->init( from )) {
+ nub->release();
+ nub = NULL;
+ }
}
- }
- return( nub);
+ return nub;
}
-bool IOPlatformExpert::compareNubName( const IOService * nub,
- OSString * name, OSString ** matched) const
+bool
+IOPlatformExpert::compareNubName( const IOService * nub,
+ OSString * name, OSString ** matched ) const
{
- return( nub->IORegistryEntry::compareName( name, matched ));
+ return nub->IORegistryEntry::compareName( name, matched );
}
-IOReturn IOPlatformExpert::getNubResources( IOService * nub )
+IOReturn
+IOPlatformExpert::getNubResources( IOService * nub )
{
- return( kIOReturnSuccess );
+ return kIOReturnSuccess;
}
-long IOPlatformExpert::getBootROMType(void)
+long
+IOPlatformExpert::getBootROMType(void)
{
- return _peBootROMType;
+ return _peBootROMType;
}
-long IOPlatformExpert::getChipSetType(void)
+long
+IOPlatformExpert::getChipSetType(void)
{
- return _peChipSetType;
+ return _peChipSetType;
}
-long IOPlatformExpert::getMachineType(void)
+long
+IOPlatformExpert::getMachineType(void)
{
- return _peMachineType;
+ return _peMachineType;
}
-void IOPlatformExpert::setBootROMType(long peBootROMType)
+void
+IOPlatformExpert::setBootROMType(long peBootROMType)
{
- _peBootROMType = peBootROMType;
+ _peBootROMType = peBootROMType;
}
-void IOPlatformExpert::setChipSetType(long peChipSetType)
+void
+IOPlatformExpert::setChipSetType(long peChipSetType)
{
- _peChipSetType = peChipSetType;
+ _peChipSetType = peChipSetType;
}
-void IOPlatformExpert::setMachineType(long peMachineType)
+void
+IOPlatformExpert::setMachineType(long peMachineType)
+{
+ _peMachineType = peMachineType;
+}
+
+bool
+IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
{
- _peMachineType = peMachineType;
+ return false;
}
-bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
+bool
+IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
{
- return( false );
+ return false;
}
-bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
+OSString*
+IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
{
- return( false );
+ return NULL;
}
-IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void)
+IORangeAllocator *
+IOPlatformExpert::getPhysicalRangeAllocator(void)
{
- return(OSDynamicCast(IORangeAllocator,
- getProperty("Platform Memory Ranges")));
+ return OSDynamicCast(IORangeAllocator,
+ getProperty("Platform Memory Ranges"));
}
-int (*PE_halt_restart)(unsigned int type) = 0;
+int (*PE_halt_restart)(unsigned int type) = NULL;
-int IOPlatformExpert::haltRestart(unsigned int type)
+int
+IOPlatformExpert::haltRestart(unsigned int type)
{
- if (type == kPEHangCPU) while (1);
-
- if (PE_halt_restart) return (*PE_halt_restart)(type);
- else return -1;
+ if (type == kPEPanicSync) {
+ return 0;
+ }
+
+ if (type == kPEHangCPU) {
+ while (true) {
+ }
+ }
+
+ if (type == kPEUPSDelayHaltCPU) {
+ // RestartOnPowerLoss feature was turned on, proceed with shutdown.
+ type = kPEHaltCPU;
+ }
+
+#if !CONFIG_EMBEDDED
+ // On ARM kPEPanicRestartCPU is supported in the drivers
+ if (type == kPEPanicRestartCPU) {
+ type = kPERestartCPU;
+ }
+#endif
+
+ if (PE_halt_restart) {
+ return (*PE_halt_restart)(type);
+ } else {
+ return -1;
+ }
}
-void IOPlatformExpert::sleepKernel(void)
+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);
+ 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
// PE_initialize_console(0, kPEDisableScreen);
-
- IOCPUSleepKernel();
-
+
+ IOCPUSleepKernel();
+
// PE_initialize_console(0, kPEEnableScreen);
#endif
}
-long IOPlatformExpert::getGMTTimeOfDay(void)
+long
+IOPlatformExpert::getGMTTimeOfDay(void)
{
- return(0);
+ return 0;
}
-void IOPlatformExpert::setGMTTimeOfDay(long secs)
+void
+IOPlatformExpert::setGMTTimeOfDay(long secs)
{
}
-IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
+IOReturn
+IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
+{
+ return PE_current_console( consoleInfo);
+}
+
+IOReturn
+IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
+ unsigned int op)
{
- return( PE_current_console( consoleInfo));
+ return PE_initialize_console( consoleInfo, op );
}
-IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
- unsigned int op)
+IOReturn
+IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
{
- return( PE_initialize_console( consoleInfo, op ));
+ IOLockLock(gIOInterruptControllersLock);
+
+ gIOInterruptControllers->setObject(name, interruptController);
+
+ IOLockWakeup(gIOInterruptControllersLock,
+ gIOInterruptControllers, /* one-thread */ false);
+
+ IOLockUnlock(gIOInterruptControllersLock);
+
+ return kIOReturnSuccess;
}
-IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
+IOReturn
+IOPlatformExpert::deregisterInterruptController(OSSymbol *name)
{
- IOLockLock(gIOInterruptControllersLock);
-
- gIOInterruptControllers->setObject(name, interruptController);
-
- IOLockWakeup(gIOInterruptControllersLock,
- gIOInterruptControllers, /* one-thread */ false);
+ IOLockLock(gIOInterruptControllersLock);
+
+ gIOInterruptControllers->removeObject(name);
+
+ IOLockUnlock(gIOInterruptControllersLock);
+
+ return kIOReturnSuccess;
+}
+
+IOInterruptController *
+IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
+{
+ OSObject *object;
+
+ IOLockLock(gIOInterruptControllersLock);
+ while (1) {
+ object = gIOInterruptControllers->getObject(name);
+
+ if (object != NULL) {
+ break;
+ }
+
+ IOLockSleep(gIOInterruptControllersLock,
+ gIOInterruptControllers, THREAD_UNINT);
+ }
- IOLockUnlock(gIOInterruptControllersLock);
-
- return kIOReturnSuccess;
+ IOLockUnlock(gIOInterruptControllersLock);
+ return OSDynamicCast(IOInterruptController, object);
}
-IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
+
+void
+IOPlatformExpert::setCPUInterruptProperties(IOService *service)
{
- 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);
+ IOCPUInterruptController *controller;
+
+ controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
+ if (controller) {
+ controller->setCPUInterruptProperties(service);
+ }
}
+bool
+IOPlatformExpert::atInterruptLevel(void)
+{
+ return ml_at_interrupt_context();
+}
-void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
+bool
+IOPlatformExpert::platformAdjustService(IOService */*service*/)
{
- IOCPUInterruptController *controller;
-
- controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
- if (controller) controller->setCPUInterruptProperties(service);
+ return true;
}
-bool IOPlatformExpert::atInterruptLevel(void)
+void
+IOPlatformExpert::getUTCTimeOfDay(clock_sec_t * secs, clock_nsec_t * nsecs)
{
- return ml_at_interrupt_context();
+ *secs = getGMTTimeOfDay();
+ *nsecs = 0;
}
-bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
+void
+IOPlatformExpert::setUTCTimeOfDay(clock_sec_t secs, __unused clock_nsec_t nsecs)
{
- return true;
+ setGMTTimeOfDay(secs);
}
//
//*********************************************************************************
-void IOPlatformExpert::PMLog(const char * who,unsigned long event,unsigned long param1, unsigned long param2)
+void
+IOPlatformExpert::
+PMLog(const char *who, unsigned long event,
+ unsigned long param1, unsigned long param2)
{
- if( gIOKitDebug & kIOLogPower) {
- kprintf("%s %02d %08x %08x\n",who,event,param1,param2);
-// IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
- }
+ clock_sec_t nows;
+ clock_usec_t nowus;
+ clock_get_system_microtime(&nows, &nowus);
+ nowus += (nows % 1000) * 1000000;
+
+ kprintf("pm%u %p %.30s %d %lx %lx\n",
+ nowus, OBFUSCATE(current_thread()), who, // Identity
+ (int) event, (long)OBFUSCATE(param1), (long)OBFUSCATE(param2)); // Args
}
//
// In this vanilla implementation, a Root Power Domain is instantiated.
// All other objects which register will be children of this Root.
-// Where this is inappropriate, PMInstantiatePowerDomains is overridden
+// Where this is inappropriate, PMInstantiatePowerDomains is overridden
// in a platform-specific subclass.
//*********************************************************************************
-void IOPlatformExpert::PMInstantiatePowerDomains ( void )
+void
+IOPlatformExpert::PMInstantiatePowerDomains( void )
{
- root = new IOPMrootDomain;
- root->init();
- root->attach(this);
- root->start(this);
- root->youAreRoot();
+ root = new IOPMrootDomain;
+ root->init();
+ root->attach(this);
+ root->start(this);
}
// Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
//*********************************************************************************
-void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
+void
+IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
{
- root->addPowerChild ( theDevice );
+ root->addPowerChild( theDevice );
}
//*********************************************************************************
//
//*********************************************************************************
-bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
+bool
+IOPlatformExpert::hasPMFeature(unsigned long featureMask)
{
- return ((_pePMFeatures & featureMask) != 0);
+ return (_pePMFeatures & featureMask) != 0;
}
//*********************************************************************************
//
//*********************************************************************************
-bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
+bool
+IOPlatformExpert::hasPrivPMFeature(unsigned long privFeatureMask)
{
- return ((_pePrivPMFeatures & privFeatureMask) != 0);
+ return (_pePrivPMFeatures & privFeatureMask) != 0;
}
//*********************************************************************************
//
//*********************************************************************************
-int IOPlatformExpert::numBatteriesSupported (void)
+int
+IOPlatformExpert::numBatteriesSupported(void)
{
- return (_peNumBatteriesSupported);
+ return _peNumBatteriesSupported;
}
//*********************************************************************************
// registered for the given service.
//*********************************************************************************
-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;
+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;
+ }
- if ( (NULL == theDevice) || (NULL == inSubTree) )
- return false;
+ numPowerTreeNodes = inSubTree->getCount();
+
+ // iterate through the power tree to find a home for this device
+
+ for (i = 0; i < numPowerTreeNodes; i++) {
+ entry = (OSDictionary *) inSubTree->getObject(i);
+
+ matchingDictionary = (OSDictionary *) entry->getObject("device");
+ providerDictionary = (OSDictionary *) entry->getObject("provider");
+
+ deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
+ if (matchingDictionary) {
+ deviceMatch = false;
+ if (NULL != (deviceDictionary = theDevice->dictionaryWithProperties())) {
+ deviceMatch = deviceDictionary->isEqualTo( matchingDictionary, matchingDictionary );
+ deviceDictionary->release();
+ }
+ }
+
+ providerMatch = true; // we indicate a match if there is no nub or provider
+ if (theNub && providerDictionary) {
+ providerMatch = false;
+ if (NULL != (nubDictionary = theNub->dictionaryWithProperties())) {
+ providerMatch = nubDictionary->isEqualTo( providerDictionary, providerDictionary );
+ nubDictionary->release();
+ }
+ }
+
+ multiParentMatch = true; // again we indicate a match if there is no multi-parent node
+ 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 the power tree specifies a provider dictionary but theNub is
+ // NULL then we cannot match with this entry.
+
+ if (theNub == NULL && providerDictionary != NULL) {
+ nodeFound = false;
+ }
+
+ // if this node is THE ONE...then register the device
+
+ if (nodeFound) {
+ if (RegisterServiceInTree(theDevice, entry, theParent, theNub)) {
+ if (kIOLogPower & gIOKitDebug) {
+ IOLog("PMRegisterDevice/CheckSubTree - service registered!\n");
+ }
+
+ numInstancesRegistered++;
+
+ // determine if we need to search for additional nodes for this item
+ 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;
+ }
+ }
- numPowerTreeNodes = inSubTree->getCount ();
+ return nodeFound;
+}
- // iterate through the power tree to find a home for this device
+//*********************************************************************************
+// RegisterServiceInTree
+//
+// Register a device at the specified node of our power tree.
+//*********************************************************************************
- for ( i = 0; i < numPowerTreeNodes; i++ ) {
+bool
+IOPlatformExpert::RegisterServiceInTree(IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
+{
+ IOService * aService;
+ bool registered = false;
+ OSArray * children;
+ unsigned int numChildren;
+ OSDictionary * child;
+
+ // make sure someone is not already registered here
+
+ if (NULL == theTreeNode->getObject("service")) {
+ if (theTreeNode->setObject("service", OSDynamicCast( OSObject, theService))) {
+ // 1. CHILDREN ------------------
+
+ // we registered the node in the tree...now if the node has children
+ // registered we must tell this service to add them.
+
+ 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);
+ }
+ }
+ }
+ }
+
+ // 2. PARENT --------------------
+
+ // also we must notify the parent of this node (if a registered service
+ // exists there) of a new child.
+
+ if (theTreeParentNode) {
+ if (NULL != (aService = (IOService *) theTreeParentNode->getObject("service"))) {
+ if (aService != theProvider) {
+ aService->addPowerChild(theService);
+ }
+ }
+ }
+
+ registered = true;
+ }
+ }
- entry = (OSDictionary *) inSubTree->getObject (i);
+ return registered;
+}
- matchingDictionary = (OSDictionary *) entry->getObject ("device");
- providerDictionary = (OSDictionary *) entry->getObject ("provider");
+//*********************************************************************************
+// printDictionaryKeys
+//
+// Print the keys for the given dictionary and selected contents.
+//*********************************************************************************
+void
+printDictionaryKeys(OSDictionary * inDictionary, char * inMsg)
+{
+ OSCollectionIterator * mcoll = OSCollectionIterator::withCollection(inDictionary);
+ OSSymbol * mkey;
+ OSString * ioClass;
+ unsigned int i = 0;
- deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
- if ( matchingDictionary ) {
- deviceMatch = false;
- if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) {
- deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary );
- deviceDictionary->release ();
- }
- }
+ mcoll->reset();
- providerMatch = true; // we indicate a match if there is no nub or provider
- if ( theNub && providerDictionary ) {
- providerMatch = false;
- if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) {
- providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary );
- nubDictionary->release ();
- }
- }
+ mkey = OSDynamicCast(OSSymbol, mcoll->getNextObject());
- multiParentMatch = true; // again we indicate a match if there is no multi-parent node
- if (deviceMatch && providerMatch) {
- if (NULL != multipleParentKeyValue) {
- OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent");
- multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false;
- }
- }
+ while (mkey) {
+ // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
- nodeFound = (deviceMatch && providerMatch && multiParentMatch);
+ // if this is the IOClass key, print it's contents
- // if the power tree specifies a provider dictionary but theNub is
- // NULL then we cannot match with this entry.
+ if (mkey->isEqualTo("IOClass")) {
+ ioClass = (OSString *) inDictionary->getObject("IOClass");
+ if (ioClass) {
+ IOLog("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy());
+ }
+ }
- if ( theNub == NULL && providerDictionary != NULL )
- nodeFound = false;
-
- // if this node is THE ONE...then register the device
+ // if this is an IOProviderClass key print it
- if ( nodeFound ) {
- if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
+ if (mkey->isEqualTo("IOProviderClass")) {
+ ioClass = (OSString *) inDictionary->getObject("IOProviderClass");
+ if (ioClass) {
+ IOLog("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy());
+ }
+ }
- if ( kIOLogPower & gIOKitDebug)
- IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
+ // also print IONameMatch keys
+ if (mkey->isEqualTo("IONameMatch")) {
+ ioClass = (OSString *) inDictionary->getObject("IONameMatch");
+ if (ioClass) {
+ IOLog("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy());
+ }
+ }
- numInstancesRegistered++;
+ // also print IONameMatched keys
- // determine if we need to search for additional nodes for this item
- multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
- }
- else
- nodeFound = false;
- }
+ if (mkey->isEqualTo("IONameMatched")) {
+ ioClass = (OSString *) inDictionary->getObject("IONameMatched");
+ if (ioClass) {
+ IOLog("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy());
+ }
+ }
- continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
+#if 0
+ // print clock-id
+
+ 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 ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
- nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
- continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
- }
+ // print name
- if ( false == continueSearch )
- break;
- }
+ if (mkey->isEqualTo("name")) {
+ char nameStr[64];
+ nameStr[0] = 0;
+ getCStringForObject(inDictionary->getObject("name"), nameStr,
+ sizeof(nameStr));
+ if (strlen(nameStr) > 0) {
+ IOLog("%s name is %s\n", inMsg, nameStr);
+ }
+ }
- return ( nodeFound );
-}
+ mkey = (OSSymbol *) mcoll->getNextObject();
-//*********************************************************************************
-// RegisterServiceInTree
-//
-// Register a device at the specified node of our power tree.
-//*********************************************************************************
+ i++;
+ }
-bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
+ mcoll->release();
+}
+
+static void
+getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen)
{
- IOService * aService;
- bool registered = false;
- OSArray * children;
- unsigned int numChildren;
- OSDictionary * child;
+ char * buffer;
+ unsigned int len, i;
- // make sure someone is not already registered here
+ if ((NULL == inObj) || (NULL == outStr)) {
+ return;
+ }
- if ( NULL == theTreeNode->getObject ("service") ) {
+ char * objString = (char *) (inObj->getMetaClass())->getClassName();
+
+ if ((0 == strncmp(objString, "OSString", sizeof("OSString"))) ||
+ (0 == strncmp(objString, "OSSymbol", sizeof("OSSymbol")))) {
+ strlcpy(outStr, ((OSString *)inObj)->getCStringNoCopy(), outStrLen);
+ } else if (0 == strncmp(objString, "OSData", sizeof("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;
+ }
+ }
+}
- if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
+/* IOShutdownNotificationsTimedOut
+ * - Called from a timer installed by PEHaltRestart
+ */
+#ifdef CONFIG_EMBEDDED
+__abortlike
+#endif
+static void
+IOShutdownNotificationsTimedOut(
+ thread_call_param_t p0,
+ thread_call_param_t p1)
+{
+#ifdef CONFIG_EMBEDDED
+ /* 30 seconds has elapsed - panic */
+ panic("Halt/Restart Timed Out");
+
+#else /* ! CONFIG_EMBEDDED */
+ int type = (int)(long)p0;
+ uint32_t timeout = (uint32_t)(uintptr_t)p1;
+
+ IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain();
+ if (pmRootDomain) {
+ if ((PEGetCoprocessorVersion() >= kCoprocessorVersion2) || pmRootDomain->checkShutdownTimeout()) {
+ pmRootDomain->panicWithShutdownLog(timeout * 1000);
+ }
+ }
- // 1. CHILDREN ------------------
+ /* 30 seconds has elapsed - resume shutdown */
+ if (gIOPlatform) {
+ gIOPlatform->haltRestart(type);
+ }
+#endif /* CONFIG_EMBEDDED */
+}
- // we registered the node in the tree...now if the node has children
- // registered we must tell this service to add them.
- 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);
- }
- }
- }
+extern "C" {
+/*
+ * Callouts from BSD for machine name & model
+ */
+
+boolean_t
+PEGetMachineName( char * name, int maxLength )
+{
+ if (gIOPlatform) {
+ return gIOPlatform->getMachineName( name, maxLength );
+ } else {
+ return false;
+ }
+}
- // 2. PARENT --------------------
+boolean_t
+PEGetModelName( char * name, int maxLength )
+{
+ if (gIOPlatform) {
+ return gIOPlatform->getModelName( name, maxLength );
+ } else {
+ return false;
+ }
+}
- // also we must notify the parent of this node (if a registered service
- // exists there) of a new child.
+int
+PEGetPlatformEpoch(void)
+{
+ if (gIOPlatform) {
+ return gIOPlatform->getBootROMType();
+ } else {
+ return -1;
+ }
+}
- if ( theTreeParentNode ) {
- if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
- if (aService != theProvider)
- aService->addPowerChild (theService);
- }
+int
+PEHaltRestart(unsigned int type)
+{
+ IOPMrootDomain *pmRootDomain;
+ AbsoluteTime deadline;
+ thread_call_t shutdown_hang;
+ IORegistryEntry *node;
+ OSData *data;
+ uint32_t timeout = kShutdownTimeout;
+ static boolean_t panic_begin_called = FALSE;
+
+ if (type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU) {
+ /* If we're in the panic path, the locks and memory allocations required below
+ * could fail. So just try to reboot instead of risking a nested panic.
+ */
+ if (panic_begin_called) {
+ goto skip_to_haltRestart;
+ }
+
+ pmRootDomain = IOService::getPMRootDomain();
+ /* Notify IOKit PM clients of shutdown/restart
+ * Clients subscribe to this message with a call to
+ * IOService::registerInterest()
+ */
+
+ /* Spawn a thread that will panic in 30 seconds.
+ * If all goes well the machine will be off by the time
+ * the timer expires. If the device wants a different
+ * timeout, use that value instead of 30 seconds.
+ */
+#if CONFIG_EMBEDDED
+#define RESTART_NODE_PATH "/defaults"
+#else
+#define RESTART_NODE_PATH "/chosen"
+#endif
+ node = IORegistryEntry::fromPath( RESTART_NODE_PATH, gIODTPlane );
+ if (node) {
+ data = OSDynamicCast( OSData, node->getProperty( "halt-restart-timeout" ));
+ if (data && data->getLength() == 4) {
+ timeout = *((uint32_t *) data->getBytesNoCopy());
+ }
+ }
+
+#if (DEVELOPMENT || DEBUG)
+ /* Override the default timeout via a boot-arg */
+ uint32_t boot_arg_val;
+ if (PE_parse_boot_argn("halt_restart_timeout", &boot_arg_val, sizeof(boot_arg_val))) {
+ timeout = boot_arg_val;
+ }
+#endif
- registered = true;
- }
- }
+ if (timeout) {
+ shutdown_hang = thread_call_allocate( &IOShutdownNotificationsTimedOut,
+ (thread_call_param_t)(uintptr_t) type);
+ clock_interval_to_deadline( timeout, kSecondScale, &deadline );
+ thread_call_enter1_delayed( shutdown_hang, (thread_call_param_t)(uintptr_t)timeout, deadline );
+ }
+
+ pmRootDomain->handlePlatformHaltRestart(type);
+ /* This notification should have few clients who all do
+ * their work synchronously.
+ *
+ * In this "shutdown notification" context we don't give
+ * drivers the option of working asynchronously and responding
+ * later. PM internals make it very hard to wait for asynchronous
+ * replies.
+ */
+ } else if (type == kPEPanicRestartCPU || type == kPEPanicSync || type == kPEPanicRestartCPUNoPanicEndCallouts ||
+ type == kPEPanicRestartCPUNoCallouts) {
+ if (type == kPEPanicRestartCPU) {
+ // Notify any listeners that we're done collecting
+ // panic data before we call through to do the restart
+#if !CONFIG_EMBEDDED
+ if (coprocessor_cross_panic_enabled)
+#endif
+ IOCPURunPlatformPanicActions(kPEPanicEnd);
+ }
+
+ if ((type == kPEPanicRestartCPU) || (type == kPEPanicRestartCPUNoPanicEndCallouts)) {
+ // Callout to shutdown the disk driver once we've returned from the
+ // kPEPanicEnd callbacks (if appropriate) and we know all coredumps
+ // on this system are complete).
+ IOCPURunPlatformPanicActions(kPEPanicDiskShutdown);
+ }
+
+ if (type == kPEPanicRestartCPUNoPanicEndCallouts || type == kPEPanicRestartCPUNoCallouts) {
+ // Replace the wrapper type with the type drivers handle
+ type = kPEPanicRestartCPU;
+ }
+
+ // Do an initial sync to flush as much panic data as possible,
+ // in case we have a problem in one of the platorm panic handlers.
+ // After running the platform handlers, do a final sync w/
+ // platform hardware quiesced for the panic.
+ PE_sync_panic_buffers();
+ IOCPURunPlatformPanicActions(type);
+ PE_sync_panic_buffers();
+ } else if (type == kPEPanicEnd) {
+#if !CONFIG_EMBEDDED
+ if (coprocessor_cross_panic_enabled)
+#endif
+ IOCPURunPlatformPanicActions(type);
+ } else if (type == kPEPanicBegin) {
+#if !CONFIG_EMBEDDED
+ if (coprocessor_cross_panic_enabled)
+#endif
+ {
+ // Only call the kPEPanicBegin callout once
+ if (!panic_begin_called) {
+ panic_begin_called = TRUE;
+ IOCPURunPlatformPanicActions(type);
+ }
+ }
+ }
- return registered;
+skip_to_haltRestart:
+ if (gIOPlatform) {
+ return gIOPlatform->haltRestart(type);
+ } else {
+ return -1;
+ }
}
-//*********************************************************************************
-// printDictionaryKeys
-//
-// Print the keys for the given dictionary and selected contents.
-//*********************************************************************************
-void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
+UInt32
+PESavePanicInfo(UInt8 *buffer, UInt32 length)
{
- OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
- OSSymbol * mkey;
- OSString * ioClass;
- unsigned int i = 0;
-
- mcoll->reset ();
+ if (gIOPlatform != NULL) {
+ return gIOPlatform->savePanicInfo(buffer, length);
+ } else {
+ return 0;
+ }
+}
+
+void
+PESavePanicInfoAction(void *buffer, UInt32 offset, UInt32 length)
+{
+ IOCPURunPlatformPanicSyncAction(buffer, offset, length);
+ return;
+}
- mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
- while (mkey) {
+inline static int
+init_gIOOptionsEntry(void)
+{
+ IORegistryEntry *entry;
+ void *nvram_entry;
+ volatile void **options;
+ int ret = -1;
- // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
+ if (gIOOptionsEntry) {
+ return 0;
+ }
- // if this is the IOClass key, print it's contents
+ entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
+ if (!entry) {
+ return -1;
+ }
- if ( mkey->isEqualTo ("IOClass") ) {
- ioClass = (OSString *) inDictionary->getObject ("IOClass");
- if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
- }
+ nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
+ if (!nvram_entry) {
+ goto release;
+ }
- // if this is an IOProviderClass key print it
+ options = (volatile void **) &gIOOptionsEntry;
+ if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
+ ret = 0;
+ goto release;
+ }
- if ( mkey->isEqualTo ("IOProviderClass") ) {
- ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
- if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
+ return 0;
- }
+release:
+ entry->release();
+ return ret;
+}
- // also print IONameMatch keys
- if ( mkey->isEqualTo ("IONameMatch") ) {
- ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
- if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
- }
+/* pass in a NULL value if you just want to figure out the len */
+boolean_t
+PEReadNVRAMProperty(const char *symbol, void *value,
+ unsigned int *len)
+{
+ OSObject *obj;
+ OSData *data;
+ unsigned int vlen;
- // also print IONameMatched keys
+ if (!symbol || !len) {
+ goto err;
+ }
- if ( mkey->isEqualTo ("IONameMatched") ) {
- ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
- if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
- }
+ if (init_gIOOptionsEntry() < 0) {
+ goto err;
+ }
-#if 0
- // print clock-id
-
- 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
+ vlen = *len;
+ *len = 0;
- // print name
+ obj = gIOOptionsEntry->getProperty(symbol);
+ if (!obj) {
+ goto err;
+ }
- 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);
- }
+ /* convert to data */
+ data = OSDynamicCast(OSData, obj);
+ if (!data) {
+ goto err;
+ }
- mkey = (OSSymbol *) mcoll->getNextObject ();
+ *len = data->getLength();
+ vlen = min(vlen, *len);
+ if (value && vlen) {
+ memcpy((void *) value, data->getBytesNoCopy(), vlen);
+ }
- i++;
- }
+ return TRUE;
- mcoll->release ();
+err:
+ return FALSE;
}
-static void getCStringForObject (OSObject * inObj, char * outStr)
+boolean_t
+PEWriteNVRAMBooleanProperty(const char *symbol, boolean_t value)
{
- char * buffer;
- unsigned int len, i;
+ const OSSymbol *sym = NULL;
+ OSBoolean *data = NULL;
+ bool ret = false;
- if ( (NULL == inObj) || (NULL == outStr))
- return;
+ if (symbol == NULL) {
+ goto exit;
+ }
- char * objString = (char *) (inObj->getMetaClass())->getClassName();
+ if (init_gIOOptionsEntry() < 0) {
+ goto exit;
+ }
+
+ if ((sym = OSSymbol::withCStringNoCopy(symbol)) == NULL) {
+ goto exit;
+ }
+
+ data = value ? kOSBooleanTrue : kOSBooleanFalse;
+ ret = gIOOptionsEntry->setProperty(sym, data);
+
+ sym->release();
- if ((0 == strcmp(objString,"OSString")) || (0 == strcmp (objString, "OSSymbol")))
- strcpy (outStr, ((OSString *)inObj)->getCStringNoCopy());
+ /* success, force the NVRAM to flush writes */
+ if (ret == true) {
+ gIOOptionsEntry->sync();
+ }
- 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;
- }
- }
+exit:
+ return ret;
}
-/* IOPMPanicOnShutdownHang
- * - Called from a timer installed by PEHaltRestart
- */
-static void IOPMPanicOnShutdownHang(thread_call_param_t p0, thread_call_param_t p1)
+static boolean_t
+PEWriteNVRAMPropertyInternal(const char *symbol, boolean_t copySymbol, const void *value,
+ const unsigned int len)
{
- int type = (int)p0;
+ const OSSymbol *sym;
+ OSData *data;
+ bool ret = false;
- /* 30 seconds has elapsed - resume shutdown */
- gIOPlatform->haltRestart(type);
-}
+ if (!symbol || !value || !len) {
+ goto err;
+ }
+ if (init_gIOOptionsEntry() < 0) {
+ goto err;
+ }
-extern "C" {
+ if (copySymbol == TRUE) {
+ sym = OSSymbol::withCString(symbol);
+ } else {
+ sym = OSSymbol::withCStringNoCopy(symbol);
+ }
-/*
- * Callouts from BSD for machine name & model
- */
+ if (!sym) {
+ goto err;
+ }
+
+ data = OSData::withBytes((void *) value, len);
+ if (!data) {
+ goto sym_done;
+ }
+
+ ret = gIOOptionsEntry->setProperty(sym, data);
+ data->release();
-boolean_t PEGetMachineName( char * name, int maxLength )
+sym_done:
+ sym->release();
+
+ if (ret == true) {
+ gIOOptionsEntry->sync();
+ return TRUE;
+ }
+
+err:
+ return FALSE;
+}
+
+boolean_t
+PEWriteNVRAMProperty(const char *symbol, const void *value,
+ const unsigned int len)
{
- if( gIOPlatform)
- return( gIOPlatform->getMachineName( name, maxLength ));
- else
- return( false );
+ return PEWriteNVRAMPropertyInternal(symbol, FALSE, value, len);
}
-boolean_t PEGetModelName( char * name, int maxLength )
+boolean_t
+PEWriteNVRAMPropertyWithCopy(const char *symbol, const void *value,
+ const unsigned int len)
{
- if( gIOPlatform)
- return( gIOPlatform->getModelName( name, maxLength ));
- else
- return( false );
+ return PEWriteNVRAMPropertyInternal(symbol, TRUE, value, len);
}
-int PEGetPlatformEpoch(void)
+boolean_t
+PERemoveNVRAMProperty(const char *symbol)
{
- if( gIOPlatform)
- return( gIOPlatform->getBootROMType());
- else
- return( -1 );
+ const OSSymbol *sym;
+
+ if (!symbol) {
+ goto err;
+ }
+
+ if (init_gIOOptionsEntry() < 0) {
+ goto err;
+ }
+
+ sym = OSSymbol::withCStringNoCopy(symbol);
+ if (!sym) {
+ goto err;
+ }
+
+ gIOOptionsEntry->removeProperty(sym);
+
+ sym->release();
+
+ gIOOptionsEntry->sync();
+ return TRUE;
+
+err:
+ return FALSE;
}
-int PEHaltRestart(unsigned int type)
+long
+PEGetGMTTimeOfDay(void)
{
- IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain();
- bool noWaitForResponses;
- AbsoluteTime deadline;
- thread_call_t shutdown_hang;
-
- if(type == kPEHaltCPU || type == kPERestartCPU)
- {
- /* Notify IOKit PM clients of shutdown/restart
- Clients subscribe to this message with a call to
- IOService::registerInterest()
- */
-
- /* Spawn a thread that will panic in 30 seconds.
- If all goes well the machine will be off by the time
- the timer expires.
- */
- 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);
- /* This notification should have few clients who all do
- their work synchronously.
-
- In this "shutdown notification" context we don't give
- drivers the option of working asynchronously and responding
- later. PM internals make it very hard to wait for asynchronous
- replies. In fact, it's a bad idea to even be calling
- tellChangeDown2 from here at all.
- */
- }
+ clock_sec_t secs;
+ clock_usec_t usecs;
- if (gIOPlatform) return gIOPlatform->haltRestart(type);
- else return -1;
+ PEGetUTCTimeOfDay(&secs, &usecs);
+ return secs;
}
-UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
+void
+PESetGMTTimeOfDay(long secs)
{
- if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
- else return 0;
+ PESetUTCTimeOfDay(secs, 0);
}
-long PEGetGMTTimeOfDay(void)
+void
+PEGetUTCTimeOfDay(clock_sec_t * secs, clock_usec_t * usecs)
{
- if( gIOPlatform)
- return( gIOPlatform->getGMTTimeOfDay());
- else
- return( 0 );
+ clock_nsec_t nsecs = 0;
+
+ *secs = 0;
+ if (gIOPlatform) {
+ gIOPlatform->getUTCTimeOfDay(secs, &nsecs);
+ }
+
+ assert(nsecs < NSEC_PER_SEC);
+ *usecs = nsecs / NSEC_PER_USEC;
}
-void PESetGMTTimeOfDay(long secs)
+void
+PESetUTCTimeOfDay(clock_sec_t secs, clock_usec_t usecs)
{
- if( gIOPlatform)
- gIOPlatform->setGMTTimeOfDay(secs);
+ assert(usecs < USEC_PER_SEC);
+ if (gIOPlatform) {
+ gIOPlatform->setUTCTimeOfDay(secs, usecs * NSEC_PER_USEC);
+ }
}
+coprocessor_type_t
+PEGetCoprocessorVersion( void )
+{
+ coprocessor_type_t coprocessor_version = kCoprocessorVersionNone;
+#if !CONFIG_EMBEDDED
+ IORegistryEntry *platform_entry = NULL;
+ OSData *coprocessor_version_obj = NULL;
+
+ platform_entry = IORegistryEntry::fromPath(kIODeviceTreePlane ":/efi/platform");
+ if (platform_entry != NULL) {
+ coprocessor_version_obj = OSDynamicCast(OSData, platform_entry->getProperty("apple-coprocessor-version"));
+ if ((coprocessor_version_obj != NULL) && (coprocessor_version_obj->getLength() <= sizeof(uint64_t))) {
+ memcpy(&coprocessor_version, coprocessor_version_obj->getBytesNoCopy(), coprocessor_version_obj->getLength());
+ }
+ platform_entry->release();
+ }
+#endif
+ return coprocessor_version;
+}
} /* extern "C" */
-void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
+void
+IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
{
- publishResource("IONVRAM");
+ OSData * data;
+ IORegistryEntry * entry;
+ OSString * string = NULL;
+ uuid_string_t uuid;
+
+#if CONFIG_EMBEDDED
+ entry = IORegistryEntry::fromPath( "/chosen", gIODTPlane );
+ if (entry) {
+ OSData * data1;
+
+ data1 = OSDynamicCast( OSData, entry->getProperty( "unique-chip-id" ));
+ if (data1 && data1->getLength() == 8) {
+ OSData * data2;
+
+ data2 = OSDynamicCast( OSData, entry->getProperty( "chip-id" ));
+ if (data2 && data2->getLength() == 4) {
+ SHA1_CTX context;
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ const uuid_t space = { 0xA6, 0xDD, 0x4C, 0xCB, 0xB5, 0xE8, 0x4A, 0xF5, 0xAC, 0xDD, 0xB6, 0xDC, 0x6A, 0x05, 0x42, 0xB8 };
+
+ SHA1Init( &context );
+ SHA1Update( &context, space, sizeof(space));
+ SHA1Update( &context, data1->getBytesNoCopy(), data1->getLength());
+ SHA1Update( &context, data2->getBytesNoCopy(), data2->getLength());
+ SHA1Final( digest, &context );
+
+ digest[6] = (digest[6] & 0x0F) | 0x50;
+ digest[8] = (digest[8] & 0x3F) | 0x80;
+
+ uuid_unparse( digest, uuid );
+ string = OSString::withCString( uuid );
+ }
+ }
+
+ entry->release();
+ }
+#endif /* CONFIG_EMBEDDED */
+
+#if defined(XNU_TARGET_OS_OSX)
+ /*
+ * If we have panic debugging enabled and the bridgeOS panic SoC watchdog is enabled,
+ * disable cross panics so that the co-processor doesn't cause the system
+ * to reset when we enter the debugger or hit a panic on the x86 side.
+ */
+ if (panicDebugging) {
+ entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
+ if (entry) {
+ data = OSDynamicCast( OSData, entry->getProperty( APPLE_VENDOR_VARIABLE_GUID":BridgeOSPanicWatchdogEnabled" ));
+ if (data && (data->getLength() == sizeof(UInt8))) {
+ UInt8 *panicWatchdogEnabled = (UInt8 *) data->getBytesNoCopy();
+ UInt32 debug_flags = 0;
+ if (*panicWatchdogEnabled || (PE_i_can_has_debugger(&debug_flags) &&
+ (debug_flags & DB_DISABLE_CROSS_PANIC))) {
+ coprocessor_cross_panic_enabled = FALSE;
+ }
+ }
+ entry->release();
+ }
+ }
+
+ entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
+ if (entry) {
+ data = OSDynamicCast( OSData, entry->getProperty( "system-id" ));
+ if (data && data->getLength() == 16) {
+ SHA1_CTX context;
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ const uuid_t space = { 0x2A, 0x06, 0x19, 0x90, 0xD3, 0x8D, 0x44, 0x40, 0xA1, 0x39, 0xC4, 0x97, 0x70, 0x37, 0x65, 0xAC };
+
+ SHA1Init( &context );
+ SHA1Update( &context, space, sizeof(space));
+ SHA1Update( &context, data->getBytesNoCopy(), data->getLength());
+ SHA1Final( digest, &context );
+
+ digest[6] = (digest[6] & 0x0F) | 0x50;
+ digest[8] = (digest[8] & 0x3F) | 0x80;
+
+ uuid_unparse( digest, uuid );
+ string = OSString::withCString( uuid );
+ }
+
+ entry->release();
+ }
+#endif /* defined(XNU_TARGET_OS_OSX) */
+
+ if (string == NULL) {
+ entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
+ if (entry) {
+ data = OSDynamicCast( OSData, entry->getProperty( "platform-uuid" ));
+ if (data && data->getLength() == sizeof(uuid_t)) {
+ uuid_unparse((uint8_t *) data->getBytesNoCopy(), uuid );
+ string = OSString::withCString( uuid );
+ }
+
+ entry->release();
+ }
+ }
+
+ if (string) {
+ getProvider()->setProperty( kIOPlatformUUIDKey, string );
+ publishResource( kIOPlatformUUIDKey, string );
+
+ string->release();
+ }
+
+ publishResource("IONVRAM");
}
-IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
- bool waitForFunction,
- void *param1, void *param2,
- void *param3, void *param4)
+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);
+ IOService *service, *_resources;
+
+ if (functionName == gIOPlatformQuiesceActionKey ||
+ functionName == gIOPlatformActiveActionKey) {
+ /*
+ * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction
+ * must consume that event themselves, without passing it up to super/IOPlatformExpert.
+ */
+ if (gEnforceQuiesceSafety) {
+ panic("Class %s passed the quiesce/active action to IOPlatformExpert",
+ getMetaClass()->getClassName());
+ }
+ }
+
+ if (waitForFunction) {
+ _resources = waitForService(resourceMatching(functionName));
+ } else {
+ _resources = getResourceService();
+ }
+ if (_resources == NULL) {
+ return kIOReturnUnsupported;
+ }
+
+ service = OSDynamicCast(IOService, _resources->getProperty(functionName));
+ if (service == NULL) {
+ return kIOReturnUnsupported;
+ }
+
+ return service->callPlatformFunction(functionName, waitForFunction,
+ param1, param2, param3, param4);
}
-IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
+IOByteCount
+IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
{
- return 0;
+ return 0;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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);
+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 )
+IOService *
+IODTPlatformExpert::probe( IOService * provider,
+ SInt32 * score )
{
- if( !super::probe( provider, score))
- return( 0 );
+ if (!super::probe( provider, score)) {
+ return NULL;
+ }
- // check machine types
- if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
- return( 0 );
+ // check machine types
+ if (!provider->compareNames( getProperty( gIONameMatchKey ))) {
+ return NULL;
+ }
- return( this);
+ return this;
}
-bool IODTPlatformExpert::configure( IOService * provider )
+bool
+IODTPlatformExpert::configure( IOService * provider )
{
- if( !super::configure( provider))
- return( false);
+ if (!super::configure( provider)) {
+ return false;
+ }
- processTopLevel( provider );
+ processTopLevel( provider );
- return( true );
+ return true;
}
-IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
+IOService *
+IODTPlatformExpert::createNub( IORegistryEntry * from )
{
- IOService * nub;
+ IOService * nub;
- nub = new IOPlatformDevice;
- if( nub) {
- if( !nub->init( from, gIODTPlane )) {
- nub->free();
- nub = 0;
+ nub = new IOPlatformDevice;
+ if (nub) {
+ if (!nub->init( from, gIODTPlane )) {
+ nub->free();
+ nub = NULL;
+ }
}
- }
- return( nub);
+ 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();
- }
+bool
+IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
+{
+ IORegistryEntry * next;
+ IOService * nub;
+ bool ok = true;
+
+ if (iter) {
+ while ((next = (IORegistryEntry *) iter->getNextObject())) {
+ if (NULL == (nub = createNub( next ))) {
+ continue;
+ }
+
+ nub->attach( parent );
+ nub->registerService();
+ }
+ iter->release();
+ }
- return( ok );
+ return ok;
}
-void IODTPlatformExpert::processTopLevel( IORegistryEntry * root )
+void
+IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
{
- OSIterator * kids;
- IORegistryEntry * next;
- IORegistryEntry * cpus;
- IORegistryEntry * options;
+ OSIterator * kids;
+ IORegistryEntry * next;
+ IORegistryEntry * cpus;
+ IORegistryEntry * options;
- // infanticide
- kids = IODTFindMatchingEntries( root, 0, deleteList() );
- if( kids) {
- while( (next = (IORegistryEntry *)kids->getNextObject())) {
- next->detachAll( gIODTPlane);
+ // infanticide
+ kids = IODTFindMatchingEntries( rootEntry, 0, deleteList());
+ if (kids) {
+ while ((next = (IORegistryEntry *)kids->getNextObject())) {
+ next->detachAll( gIODTPlane);
+ }
+ kids->release();
}
- kids->release();
- }
- // Publish an IODTNVRAM class on /options.
- options = root->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();
+ // Publish an IODTNVRAM class on /options.
+ options = rootEntry->childFromPath("options", gIODTPlane);
+ if (options) {
+ dtNVRAM = new IODTNVRAM;
+ if (dtNVRAM) {
+ if (!dtNVRAM->init(options, gIODTPlane)) {
+ dtNVRAM->release();
+ dtNVRAM = NULL;
+ } else {
+ dtNVRAM->attach(this);
+ dtNVRAM->registerService();
+ options->release();
+ }
+ }
}
- }
- }
- // Publish the cpus.
- cpus = root->childFromPath( "cpus", gIODTPlane);
- if ( cpus)
- createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
+ // Publish the cpus.
+ cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
+ if (cpus) {
+ createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, NULL));
+ cpus->release();
+ }
- // publish top level, minus excludeList
- createNubs( this, IODTFindMatchingEntries( root, kIODTExclusive, excludeList()));
+ // publish top level, minus excludeList
+ createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
}
-IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
+IOReturn
+IODTPlatformExpert::getNubResources( IOService * nub )
{
- if( nub->getDeviceMemory())
- return( kIOReturnSuccess );
+ if (nub->getDeviceMemory()) {
+ return kIOReturnSuccess;
+ }
- IODTResolveAddressing( nub, "reg", 0);
+ IODTResolveAddressing( nub, "reg", NULL);
- return( kIOReturnSuccess);
+ return kIOReturnSuccess;
}
-bool IODTPlatformExpert::compareNubName( const IOService * nub,
- OSString * name, OSString ** matched ) const
+bool
+IODTPlatformExpert::compareNubName( const IOService * nub,
+ OSString * name, OSString ** matched ) const
{
- return( IODTCompareNubName( nub, name, matched )
- || super::compareNubName( nub, name, matched) );
+ 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;
+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;
}
-
- name[ len ] = 0;
- ok = true;
- }
- return( ok );
+ return ok;
}
-bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
+bool
+IODTPlatformExpert::getMachineName( char * name, int maxLength )
{
- OSData * prop;
- bool ok = false;
+ OSData * prop;
+ bool ok = false;
- maxLength--;
- prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
- ok = (0 != prop);
+ maxLength--;
+ prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
+ ok = (NULL != prop);
- if( ok )
- strncpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
+ if (ok) {
+ strlcpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
+ }
- return( ok );
+ return ok;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
+void
+IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
{
- if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
-
- super::registerNVRAMController(nvram);
+ if (dtNVRAM) {
+ dtNVRAM->registerNVRAMController(nvram);
+ }
+
+ super::registerNVRAMController(nvram);
}
-int IODTPlatformExpert::haltRestart(unsigned int type)
+int
+IODTPlatformExpert::haltRestart(unsigned int type)
{
- if (dtNVRAM) dtNVRAM->sync();
-
- return super::haltRestart(type);
+ if (dtNVRAM) {
+ dtNVRAM->sync();
+ }
+
+ return super::haltRestart(type);
}
-IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
- IOByteCount length)
+IOReturn
+IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
+ IOByteCount length)
{
- if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
- else return kIOReturnNotReady;
+ if (dtNVRAM) {
+ return dtNVRAM->readXPRAM(offset, buffer, length);
+ } else {
+ return kIOReturnNotReady;
+ }
}
-IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
- IOByteCount length)
+IOReturn
+IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
+ IOByteCount length)
{
- if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
- else return kIOReturnNotReady;
+ if (dtNVRAM) {
+ return dtNVRAM->writeXPRAM(offset, buffer, length);
+ } else {
+ return kIOReturnNotReady;
+ }
}
-IOReturn IODTPlatformExpert::readNVRAMProperty(
+IOReturn
+IODTPlatformExpert::readNVRAMProperty(
IORegistryEntry * entry,
const OSSymbol ** name, OSData ** value )
{
- if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
- else return kIOReturnNotReady;
+ if (dtNVRAM) {
+ return dtNVRAM->readNVRAMProperty(entry, name, value);
+ } else {
+ return kIOReturnNotReady;
+ }
}
-IOReturn IODTPlatformExpert::writeNVRAMProperty(
+IOReturn
+IODTPlatformExpert::writeNVRAMProperty(
IORegistryEntry * entry,
const OSSymbol * name, OSData * value )
{
- if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
- else return kIOReturnNotReady;
+ if (dtNVRAM) {
+ return dtNVRAM->writeNVRAMProperty(entry, name, value);
+ } else {
+ return kIOReturnNotReady;
+ }
}
-OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
+OSDictionary *
+IODTPlatformExpert::getNVRAMPartitions(void)
{
- if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
- else return 0;
+ if (dtNVRAM) {
+ return dtNVRAM->getNVRAMPartitions();
+ } else {
+ return NULL;
+ }
}
-IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
- IOByteCount offset, UInt8 * buffer,
- IOByteCount length)
+IOReturn
+IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
+ IOByteCount offset, UInt8 * buffer,
+ IOByteCount length)
{
- if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
- buffer, length);
- else return kIOReturnNotReady;
+ if (dtNVRAM) {
+ return dtNVRAM->readNVRAMPartition(partitionID, offset,
+ buffer, length);
+ } else {
+ return kIOReturnNotReady;
+ }
}
-IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
- IOByteCount offset, UInt8 * buffer,
- IOByteCount length)
+IOReturn
+IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
+ IOByteCount offset, UInt8 * buffer,
+ IOByteCount length)
{
- if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
- buffer, length);
- else return kIOReturnNotReady;
+ if (dtNVRAM) {
+ return dtNVRAM->writeNVRAMPartition(partitionID, offset,
+ buffer, length);
+ } else {
+ return kIOReturnNotReady;
+ }
}
-IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
+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;
+ 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) {
+ // check to see if this is a CTO serial number...
+ while (pos < serialNumberSize && temp[pos] != '-') {
+ pos++;
+ }
+
+ if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number
+ memcpy(SerialNo, serialNumber + 12, 8);
+ memcpy(&SerialNo[8], serialNumber, 3);
+ SerialNo[11] = '-';
+ memcpy(&SerialNo[12], serialNumber + 3, 8);
+ SerialNo[20] = 0;
+ } else { // just a normal serial number
+ memcpy(SerialNo, serialNumber + 13, 8);
+ memcpy(&SerialNo[8], serialNumber, 3);
+ SerialNo[11] = 0;
+ }
+ return OSString::withCString(SerialNo);
+ }
+ }
+ return NULL;
}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#undef super
OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
-OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
-OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
-OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
-OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
+OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
+OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
+OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
+OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-bool IOPlatformExpertDevice::compareName( OSString * name,
- OSString ** matched) const
+bool
+IOPlatformExpertDevice::compareName( OSString * name,
+ OSString ** matched ) const
{
- return( IODTCompareNubName( this, name, matched ));
+ return IODTCompareNubName( this, name, matched );
}
bool
IOPlatformExpertDevice::initWithArgs(
- void * dtTop, void * p2, void * p3, void * p4 )
+ void * dtTop, void * p2, void * p3, void * p4 )
{
- IORegistryEntry * dt = 0;
- void * argsData[ 4 ];
- bool ok;
+ IORegistryEntry * dt = NULL;
+ bool ok;
- // dtTop may be zero on non- device tree systems
- if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
- ok = super::init( dt, gIODTPlane );
- else
- ok = super::init();
+ // dtTop may be zero on non- device tree systems
+ if (dtTop && (dt = IODeviceTreeAlloc( dtTop ))) {
+ ok = super::init( dt, gIODTPlane );
+ } else {
+ ok = super::init();
+ }
- if( !ok)
- return( false);
+ if (!ok) {
+ return false;
+ }
- workLoop = IOWorkLoop::workLoop();
- if (!workLoop)
- return false;
+ workLoop = IOWorkLoop::workLoop();
+ if (!workLoop) {
+ return false;
+ }
- argsData[ 0 ] = dtTop;
- argsData[ 1 ] = p2;
- argsData[ 2 ] = p3;
- argsData[ 3 ] = p4;
+ return true;
+}
- setProperty("IOPlatformArgs", (void *)argsData, sizeof( argsData));
+IOWorkLoop *
+IOPlatformExpertDevice::getWorkLoop() const
+{
+ return workLoop;
+}
- return( true);
+IOReturn
+IOPlatformExpertDevice::setProperties( OSObject * properties )
+{
+ return kIOReturnUnsupported;
}
-IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
+IOReturn
+IOPlatformExpertDevice::newUserClient( task_t owningTask, void * securityID,
+ UInt32 type, OSDictionary * properties,
+ IOUserClient ** handler )
{
- return workLoop;
+ IOReturn err = kIOReturnSuccess;
+ IOUserClient * newConnect = NULL;
+ IOUserClient * theConnect = NULL;
+
+ switch (type) {
+ case kIOKitDiagnosticsClientType:
+ newConnect = IOKitDiagnosticsClient::withTask(owningTask);
+ if (!newConnect) {
+ err = kIOReturnNotPermitted;
+ }
+ break;
+ case kIOKitUserServerClientType:
+ newConnect = IOUserServer::withTask(owningTask);
+ if (!newConnect) {
+ err = kIOReturnNotPermitted;
+ }
+ break;
+ default:
+ err = kIOReturnBadArgument;
+ }
+
+ if (newConnect) {
+ if ((false == newConnect->attach(this))
+ || (false == newConnect->start(this))) {
+ newConnect->detach( this );
+ newConnect->release();
+ err = kIOReturnNotPermitted;
+ } else {
+ theConnect = newConnect;
+ }
+ }
+
+ *handler = theConnect;
+ return err;
}
-void IOPlatformExpertDevice::free()
+void
+IOPlatformExpertDevice::free()
{
- if (workLoop)
- workLoop->release();
+ if (workLoop) {
+ workLoop->release();
+ }
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
-OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
-OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
-OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
-OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
+OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-bool IOPlatformDevice::compareName( OSString * name,
- OSString ** matched) const
+bool
+IOPlatformDevice::compareName( OSString * name,
+ OSString ** matched ) const
{
- return( ((IOPlatformExpert *)getProvider())->
- compareNubName( this, name, matched ));
+ return ((IOPlatformExpert *)getProvider())->
+ compareNubName( this, name, matched );
}
-IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
+IOService *
+IOPlatformDevice::matchLocation( IOService * /* client */ )
{
- return( this );
+ return this;
}
-IOReturn IOPlatformDevice::getResources( void )
+IOReturn
+IOPlatformDevice::getResources( void )
{
- return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
+ return ((IOPlatformExpert *)getProvider())->getNubResources( this );
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
*********************************************************************/
class IOPanicPlatform : IOPlatformExpert {
- OSDeclareDefaultStructors(IOPanicPlatform);
+ OSDeclareDefaultStructors(IOPanicPlatform);
public:
- bool start(IOService * provider);
+ bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
};
OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
-bool IOPanicPlatform::start(IOService * provider) {
- const char * platform_name = "(unknown platform name)";
+bool
+IOPanicPlatform::start(IOService * provider)
+{
+ const char * platform_name = "(unknown platform name)";
- if (provider) platform_name = provider->getName();
+ if (provider) {
+ platform_name = provider->getName();
+ }
- panic("Unable to find driver for this platform: \"%s\".\n",
- platform_name);
+ panic("Unable to find driver for this platform: \"%s\".\n",
+ platform_name);
- return false;
+ return false;
}