/*
- * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-/*
- * HISTORY
- */
#include <IOKit/IOCPU.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <libkern/c++/OSContainers.h>
#include <libkern/crypto/sha1.h>
+#include <libkern/OSAtomic.h>
extern "C" {
#include <machine/machine_routines.h>
#include <uuid/uuid.h>
}
-/* Delay period for UPS halt */
-#define kUPSDelayHaltCPU_msec (1000*60*5)
-
void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
static void getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen);
static IOPlatformExpert * gIOPlatform;
static OSDictionary * gIOInterruptControllers;
static IOLock * gIOInterruptControllersLock;
+static IODTNVRAM *gIOOptionsEntry;
OSSymbol * gPlatformInterruptControllerName;
return false;
// Override the mapper present flag is requested by boot arguments.
- if (PE_parse_boot_arg("dart", &debugFlags) && (debugFlags == 0))
+ if (PE_parse_boot_argn("dart", &debugFlags, sizeof (debugFlags)) && (debugFlags == 0))
removeProperty(kIOPlatformMapperPresentKey);
-
+ if (PE_parse_boot_argn("-x", &debugFlags, sizeof (debugFlags)))
+ removeProperty(kIOPlatformMapperPresentKey);
+
// Register the presence or lack thereof a system
// PCI address mapper with the IOMapper class
IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey));
{
if (type == kPEPanicSync) return 0;
- if (type == kPEHangCPU) while (1);
+ if (type == kPEHangCPU) while (true) {}
if (type == kPEUPSDelayHaltCPU) {
- // Stall shutdown for 5 minutes, and if no outside force has
- // removed our power at that point, proceed with a reboot.
- IOSleep( kUPSDelayHaltCPU_msec );
-
- // Ideally we never reach this point.
-
- type = kPERestartCPU;
+ // RestartOnPowerLoss feature was turned on, proceed with shutdown.
+ type = kPEHaltCPU;
}
// On ARM kPEPanicRestartCPU is supported in the drivers
if (type == kPEPanicRestartCPU)
type = kPERestartCPU;
-
+
if (PE_halt_restart) return (*PE_halt_restart)(type);
else return -1;
}
PMLog(const char *who, unsigned long event,
unsigned long param1, unsigned long param2)
{
- UInt32 debugFlags = gIOKitDebug;
-
- if (debugFlags & kIOLogPower) {
-
- uint32_t nows, nowus;
+ clock_sec_t nows;
+ clock_usec_t 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, // Identity
- (int) event, param1, param2); // Args
-
- if (debugFlags & kIOLogTracePower) {
- static const UInt32 sStartStopBitField[] =
- { 0x00000000, 0x00000040 }; // Only Program Hardware so far
-
- // Arcane formula from Hacker's Delight by Warren
- // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
- 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) ) {
- // Or in the START or END bits, Start = 1 & END = 2
- // If sgnevent == 0 then START - 0 => START
- // else if sgnevent == -1 then START - -1 => END
- code |= DBG_FUNC_START - sgnevent;
- }
-
- // Record the timestamp, wish I had a this pointer
- IOTimeStampConstant(code, (UInt32) who, event, param1, param2);
- }
- }
+ kprintf("pm%u %p %.30s %d %lx %lx\n",
+ nowus, current_thread(), who, // Identity
+ (int) event, (long) param1, (long) param2); // Args
}
root->init();
root->attach(this);
root->start(this);
- root->youAreRoot();
}
thread_call_param_t p0,
thread_call_param_t p1)
{
- int type = (int)p0;
+#ifdef CONFIG_EMBEDDED
+ /* 30 seconds has elapsed - panic */
+ panic("Halt/Restart Timed Out");
+
+#else /* ! CONFIG_EMBEDDED */
+ int type = (int)(long)p0;
/* 30 seconds has elapsed - resume shutdown */
if(gIOPlatform) gIOPlatform->haltRestart(type);
+#endif /* CONFIG_EMBEDDED */
}
int PEHaltRestart(unsigned int type)
{
- IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain();
+ IOPMrootDomain *pmRootDomain;
AbsoluteTime deadline;
thread_call_t shutdown_hang;
- unsigned int tell_type;
if(type == kPEHaltCPU || type == kPERestartCPU || type == kPEUPSDelayHaltCPU)
{
+ pmRootDomain = IOService::getPMRootDomain();
/* Notify IOKit PM clients of shutdown/restart
Clients subscribe to this message with a call to
IOService::registerInterest()
(thread_call_param_t) type);
clock_interval_to_deadline( 30, kSecondScale, &deadline );
thread_call_enter1_delayed( shutdown_hang, 0, deadline );
-
-
- if( kPEUPSDelayHaltCPU == type ) {
- tell_type = kPEHaltCPU;
- } else {
- tell_type = type;
- }
- pmRootDomain->handlePlatformHaltRestart(tell_type);
+ pmRootDomain->handlePlatformHaltRestart(type);
/* This notification should have few clients who all do
their work synchronously.
else return 0;
}
+
+
+inline static int init_gIOOptionsEntry(void)
+{
+ IORegistryEntry *entry;
+ void *nvram_entry;
+ volatile void **options;
+ int ret = -1;
+
+ if (gIOOptionsEntry)
+ return 0;
+
+ entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
+ if (!entry)
+ return -1;
+
+ nvram_entry = (void *) OSDynamicCast(IODTNVRAM, entry);
+ if (!nvram_entry)
+ goto release;
+
+ options = (volatile void **) &gIOOptionsEntry;
+ if (!OSCompareAndSwapPtr(NULL, nvram_entry, options)) {
+ ret = 0;
+ goto release;
+ }
+
+ return 0;
+
+release:
+ entry->release();
+ return ret;
+
+}
+
+/* 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;
+
+ if (!symbol || !len)
+ goto err;
+
+ if (init_gIOOptionsEntry() < 0)
+ goto err;
+
+ vlen = *len;
+ *len = 0;
+
+ obj = gIOOptionsEntry->getProperty(symbol);
+ if (!obj)
+ goto err;
+
+ /* convert to data */
+ data = OSDynamicCast(OSData, obj);
+ if (!data)
+ goto err;
+
+ *len = data->getLength();
+ vlen = min(vlen, *len);
+ if (vlen)
+ memcpy((void *) value, data->getBytesNoCopy(), vlen);
+
+ return TRUE;
+
+err:
+ return FALSE;
+}
+
+
+boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value,
+ const unsigned int len)
+{
+ const OSSymbol *sym;
+ OSData *data;
+ bool ret = false;
+
+ if (!symbol || !value || !len)
+ goto err;
+
+ if (init_gIOOptionsEntry() < 0)
+ goto err;
+
+ sym = OSSymbol::withCStringNoCopy(symbol);
+ if (!sym)
+ goto err;
+
+ data = OSData::withBytes((void *) value, len);
+ if (!data)
+ goto sym_done;
+
+ ret = gIOOptionsEntry->setProperty(sym, data);
+ data->release();
+
+sym_done:
+ sym->release();
+
+ if (ret == true) {
+ gIOOptionsEntry->sync();
+ return TRUE;
+ }
+
+err:
+ return FALSE;
+}
+
+
long PEGetGMTTimeOfDay(void)
{
long result = 0;
- if( gIOPlatform)
- result = gIOPlatform->getGMTTimeOfDay();
+ if( gIOPlatform) result = gIOPlatform->getGMTTimeOfDay();
return (result);
}
void PESetGMTTimeOfDay(long secs)
{
- if( gIOPlatform)
- gIOPlatform->setGMTTimeOfDay(secs);
+ if( gIOPlatform) gIOPlatform->setGMTTimeOfDay(secs);
}
} /* extern "C" */
OSData * data;
IORegistryEntry * entry;
OSString * string = 0;
- char uuid[ 36 + 1 ];
+ 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( );
+ }
+#else /* !CONFIG_EMBEDDED */
entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
if ( entry )
{
entry->release( );
}
+#endif /* !CONFIG_EMBEDDED */
if ( string == 0 )
{
if (waitForFunction) {
_resources = waitForService(resourceMatching(functionName));
} else {
- _resources = resources();
+ _resources = getResourceService();
}
if (_resources == 0) return kIOReturnUnsupported;
return false;
}
+