]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPlatformExpert.cpp
xnu-7195.81.3.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
index 1fb74c64288dfdadcd17eeac6ed90a2e9c4019f2..407dd5b02e3e46e4ca8b0ea3d9972f9fd716f276 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <IOKit/IOCPU.h>
+#include <IOKit/IOPlatformActions.h>
 #include <IOKit/IODeviceTreeSupport.h>
 #include <IOKit/IOKitDebug.h>
 #include <IOKit/IOMapper.h>
 #include <IOKit/IOKitDiagnosticsUserClient.h>
 #include <IOKit/IOUserServer.h>
 
+#include "IOKitKernelInternal.h"
+
 #include <IOKit/system.h>
 #include <sys/csr.h>
 
 #include <libkern/c++/OSContainers.h>
+#include <libkern/c++/OSSharedPtr.h>
 #include <libkern/crypto/sha1.h>
 #include <libkern/OSAtomic.h>
 
+#if defined(__arm64__)
+#include <arm64/tlb.h>
+#endif
+
 extern "C" {
 #include <machine/machine_routines.h>
 #include <pexpert/pexpert.h>
 #include <uuid/uuid.h>
+#include <sys/sysctl.h>
 }
 
 #define kShutdownTimeout    30 //in secs
@@ -83,14 +92,14 @@ uint32_t gEnforceQuiesceSafety = 0;
 
 OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
 
-OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
-OSMetaClassDefineReservedUsed(IOPlatformExpert, 1);
-OSMetaClassDefineReservedUsed(IOPlatformExpert, 2);
-OSMetaClassDefineReservedUsed(IOPlatformExpert, 3);
-OSMetaClassDefineReservedUsed(IOPlatformExpert, 4);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 0);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 1);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 2);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 3);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 4);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 5);
+OSMetaClassDefineReservedUsedX86(IOPlatformExpert, 6);
 
-OSMetaClassDefineReservedUnused(IOPlatformExpert, 5);
-OSMetaClassDefineReservedUnused(IOPlatformExpert, 6);
 OSMetaClassDefineReservedUnused(IOPlatformExpert, 7);
 OSMetaClassDefineReservedUnused(IOPlatformExpert, 8);
 OSMetaClassDefineReservedUnused(IOPlatformExpert, 9);
@@ -167,17 +176,11 @@ IOPlatformExpert::start( IOService * provider )
 
        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 !defined(__x86_64__)
+       publishPlatformUUIDAndSerial();
+#endif /* !defined(__x86_64__) */
 
