+void
+IOPlatformExpertDevice::configureDefaults( void )
+{
+ createNVRAM();
+ // Parse the serial-number data and publish a user-readable string
+ OSData* mydata = (OSData*) (getProperty("serial-number"));
+ if (mydata != NULL) {
+ OSString *serNoString = OSString::withCString((const char *)mydata->getBytesNoCopy());
+ if (serNoString != NULL) {
+ setProperty(kIOPlatformSerialNumberKey, serNoString);
+ serNoString->release();
+ }
+ }
+ generatePlatformUUID();
+}
+
+void
+IOPlatformExpertDevice::createNVRAM( void )
+{
+ /*
+ * Publish an IODTNVRAM class on /options, if present.
+ * DT-based platforms may need NVRAM access prior to the start
+ * of IOKit matching, to support security-related operations
+ * that must happen before machine_lockdown().
+ */
+ IORegistryEntry *options = IORegistryEntry::fromPath("/options", gIODTPlane);
+ if (options == NULL) {
+ return; // /options may not be present
+ }
+
+ assert(gIOOptionsEntry == NULL);
+ gIOOptionsEntry = new IODTNVRAM;
+
+ assert(gIOOptionsEntry != NULL);
+
+ gIOOptionsEntry->init(options, gIODTPlane);
+
+ gIOOptionsEntry->attach(this);
+ options->release();
+}
+
+void
+IOPlatformExpertDevice::generatePlatformUUID( void )
+{
+ IORegistryEntry * entry;
+ OSString * string = NULL;
+ uuid_string_t uuid;
+
+#if !defined(__x86_64__)
+ 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 /* !defined(__x86_64__) */
+ OSData * data;
+
+ 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();
+ }
+ if (!string) {
+ /* vmware still runs this path */
+ 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();
+ }
+ }
+#endif /* defined(__x86_64__) */
+
+ if (string) {
+ setProperty( kIOPlatformUUIDKey, string );
+ gIOPlatformUUIDAndSerialDone = true;
+
+ string->release();
+ }
+}