MacOS – How to Delay the Loading of a Kext

bootcrashlaunchdmacos

The way the question in the title is framed might be of general interest.

The concrete problem or example that this question should be applied to is:
Finding the optimal solution to hack an otherwise dead MacBook Pro (burned out AMD discrete graphics chip) back into usable condition.

Background:

Current situation: fried dGPU, boot has to be forced into iGPU always. With default hardware settings and default system installation the machine will simply not boot.

Unwanted side-effect for disabling the dGPU in software: AMDRadeonX3000.kext mustn't load immediately, if it does – boot hangs on Yosemite, freezes in Sierra and results in quickly forced reboots due to overheating in High Sierra before the GUI is up. Symptoms observable in Sierra, last line in verbose boot is: IOConsoleUsers IOScreenLockState 3.

Not loading the kext at all: thermal management for AMD chip gets out of hand. Temperature never sinks below 65°C and easily spikes higher despite the chip not being used.

Delayed loading: All is OK an the temperature side. GPU isn't idling at full power but idling at a much lower powerstate. Depending on OS version the sensors report temperatures ranging from 0°C–60°C. Although that reading seems not really realistic or trustworthy the whole unit also stays cooler to the touch.

But "all is well" only most of the time. Every now and then there are very rare sleep issues on Sierra, and alas: every time on Yosemite.

Finding that the kext needs to be loaded for running the machine but is better not loaded (in the delayed manner at least) for sleeping the machine: an attempt to kextunload the seemingly responsible kext results in an immediate panic. This one paragraph is mainly of concern when on Yosemite but not so much on Sierra.

On top of that it may not be the optimal solution. Thermal management needs 1-2 minutes in the current configuration after loading the kext to stabilise into acceptable levels. Therefore the desire to rotate the kexts and see what might give best results.

Steps taken so far:

One of the graphics driver kexts in Sierra needs to be loaded at/around/after boot, automatically, but later.

They are interdependent of course and all loaded as deemed necessary by the system under normal circumstances.

But the system will hang on boot if the one kext in question is loaded too early and the system runs exactly as desired if it is loaded later.

In this case I confirmed that loading it either manually or together with a GUI login via hooks works.

However, this means that placing the kext in /System/Library/Extensions or /Library/Extensions results in the hang on boot as they are consulted too early.

What also does not work is using system wide launchd agents or daemons since these are also consulted too early. Same daemons under user-hierarchies do apparently not have the necessary privileges to load a kext.

So where has this one kext from /System/Library/Extensions to go?
How can a delay be enforced that this kext is only loaded after all its up or down dependencies have been loaded?

"Which kext?" you might ask.
This question is about all the AMD kexts, each to be tested individually.

This is in an attempt to further improve this guide.

Questions

Main question: How can one of those graphics kexts be forced to a delayed load? (Other than the LoginHook method.)

If this proves suboptimal for the stated goal, it would be also nice, or even better to know:

Are there other ways in software to keep the disabled dGPU under the thermal and power management rules of the system? (The less power goes through this unsused chip the better.)

That case may involve other kernel extensions as well.

Best Answer

The easiest solution is probably to outright remove the offending kernel extension from /System/Library/Extensions, in your case AMDRadeonX3000.kext. You need to:

  1. Disable System Integrity Protection. There are many guides across the internet on how to do this, but the short version is: reboot into recovery mode, open the terminal, and enter csrutil disable.

  2. Copy /System/Library/Extensions/AMDRadeonX3000.kext to a safe space somewhere else on your computer, in case something goes wrong and you need to revert.

  3. Delete AMDRadeonX3000.kext from /System/Library/Extensions.

  4. Clear your kext cache. Open the terminal and run: sudo touch /System/Library/Extensions && sudo kextcache -u /. Then reboot.

The kext may reappear after updating macOS, in which case you'll need to repeat steps 3 & 4. For this reason, although you can re-enable SIP once the kext has been removed, I recommend just leaving it off.

The Hackintosh community has more persistent methods of disabling specific kernel extensions. If you'd like, you could look into installing the Clover bootloader, which is targeted at Hackintosh users but should work on official hardware as well. For your needs, however, I think simply deleting the kext is the best solution.

Edit: This method will cause the dedicated GPU to continue receiving power, wasting the battery. In order to stop the GPU from receiving power, you will need to install Clover and then create a custom SSDT that switches off the GPU.