-#if !CONFIG_EMBEDDED
+#if defined (__x86_64__)
        if (PEGetCoprocessorVersion() >= kCoprocessorVersion2) {
                coprocessor_paniclog_flush = TRUE;
                extended_debug_log_init();
@@ -239,6 +242,16 @@ IOPlatformExpert::compareNubName( const IOService * nub,
        return nub->IORegistryEntry::compareName( name, matched );
 }
 
+bool
+IOPlatformExpert::compareNubName( const IOService * nub,
+    OSString * name, OSSharedPtr<OSString>& matched ) const
+{
+       OSString* matchedRaw = NULL;
+       bool result = compareNubName(nub, name, &matchedRaw);
+       matched.reset(matchedRaw, OSNoRetain);
+       return result;
+}
+
 IOReturn
 IOPlatformExpert::getNubResources( IOService * nub )
 {
@@ -293,6 +306,18 @@ IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
        return false;
 }
 
+bool
+IOPlatformExpert::getTargetName( char * /*name*/, int /*maxLength*/)
+{
+       return false;
+}
+
+bool
+IOPlatformExpert::getProductName( char * /*name*/, int /*maxLength*/)
+{
+       return false;
+}
+
 OSString*
 IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
 {
@@ -325,7 +350,7 @@ IOPlatformExpert::haltRestart(unsigned int type)
                type = kPEHaltCPU;
        }
 
-#if !CONFIG_EMBEDDED
+#if defined (__x86_64__)
        // On ARM kPEPanicRestartCPU is supported in the drivers
        if (type == kPEPanicRestartCPU) {
                type = kPERestartCPU;
@@ -439,9 +464,12 @@ IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
 void
 IOPlatformExpert::setCPUInterruptProperties(IOService *service)
 {
-       IOCPUInterruptController *controller;
+       IOInterruptController *controller;
+
+       OSDictionary *matching = serviceMatching("IOInterruptController");
+       matching = propertyMatching(gPlatformInterruptControllerName, kOSBooleanTrue, matching);
 
-       controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
+       controller = OSDynamicCast(IOInterruptController, waitForService(matching));
        if (controller) {
                controller->setCPUInterruptProperties(service);
        }
@@ -840,7 +868,7 @@ getCStringForObject(OSObject *inObj, char *outStr, size_t outStrLen)
 /* IOShutdownNotificationsTimedOut
  * - Called from a timer installed by PEHaltRestart
  */
-#ifdef CONFIG_EMBEDDED
+#if !defined(__x86_64)
 __abortlike
 #endif
 static void
@@ -848,11 +876,11 @@ IOShutdownNotificationsTimedOut(
        thread_call_param_t p0,
        thread_call_param_t p1)
 {
-#ifdef CONFIG_EMBEDDED
+#if !defined(__x86_64__)
        /* 30 seconds has elapsed - panic */
        panic("Halt/Restart Timed Out");
 
-#else /* ! CONFIG_EMBEDDED */
+#else /* !defined(__x86_64__) */
        int type = (int)(long)p0;
        uint32_t timeout = (uint32_t)(uintptr_t)p1;
 
@@ -867,7 +895,7 @@ IOShutdownNotificationsTimedOut(
        if (gIOPlatform) {
                gIOPlatform->haltRestart(type);
        }
-#endif /* CONFIG_EMBEDDED */
+#endif /* defined(__x86_64__) */
 }
 
 
@@ -876,6 +904,11 @@ extern "C" {
  * Callouts from BSD for machine name & model
  */
 
+/*
+ * PEGetMachineName() and PEGetModelName() are inconsistent across
+ * architectures, and considered deprecated. Use PEGetTargetName() and
+ * PEGetProductName() instead.
+ */
 boolean_t
 PEGetMachineName( char * name, int maxLength )
 {
@@ -886,6 +919,11 @@ PEGetMachineName( char * name, int maxLength )
        }
 }
 
+/*
+ * PEGetMachineName() and PEGetModelName() are inconsistent across
+ * architectures, and considered deprecated. Use PEGetTargetName() and
+ * PEGetProductName() instead.
+ */
 boolean_t
 PEGetModelName( char * name, int maxLength )
 {
@@ -896,18 +934,51 @@ PEGetModelName( char * name, int maxLength )
        }
 }
 
+boolean_t
+PEGetTargetName( char * name, int maxLength )
+{
+       if (gIOPlatform) {
+               return gIOPlatform->getTargetName( name, maxLength );
+       } else {
+               return false;
+       }
+}
+
+boolean_t
+PEGetProductName( char * name, int maxLength )
+{
+       if (gIOPlatform) {
+               return gIOPlatform->getProductName( name, maxLength );
+       } else {
+               return false;
+       }
+}
+
 int
 PEGetPlatformEpoch(void)
 {
        if (gIOPlatform) {
-               return gIOPlatform->getBootROMType();
+               return (int) gIOPlatform->getBootROMType();
        } else {
                return -1;
        }
 }
 
+/* Handle necessary platform specific actions prior to panic */
+void
+PEInitiatePanic(void)
+{
+#if defined(__arm64__)
+       /*
+        * Trigger a TLB flush so any hard hangs exercise the SoC diagnostic
+        * collection flow rather than hanging late in panic (see rdar://58062030)
+        */
+       flush_mmu_tlb_entry(0);
+#endif
+}
+
 int
-PEHaltRestart(unsigned int type)
+PEHaltRestartInternal(unsigned int type, uint32_t details)
 {
        IOPMrootDomain    *pmRootDomain;
        AbsoluteTime      deadline;
@@ -936,7 +1007,7 @@ PEHaltRestart(unsigned int type)
                 *  the timer expires. If the device wants a different
                 *  timeout, use that value instead of 30 seconds.
                 */
-#if CONFIG_EMBEDDED
+#if  defined(__arm__) || defined(__arm64__)
 #define RESTART_NODE_PATH    "/defaults"
 #else
 #define RESTART_NODE_PATH    "/chosen"
@@ -973,50 +1044,42 @@ PEHaltRestart(unsigned int type)
                 *  later. PM internals make it very hard to wait for asynchronous
                 *  replies.
                 */
-       } else if (type == kPEPanicRestartCPU || type == kPEPanicSync || type == kPEPanicRestartCPUNoPanicEndCallouts ||
-           type == kPEPanicRestartCPUNoCallouts) {
+       } else if (type == kPEPanicRestartCPU || type == kPEPanicSync || 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 defined(__x86_64__)
                        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
+                       IOCPURunPlatformPanicActions(kPEPanicEnd, details);
+               } else if (type == kPEPanicRestartCPUNoCallouts) {
+                       // We skipped the callouts so now set the type to
+                       // the variant that the platform uses for panic restarts.
                        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);
+               IOCPURunPlatformPanicActions(type, details);
                PE_sync_panic_buffers();
        } else if (type == kPEPanicEnd) {
-#if !CONFIG_EMBEDDED
+#if defined(__x86_64__)
                if (coprocessor_cross_panic_enabled)
 #endif
-               IOCPURunPlatformPanicActions(type);
+               IOCPURunPlatformPanicActions(type, details);
        } else if (type == kPEPanicBegin) {
-#if !CONFIG_EMBEDDED
+#if defined(__x86_64__)
                if (coprocessor_cross_panic_enabled)
 #endif
                {
                        // Only call the kPEPanicBegin callout once
                        if (!panic_begin_called) {
                                panic_begin_called = TRUE;
-                               IOCPURunPlatformPanicActions(type);
+                               IOCPURunPlatformPanicActions(type, details);
                        }
                }
        }
@@ -1029,11 +1092,17 @@ skip_to_haltRestart:
        }
 }
 
