]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/RootDomainUserClient.cpp
xnu-1228.tar.gz
[apple/xnu.git] / iokit / Kernel / RootDomainUserClient.cpp
index c6c812c547df51e8eadf3e0afbad2821fd3e090f..170ab0eaef04b27ed629ab3682f69cad3e0b3e97 100644 (file)
@@ -71,26 +71,75 @@ bool RootDomainUserClient::start( IOService * provider )
     return true;
 }
 
-IOReturn RootDomainUserClient::secureSleepSystem( int *return_code )
+IOReturn RootDomainUserClient::secureSleepSystem( uint32_t *return_code )
 {
+    IOByteCount     return_code_size = 1;
+
+    return secureSleepSystemOptions( NULL,      // inOptions
+                                     (void *)return_code, // returnCode
+                                     (void *)0,     // inSize
+                                     (void *)&return_code_size, // returnSize
+                                     NULL, NULL);
+}
+
+IOReturn RootDomainUserClient::secureSleepSystemOptions( 
+    void * p1, void * p2, void * p3,
+    void * p4, void * p5, void * p6 )
+{
+    void            *inOptions = (void *)p1; 
+    uint32_t        *returnCode = (uint32_t *)p2;
+    IOByteCount     inOptionsSize = (IOByteCount)p3;
+    IOByteCount     *returnCodeSize = (IOByteCount *)p4;
+
     int             local_priv = 0;
     int             admin_priv = 0;
     IOReturn        ret = kIOReturnNotPrivileged;
+    OSDictionary    *unserializedOptions =  NULL;
+    OSString        *unserializeErrorString = NULL;
 
     ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeLocalUser);
     local_priv = (kIOReturnSuccess == ret);
     
     ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
     admin_priv = (kIOReturnSuccess == ret);
+    
+    *returnCodeSize = sizeof(uint32_t);
+    
+    if (inOptions)
+    {
+        unserializedOptions = OSDynamicCast( OSDictionary,
+                                             OSUnserializeXML((const char *)inOptions, &unserializeErrorString));
+    
+        if (!unserializedOptions) {
+            IOLog("IOPMRootDomain SleepSystem unserialization failure: %s\n", 
+                unserializeErrorString ? unserializeErrorString->getCStringNoCopy() : "Unknown");
+        }
+    }
+
+    if ( (local_priv || admin_priv) 
+          && fOwner ) 
+    {
+        if (unserializedOptions) 
+        {
+            // Publish Sleep Options in registry under root_domain
+            fOwner->setProperty( kRootDomainSleepOptionsKey, unserializedOptions);            
+
+            *returnCode = fOwner->sleepSystemOptions( unserializedOptions );
+
+            unserializedOptions->release();        
+        } else {
+            // No options
+            // Clear any pre-existing options
+            fOwner->removeProperty( kRootDomainSleepOptionsKey );
+
+            *returnCode = fOwner->sleepSystemOptions( NULL );        
+        }
 
-    if((local_priv || admin_priv) && fOwner) {
-        *return_code = fOwner->sleepSystem();
-        return kIOReturnSuccess;
     } else {
-        *return_code = kIOReturnNotPrivileged;
-        return kIOReturnSuccess;
+        *returnCode = kIOReturnNotPrivileged;
     }
 
+    return kIOReturnSuccess;
 }
 
 IOReturn RootDomainUserClient::secureSetAggressiveness( 
@@ -134,7 +183,7 @@ IOReturn RootDomainUserClient::clientClose( void )
 IOExternalMethod *
 RootDomainUserClient::getTargetAndMethodForIndex( IOService ** targetP, UInt32 index )
 {
-    static IOExternalMethod sMethods[] = {
+    static const IOExternalMethod sMethods[] = {
         { // kPMSetAggressiveness, 0
             (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1
         },
@@ -156,9 +205,10 @@ RootDomainUserClient::getTargetAndMethodForIndex( IOService ** targetP, UInt32 i
         { // kPMRestartSystem, 6
             0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0
         },
-        { // kPMSetPreventative, 7
-            (IOService *)1, (IOMethod)&RootDomainUserClient::setPreventative, kIOUCScalarIScalarO, 2, 0
-        },
+        { // kPMSleepSystemOptions, 7
+            (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystemOptions, 
+            kIOUCStructIStructO, kIOUCVariableStructureSize, sizeof(uint32_t)
+        }
     };
     
     if(index >= kNumPMMethods)
@@ -169,10 +219,53 @@ RootDomainUserClient::getTargetAndMethodForIndex( IOService ** targetP, UInt32 i
         else
             *targetP = fOwner;
 
-        return &sMethods[index];
+        return (IOExternalMethod *)&sMethods[index];
     }
 }
 
+#if 0
+IOReturn RootDomainUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
+                                               IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
+{
+    static const IOExternalMethodDispatch sMethods[] = {
+        { // kPMSetAggressiveness, 0
+            (IOService *)1, (IOMethod)&RootDomainUserClient::secureSetAggressiveness, kIOUCScalarIScalarO, 2, 1
+        },
+        { // kPMGetAggressiveness, 1
+            0, (IOMethod)&IOPMrootDomain::getAggressiveness, kIOUCScalarIScalarO, 1, 1
+        },
+        { // kPMSleepSystem, 2
+            (IOService *)1, (IOMethod)&RootDomainUserClient::secureSleepSystem, kIOUCScalarIScalarO, 0, 1
+        },
+        { // kPMAllowPowerChange, 3
+            0, (IOMethod)&IOPMrootDomain::allowPowerChange, kIOUCScalarIScalarO, 1, 0
+        },
+        { // kPMCancelPowerChange, 4
+            0, (IOMethod)&IOPMrootDomain::cancelPowerChange, kIOUCScalarIScalarO, 1, 0
+        },
+        { // kPMShutdownSystem, 5
+            0, (IOMethod)&IOPMrootDomain::shutdownSystem, kIOUCScalarIScalarO, 0, 0
+        },
+        { // kPMRestartSystem, 6
+            0, (IOMethod)&IOPMrootDomain::restartSystem, kIOUCScalarIScalarO, 0, 0
+        },
+        { // kPMSetPreventative, 7
+            (IOService *)1, (IOMethod)&RootDomainUserClient::setPreventative, kIOUCScalarIScalarO, 2, 0
+        },
+    };
+
+    if (selector > (sizeof(sMethods) / sizeof(sMethods[0])))
+       return (kIOReturnBadArgument);
+
+    if ((1 << selector) & ((1 << 0) | (1 << 7))
+       target = this;
+    else
+       target = fOwner;
+
+    return (super::externalMethod(selector, args, &sMethods[selector], target, 0));
+}
+#endif
+
 void 
 RootDomainUserClient::setPreventative(UInt32 on_off, UInt32 types_of_sleep)
 {