-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
395 additions
and
369 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// | ||
// CPUFriend.cpp | ||
// CPUFriend | ||
// | ||
// Copyright © 2017 Vanilla. All rights reserved. | ||
// | ||
|
||
#include <Headers/kern_api.hpp> | ||
|
||
#include "CPUFriend.hpp" | ||
|
||
static const char * binList[] { | ||
"/System/Library/Extensions/IOPlatformPluginFamily.kext/Contents/PlugIns/X86PlatformPlugin.kext/Contents/MacOS/X86PlatformPlugin" | ||
}; | ||
|
||
static const char * idList[] { | ||
"com.apple.driver.X86PlatformPlugin" | ||
}; | ||
|
||
static const char * symbolList[] { | ||
"__ZN17X86PlatformPlugin22configResourceCallbackEjiPKvjPv" | ||
}; | ||
|
||
static KernelPatcher::KextInfo kextList[] { | ||
{ idList[0], & binList[0], arrsize(binList), { false, false }, {}, KernelPatcher::KextInfo::Unloaded } | ||
}; | ||
|
||
static constexpr size_t kextListSize = arrsize(kextList); | ||
|
||
static CPUFriendPlugin * callbackCpuf = nullptr; | ||
|
||
OSDefineMetaClassAndStructors(CPUFriendPlatform, IOService) | ||
|
||
IOService * CPUFriendPlatform::probe(IOService * provider, SInt32 * score) { | ||
if (provider) { | ||
if (callbackCpuf) { | ||
if (! callbackCpuf->frequencyData) { | ||
auto name = provider->getName(); | ||
if (! name) | ||
name = "(null)"; | ||
DBGLOG("probe", "looking for cf-frequency-data in %s", name); | ||
|
||
auto data = OSDynamicCast(OSData, provider->getProperty("cf-frequency-data")); | ||
if (! data) { | ||
auto cpu = provider->getParentEntry(gIOServicePlane); | ||
if (cpu) { | ||
name = cpu->getName(); | ||
if (! name) | ||
name = "(null)"; | ||
DBGLOG("probe", "looking for cf-frequency-data in %s", name); | ||
data = OSDynamicCast(OSData, cpu->getProperty("cf-frequency-data")); | ||
} else { | ||
SYSLOG("probe", "unable to access cpu parent"); | ||
} | ||
} | ||
|
||
if (data) { | ||
callbackCpuf->frequencyDataSize = data->getLength(); | ||
callbackCpuf->frequencyData = data->getBytesNoCopy(); | ||
} else { | ||
SYSLOG("probe", "failed to obtain cf-frequency-data"); | ||
} | ||
} | ||
} else | ||
SYSLOG("probe", "missing storage instance"); | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
bool CPUFriendPlugin::init() { | ||
callbackCpuf = this; | ||
|
||
LiluAPI::Error error = lilu.onKextLoad(kextList, kextListSize, [](void * user, KernelPatcher & patcher, size_t index, mach_vm_address_t address, size_t size) { | ||
static_cast<CPUFriendPlugin * >(user)->processKext(patcher, index, address, size); | ||
}, this); | ||
|
||
if (error != LiluAPI::Error::NoError) { | ||
SYSLOG("init", "failed to register onKextLoad method %d", error); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void CPUFriendPlugin::myConfigResourceCallback(uint32_t requestTag, kern_return_t result, const void * resourceData, uint32_t resourceDataLength, void * context) { | ||
if (callbackCpuf && callbackCpuf->orgConfigLoadCallback) { | ||
auto data = callbackCpuf->frequencyData; | ||
auto sz = callbackCpuf->frequencyDataSize; | ||
if (data && sz > 0) { | ||
DBGLOG("myConfigResourceCallback", "feeding frequency data %u", sz); | ||
resourceData = data; | ||
resourceDataLength = sz; | ||
result = kOSReturnSuccess; | ||
} else { | ||
SYSLOG("myConfigResourceCallback", "failed to feed cpu data (%u, %d)", sz, data != nullptr); | ||
} | ||
callbackCpuf->orgConfigLoadCallback(requestTag, result, resourceData, resourceDataLength, context); | ||
} else { | ||
SYSLOG("myConfigResourceCallback", "config callback arrived at nowhere"); | ||
} | ||
} | ||
|
||
void CPUFriendPlugin::processKext(KernelPatcher & patcher, size_t index, mach_vm_address_t address, size_t size) { | ||
if (progressState != ProcessingState::EverythingDone) { | ||
for (size_t i = 0; i < kextListSize; i++) { | ||
if (kextList[i].loadIndex == index) { | ||
DBGLOG("processKext", "current kext is %s progressState %d", kextList[i].id, progressState); | ||
// clear error from the very beginning just in case | ||
patcher.clearError(); | ||
if (! strcmp(kextList[i].id, idList[0])) { | ||
auto callback = patcher.solveSymbol(index, symbolList[0]); | ||
if (callback) { | ||
orgConfigLoadCallback = reinterpret_cast<t_callback>(patcher.routeFunction(callback, reinterpret_cast<mach_vm_address_t>(myConfigResourceCallback), true)); | ||
if (patcher.getError() == KernelPatcher::Error::NoError) { | ||
DBGLOG("processKext", "routed %s", symbolList[0]); | ||
} else { | ||
SYSLOG("processKext", "failed to route %s", symbolList[0]); | ||
} | ||
} else { | ||
SYSLOG("processKext", "failed to find %s", symbolList[0]); | ||
} | ||
progressState |= ProcessingState::CallbackRouted; | ||
} | ||
} | ||
} | ||
} | ||
// Ignore all the errors for other processors | ||
patcher.clearError(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// | ||
// CPUFriend.hpp | ||
// CPUFriend | ||
// | ||
// Copyright © 2017 Vanilla. All rights reserved. | ||
// | ||
|
||
#ifndef kern_cpuf_hpp | ||
#define kern_cpuf_hpp | ||
|
||
#include <Headers/kern_patcher.hpp> | ||
#include <Library/LegacyIOService.h> | ||
|
||
class EXPORT CPUFriendPlatform : public IOService { | ||
OSDeclareDefaultStructors(CPUFriendPlatform) | ||
public: | ||
IOService * probe(IOService * provider, SInt32 *score) override; | ||
}; | ||
|
||
class CPUFriendPlugin { | ||
public: | ||
bool init(); | ||
|
||
/** | ||
* ResourceLoad callback type | ||
*/ | ||
using t_callback = void (*)(uint32_t, kern_return_t, const void *, uint32_t, void *); | ||
|
||
/** | ||
* Trampolines for original resource load callback | ||
*/ | ||
t_callback orgConfigLoadCallback = nullptr; | ||
|
||
/** | ||
* Loaded user-specified frequency data | ||
*/ | ||
const void * frequencyData = nullptr; | ||
|
||
/** | ||
* Loaded user-specified frequency data size | ||
*/ | ||
uint32_t frequencyDataSize = 0; | ||
|
||
private: | ||
/** | ||
* Hooked ResourceLoad callback returning user-specified platform data | ||
*/ | ||
static void myConfigResourceCallback(uint32_t requestTag, kern_return_t result, const void * resourceData, uint32_t resourceDataLength, void * context); | ||
|
||
/** | ||
* Patch kext if needed and prepare other patches | ||
* | ||
* @param patcher KernelPatcher instance | ||
* @param index kinfo handle | ||
* @param address kinfo load address | ||
* @param size kinfo memory size | ||
*/ | ||
void processKext(KernelPatcher & patcher, size_t index, mach_vm_address_t address, size_t size); | ||
|
||
/** | ||
* Current progress mask | ||
*/ | ||
struct ProcessingState { | ||
enum : uint32_t { | ||
NothingReady = 0, | ||
CallbackRouted = 1, | ||
EverythingDone = CallbackRouted | ||
}; | ||
}; | ||
uint32_t progressState = ProcessingState::NothingReady; | ||
}; | ||
|
||
#endif /* kern_cpuf_hpp */ |
Oops, something went wrong.