+int
+PEHaltRestart(unsigned int type)
+{
+       return PEHaltRestartInternal(type, 0);
+}
+
 UInt32
 PESavePanicInfo(UInt8 *buffer, UInt32 length)
 {
        if (gIOPlatform != NULL) {
-               return gIOPlatform->savePanicInfo(buffer, length);
+               return (UInt32) gIOPlatform->savePanicInfo(buffer, length);
        } else {
                return 0;
        }
@@ -1047,6 +1116,12 @@ PESavePanicInfoAction(void *buffer, UInt32 offset, UInt32 length)
 }
 
 
+/*
+ * Depending on the platform, the /options node may not be created
+ * until after IOKit matching has started, by an externally-supplied
+ * platform expert subclass.  Therefore, we must check for its presence
+ * here and update gIOOptionsEntry for the platform code as necessary.
+ */
 inline static int
 init_gIOOptionsEntry(void)
 {
@@ -1290,7 +1365,7 @@ coprocessor_type_t
 PEGetCoprocessorVersion( void )
 {
        coprocessor_type_t coprocessor_version = kCoprocessorVersionNone;
-#if !CONFIG_EMBEDDED
+#if defined(__x86_64__)
        IORegistryEntry     *platform_entry = NULL;
        OSData              *coprocessor_version_obj = NULL;
 
@@ -1307,50 +1382,55 @@ PEGetCoprocessorVersion( void )
 }
 } /* extern "C" */
 
-void
-IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
-{
-       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;
+bool gIOPlatformUUIDAndSerialDone = false;
 
-                       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 );
+void
+IOPlatformExpert::publishPlatformUUIDAndSerial( void )
+{
+       if (!gIOPlatformUUIDAndSerialDone) {
+               // Parse the serial-number data and publish a user-readable string
+               if (NULL == getProvider()->getProperty(kIOPlatformSerialNumberKey)) {
+                       OSData* mydata = (OSData*) (getProvider()->getProperty("serial-number"));
+                       if (mydata != NULL) {
+                               OSString *serNoString = createSystemSerialNumberString(mydata);
+                               if (serNoString != NULL) {
+                                       getProvider()->setProperty(kIOPlatformSerialNumberKey, serNoString);
+                                       serNoString->release();
+                               }
                        }
                }
+               IOPlatformExpertDevice *provider = OSDynamicCast(IOPlatformExpertDevice, getProvider());
+               assert(provider != NULL);
+               provider->generatePlatformUUID();
+       }
 
-               entry->release();
+       if (gIOPlatformUUIDAndSerialDone) {
+               publishResource(kIOPlatformUUIDKey, getProvider()->getProperty(kIOPlatformUUIDKey));
        }
-#endif /* CONFIG_EMBEDDED */
+}
+
+void
+IOPlatformExpert::publishNVRAM( void )
+{
+       if (init_gIOOptionsEntry() < 0) {
+               IOPlatformExpertDevice *provider = OSDynamicCast(IOPlatformExpertDevice, getProvider());
+               assert(provider != NULL);
+               provider->createNVRAM();
+       }
+       if (gIOOptionsEntry != NULL) {
+               gIOOptionsEntry->registerService();
+       }
+}
+
+void
+IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
+{
+#if defined(__x86_64__)
+       OSData *          data;
+       IORegistryEntry * entry;
 
-#if defined(XNU_TARGET_OS_OSX)
        /*
-        * If we have panic debugging enabled and the bridgeOS panic SoC watchdog is enabled,
+        * If we have panic debugging enabled and a prod-fused coprocessor,
         * 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.
         */
@@ -1370,49 +1450,26 @@ IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
                }
        }
 
