Override Mac XNU kernel without recompiling source code

517 views Asked by At

I want to use Macbook air in clamshell mode without AC adapter connected. However, Mac OS will force system going to sleep when I close lid.

I found this part of XNU kernel from apple open source may relate to this behavior:

iokit/Kernel/IOPMrootDomain.cpp

...

6362     /*
6363      * Evaluate clamshell and SLEEP if appropiate
6364      */
6365     if (eval_clamshell && clamshellClosed)
6366     {
6367         if (shouldSleepOnClamshellClosed())
6368             privateSleepSystem (kIOPMSleepReasonClamshell);
6369         else
6370             evaluatePolicy( kStimulusDarkWakeEvaluate );
6371     }

...

3061 //******************************************************************************
3062 // sleepOnClamshellClosed
3063 //
3064 // contains the logic to determine if the system should sleep when the clamshell
3065 // is closed.
3066 //******************************************************************************
3067 
3068 bool IOPMrootDomain::shouldSleepOnClamshellClosed( void )
3069 {
3070     if (!clamshellExists)
3071         return false;
3072 
3073     DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3074         clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected, clamshellSleepDisabled);
3075 
3076     return ( !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisabled );
3077 }

Of course, I can compile kernel but I doubt if it is latest Mavericks kernel. So I want to know if I can override kernel space function as we do it for user space function by inserting dynamic library.

1

There are 1 answers

2
pmdj On

Recompiling the xnu kernel is easier than you seem to think:

http://shantonu.blogspot.ca/2013/10/building-xnu-for-os-x-109-mavericks.html

Apple have been pretty slow to release source code for maintenance releases of OSX however, so you would have to delay updates 10.9.x until source becomes available.

Aside from that, you have a 2 obvious options:

  • Patch the mach_kernel executable directly on disk.
  • Patch the IOPMrootDomain::shouldSleepOnClamshellClosed function at runtime using a purpose-built kext.

In both cases, locate the IOPMrootDomain::shouldSleepOnClamshellClosed function in the mach_kernel disassembly. Figure out where it reads acAdaptorConnected and replace those instructions with ones that make the code behave as if acAdaptorConnected were always true.

You'll need to take care when patching at runtime. The method is private, so you can't directly get its address using the kext linker, so you'd need to get the address from elsewhere.

FWIW, I'm not 100% convinced this code is to blame for the behaviour you're seeing. clamshellDisabled should normally be true if an external display is attached. If you're specifically trying to use your Macbook with no screen attached, you can try generating a fake kIOPMDisableClamshell power event, which should flip that flag.

As an aside, it's somewhat disappointing that Apple has hardcoded such behaviour in the kernel - seems like the thing a simple userspace script should be deciding. :-(