Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 79 additions & 1 deletion WhateverGreen/kern_rad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#include <Headers/kern_devinfo.hpp>
#include <IOKit/IOService.h>

#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/uio.h>
#include <sys/namei.h>

#include <Availability.h>
#include <IOKit/IOPlatformExpert.h>

Expand Down Expand Up @@ -302,6 +307,73 @@ IOReturn RAD::wrapAMDRadeonX6000AmdRadeonFramebufferGetAttribute(IOService *fram
return ret;
}

bool fileExistsAtPath(const char *path) {
vnode_t vp = NULL;
vfs_context_t ctx = vfs_context_current();
int error = vnode_lookup(path, 0, &vp, ctx);

if (error == 0 && vp != NULL) {
vnode_put(vp);
DBGLOG("rad", "File exists: %s", path);
return true;
}

DBGLOG("rad", "File NOT found: %s (error: %d)", path, error);
return false;
}

bool RAD::isNormalSys() {
const char* modeStr = "Unknown";
switch (lilu.getRunMode()) {
case 1: modeStr = "Normal Boot"; break;
case 2: modeStr = "Recovery/Installer"; break;
case 4: modeStr = "Safe Mode"; break;
}

IOLog("WEG: isNormalSys() called | RunMode: %s (%d)\n", modeStr, lilu.getRunMode());

// Ignore all detections when forcibly enabling -radconnector
if (lilu.getRunMode() == 1 && checkKernelArgument("-radconnector")) {
IOLog("WEG: -radconnector detected in Recovery, FORCING override enable\n");
return true;
}

// Directly reject abnormal startup environments
if (lilu.getRunMode() != 1) {
IOLog("WEG: Not in Normal Boot mode, but RunMode=%d → blocking override\n", lilu.getRunMode());
return false;
}

// When using BaseSystemKernelExtensions as the Kernel Cache, the linker is also not overwritten.
// Because in the second stage of the OTA (when the macOS Installer finishes booting and the volume
// label returns to Macintosh HD), it still uses BaseSystemKernelExtensions.kc, but Lilu mistakenly determines
// it as a normal boot. This causes it to still freeze during the KC verification stage.
if (fileExistsAtPath("/System/Library/KernelCollections/BaseSystemKernelExtensions.kc")) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we want this to be fixed on Lilu side.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we want this to be fixed on Lilu side.

As of now, only this patch has encountered issues on macOS Tahoe. Perhaps modifying WhateverGreen is already simple enough, there is no need to modify Lilu temporarily

IOLog("WEG: BaseSystemKernelExtensions.kc EXISTS -> BLOCK override (prevent freeze)\n");
return false;
}

IOLog("WEG: Normal boot -> ALLOW connector override\n");
return true;
}

bool RAD::ifNeedOverrideConnector(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
// No need to overwrite the connector when booting BaseSystem on macOS Tahoe.
// This step is unnecessary and will cause macOS Tahoe recovery mode to freeze when booting.
// Committed by laobamac
if (getKernelVersion() >= KernelVersion::Tahoe) {
if (!isNormalSys()) {
IOLog("WEG: skip override.\n");
return false;
} else {
IOLog("WEG: allow override.\n");
return true;
}
} else {
return true;
}
}

bool RAD::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
if (kextRadeonX6000Framebuffer.loadIndex == index) {
KernelPatcher::RouteRequest requests[] = {
Expand Down Expand Up @@ -333,7 +405,13 @@ bool RAD::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t ad
}

if (kextRadeonSupport.loadIndex == index) {
processConnectorOverrides(patcher, address, size, true);
// The abnormal start-up system does not cover the connector on Tahoe.
if (ifNeedOverrideConnector(patcher, index, address, size) != false) {
Copy link
Collaborator

@vit9696 vit9696 Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After we fix Lilu to correctly detect normal mode I believe the change here should look as follows:

if (getKernelVersion() < KernelVersion::Tahoe
  || checkKernelArgument("-radconnector")
  || lilu.getRunMode() == LiluAPI::RunningNormal) {
  processConnectorOverrides(patcher, address, size, true);
  DBGLOG("rad", "processing override connector");
} else {
  DBGLOG("rad", "skipping override connector");
}

No other changes should be necessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After we fix Lilu to correctly detect normal mode I believe the change here should look as follows:

if (getKernelVersion() < KernelVersion::Tahoe || checkKernelArgument("-radconnector") || lilu.getRunMode() == LiluAPI::RunningNormal) {
  processConnectorOverrides(patcher, address, size, true);
  DBGLOG("rad", "processing override connector");
} else {
  DBGLOG("rad", "skipping override connector");
}

No other changes should be necessary.

I understand, do you mean to put the method that recognizes BaseSystemKernelExtendes.kc into Lilu's getRunMode?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we could go this way if no better is found. Please make sure we guard it with macOS 26, so that we definitely do not regress on older operating systems. Ideally we want a lighter approach.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we could go this way if no better is found. Please make sure we guard it with macOS 26, so that we definitely do not regress on older operating systems. Ideally we want a lighter approach.

But when Lilu.kext checks the running status, the root file system may not have been loaded yet, and using vfs_lookup at this time will cause a panic.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I think we should find some other approach. Do you have an ioreg dump? Ideally both IODeviceTree and IOService planes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I think we should find some other approach. Do you have an ioreg dump? Ideally both IODeviceTree and IOService planes.

Unfortunately, ioreg only recorded BootKernelExtensions.kc. And there is no other obvious difference except BaseSystemKernelExtendes.kc.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, could you upload one for me to think about it as well? If it contains private data, you could also e-mail me to vit9696 at pm dot me ^^

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, could you upload one for me to think about it as well? If it contains private data, you could also e-mail me to vit9696 at pm dot me ^^

OK, Wait for me a moment, I will restart into Recovery and save one

processConnectorOverrides(patcher, address, size, true);
IOLog("WEG: Override Connector.\n");
}
else
IOLog("WEG: WON'T Override Connector.\n");

if (getKernelVersion() > KernelVersion::Mojave ||
(getKernelVersion() == KernelVersion::Mojave && getKernelMinorVersion() >= 5)) {
Expand Down
6 changes: 6 additions & 0 deletions WhateverGreen/kern_rad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,12 @@ class RAD {
* Wrapped codec hw info method
*/
static void updateGetHWInfo(IOService *accelVideoCtx, void *hwInfo);

/**
* If need override connector
*/
bool ifNeedOverrideConnector(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);
bool isNormalSys();
};

#endif /* kern_rad_hpp */