-       entry = IORegistryEntry::fromPath( "/efi/platform", gIODTPlane );
+#if (DEVELOPMENT || DEBUG)
+       entry = IORegistryEntry::fromPath( "/options", 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 );
+               data = OSDynamicCast( OSData, entry->getProperty(nvram_osenvironment));
+               if (data) {
+                       sysctl_set_osenvironment(data->getLength(), data->getBytesNoCopy());
+                       entry->removeProperty(nvram_osenvironment);
+                       IODTNVRAM * nvramOptionsEntry = OSDynamicCast(IODTNVRAM, entry);
+                       if (nvramOptionsEntry) {
+                               nvramOptionsEntry->sync();
                        }
-
-                       entry->release();
                }
+               entry->release();
        }
+       sysctl_unblock_osenvironment();
+#endif
+       /* on intel the UUID must be published after nvram is available */
+       publishPlatformUUIDAndSerial();
 
-       if (string) {
-               getProvider()->setProperty( kIOPlatformUUIDKey, string );
-               publishResource( kIOPlatformUUIDKey, string );
-
-               string->release();
-       }
+#endif /* defined(__x86_64__) */
 
        publishResource("IONVRAM");
 }
@@ -1536,6 +1593,45 @@ IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
                        }
 
                        nub->attach( parent );
+#if !defined(__x86_64__)
+                       OSData *tmpData = (OSData *)next->getProperty("device_type");
+                       if (tmpData == NULL) {
+                               nub->registerService();
+                               continue;
+                       }
+
+                       char *device_type = (char *)tmpData->getBytesNoCopy();
+                       if (strcmp(device_type, "cpu") != 0) {
+                               nub->registerService();
+                               continue;
+                       }
+
+                       tmpData = (OSData *)next->getProperty("reg");
+                       assert(tmpData != NULL);
+                       assert(tmpData->getLength() >= sizeof(UInt32));
+
+                       uint32_t phys_id = *(UInt32 *)tmpData->getBytesNoCopy();
+                       int logical_cpu_id = ml_get_cpu_number(phys_id);
+                       int logical_cluster_id = ml_get_cluster_number(phys_id);
+
+                       /*
+                        * If the following condition triggers, it means that a CPU that was present in the DT
+                        * was ignored by XNU at topology parsing time. This can happen currently when using the
+                        * cpus=N boot-arg; for example, cpus=1 will cause XNU to parse and enable a single CPU.
+                        *
+                        * Note that this condition will not trigger for harvested cores because these do not show up
+                        * in the DT/IORegistry in the first place.
+                        */
+                       if (logical_cpu_id < 0) {
+                               nub->registerService();
+                               continue;
+                       }
+
+                       __assert_only bool logical_id_added_to_ioreg = nub->setProperty("logical-cpu-id", logical_cpu_id, 32U);
+                       assert(logical_id_added_to_ioreg == true);
+                       logical_id_added_to_ioreg = nub->setProperty("logical-cluster-id", logical_cluster_id, 32U);
+                       assert(logical_id_added_to_ioreg == true);
+#endif
                        nub->registerService();
                }
                iter->release();
@@ -1550,7 +1646,6 @@ IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
        OSIterator *        kids;
        IORegistryEntry *   next;
        IORegistryEntry *   cpus;
-       IORegistryEntry *   options;
 
        // infanticide
        kids = IODTFindMatchingEntries( rootEntry, 0, deleteList());
@@ -1561,21 +1656,9 @@ IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
                kids->release();
        }
 
-       // 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();
-                       }
-               }
-       }
+       publishNVRAM();
+       assert(gIOOptionsEntry != NULL); // subclasses that do their own NVRAM initialization shouldn't be calling this
+       dtNVRAM = gIOOptionsEntry;
 
        // Publish the cpus.
        cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
@@ -1608,6 +1691,20 @@ IODTPlatformExpert::compareNubName( const IOService * nub,
               || super::compareNubName( nub, name, matched);
 }
 
+
+/*
+ * Do not use this method directly, it returns inconsistent results
+ * across architectures and is considered deprecated.
+ *
+ * Use getTargetName and getProductName respectively.  For example:
+ *
+ * targetName: J137AP
+ * productName: iMacPro1,1
+ *
+ * targetName: D331pAP
+ * productName: iPhone11,6
+ */
+
 bool
 IODTPlatformExpert::getModelName( char * name, int maxLength )
 {
@@ -1645,6 +1742,19 @@ IODTPlatformExpert::getModelName( char * name, int maxLength )
        return ok;
 }
 
+/*
+ * Do not use this method directly, it returns inconsistent results
+ * across architectures and is considered deprecated.
+ *
+ * Use getTargetName and getProductName respectively.  For example:
+ *
+ * targetName: J137AP
+ * productName: iMacPro1,1
+ *
+ * targetName: D331pAP
+ * productName: iPhone11,6
+ */
+
 bool
 IODTPlatformExpert::getMachineName( char * name, int maxLength )
 {
@@ -1662,6 +1772,46 @@ IODTPlatformExpert::getMachineName( char * name, int maxLength )
        return ok;
 }
 
+/* Examples: J137AP, D331pAP... */
+
+bool
+IODTPlatformExpert::getTargetName( char * name, int maxLength )
+{
+#if __x86_64__
+       OSData *            prop;
+
+       const OSSymbol *        key = gIODTBridgeModelKey;
+
+       maxLength--;
+       prop = (OSData *) getProvider()->getProperty( key );
+
+       if (prop == NULL) {
+               // This happens if there is no bridge.
+               char const * const  unknown = "";
+
+               strlcpy( name, unknown, maxLength );
+       } else {
+               strlcpy( name, (const char *)prop->getBytesNoCopy(), maxLength );
+       }
+
+       return true;
+#else
+       return getModelName( name, maxLength );
+#endif
+}
+
+/* Examples: iMacPro1,1, iPhone11,6... */
+
+bool
+IODTPlatformExpert::getProductName( char * name, int maxLength )
+{
+#if __x86_64__
+       return getModelName( name, maxLength );
+#else
+       return getMachineName( name, maxLength );
+#endif
+}
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 void
@@ -1718,6 +1868,22 @@ IODTPlatformExpert::readNVRAMProperty(
        }
 }
 
+IOReturn
+IODTPlatformExpert::readNVRAMProperty(
+       IORegistryEntry * entry,
+       OSSharedPtr<const OSSymbol>& name, OSSharedPtr<OSData>& value )
+{
+       const OSSymbol* nameRaw = NULL;
+       OSData* valueRaw = NULL;
+
+       IOReturn result = readNVRAMProperty(entry, &nameRaw, &valueRaw);
+
+       name.reset(nameRaw, OSNoRetain);
+       value.reset(valueRaw, OSNoRetain);
+
+       return result;
+}
+
 IOReturn
 IODTPlatformExpert::writeNVRAMProperty(
        IORegistryEntry * entry,
@@ -1841,14 +2007,12 @@ IOPlatformExpertDevice::compareName( OSString * name,
 }
 
 bool
-IOPlatformExpertDevice::initWithArgs(
-       void * dtTop, void * p2, void * p3, void * p4 )
+IOPlatformExpertDevice::init(void *dtRoot)
 {
        IORegistryEntry *   dt = NULL;
        bool                ok;
 
-       // dtTop may be zero on non- device tree systems
-       if (dtTop && (dt = IODeviceTreeAlloc( dtTop ))) {
+       if ((dtRoot != NULL) && (dt = IODeviceTreeAlloc(dtRoot))) {
                ok = super::init( dt, gIODTPlane );
        } else {
                ok = super::init();
@@ -1858,11 +2022,19 @@ IOPlatformExpertDevice::initWithArgs(
                return false;
        }
 
+       return true;
+}
+
+bool
+IOPlatformExpertDevice::startIOServiceMatching(void)
+{
        workLoop = IOWorkLoop::workLoop();
        if (!workLoop) {
                return false;
        }
 
+       registerService();
+
        return true;
 }
 
@@ -1927,6 +2099,131 @@ IOPlatformExpertDevice::free()
        }
 }
 
+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();
+       }
+}
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #undef super