void AlcEnabler::processKext(size_t index, mach_vm_address_t address, size_t size) { patcher.updateRunningInfo(index, address, size); if (patcher.getError() == KernelPatcher::Error::NoError) { if (!(progressState & ProcessingState::ControllersLoaded)) { grabControllers(); progressState |= ProcessingState::ControllersLoaded; } else if (!(progressState & ProcessingState::CodecsLoaded)) { for (size_t i = 0; i < kextListSize; i++) { if (kextList[i].loadIndex == index) { if (kextList[i].detectCodecs && grabCodecs()) { progressState |= ProcessingState::CodecsLoaded; break; } DBGLOG("alc @ failed to find a suitable codec, we have nothing to do"); return; } } } if (progressState & ProcessingState::ControllersLoaded) { for (size_t i = 0, num = controllers.size(); i < num; i++) { auto &info = controllers[i]->info; if (!info) { DBGLOG("alc @ missing ControllerModInfo for %zu controller", i); continue; } applyPatches(index, info->patches, info->patchNum); } } if (progressState & ProcessingState::CodecsLoaded) { for (size_t i = 0, num = codecs.size(); i < num; i++) { auto &info = codecs[i]->info; if (!info) { SYSLOG("alc @ missing CodecModInfo for %zu codec", i); continue; } if (info->platforms > 0 && info->layoutNum > 0) { DBGLOG("alc @ will route callbacks resource loading callbacks"); progressState |= ProcessingState::CallbacksWantRouting; } applyPatches(index, info->patches, info->patchNum); } } if ((progressState & ProcessingState::CallbacksWantRouting) && !(progressState & ProcessingState::CallbacksRouted)) { auto layout = patcher.solveSymbol(index, "__ZN14AppleHDADriver18layoutLoadCallbackEjiPKvjPv"); auto platform = patcher.solveSymbol(index, "__ZN14AppleHDADriver20platformLoadCallbackEjiPKvjPv"); if (!layout || !platform) { SYSLOG("alc @ failed to find AppleHDA layout or platform callback symbols (%llX, %llX)", layout, platform); } else if (orgLayoutLoadCallback = reinterpret_cast<t_callback>(patcher.routeFunction(layout, reinterpret_cast<mach_vm_address_t>(layoutLoadCallback), true)), patcher.getError() != KernelPatcher::Error::NoError) { SYSLOG("alc @ failed to hook layout callback"); } else if (orgPlatformLoadCallback = reinterpret_cast<t_callback>(patcher.routeFunction(platform, reinterpret_cast<mach_vm_address_t>(platformLoadCallback), true)), patcher.getError() != KernelPatcher::Error::NoError) { SYSLOG("alc @ failed to hook platform callback"); } else { progressState |= ProcessingState::CallbacksRouted; } } } else { SYSLOG("alc @ failed to update kext running info"); } // Ignore all the errors for other processors patcher.clearError(); }
void AlcEnabler::processKext(size_t index, mach_vm_address_t address, size_t size) { // We could have done some of this earlier by requiring com.apple.iokit.IOHDAFamily to load first // However, IOHDAFamily has insane version compatibilities over the OS X versions, I am lazy to use // TrustedBSD apis, and we might want to patch other kexts one day, so better to be ready asap and // keep this in one place... if (index == kextAppleHDA->loadIndex && !grabCodecs()) { SYSLOG("alc @ failed to find a suitable codec, we have nothing to do"); return; } patcher.updateRunningInfo(index, address, size); bool routeCallbacks {false}; for (size_t i = 0, num = codecs.size(); i < num; i++) { auto &info = codecs[i]->info; if (!info) { SYSLOG("alc @ missing CodecModInfo for %zu codec", i); continue; } if (index == kextAppleHDA->loadIndex && info->platforms > 0 && info->layoutNum > 0) { DBGLOG("alc @ will route callbacks resource loading callbacks"); routeCallbacks = true; } for (size_t p = 0; p < info->patchNum; p++) { auto &patch = info->patches[p]; if (patch.patch.kext->loadIndex == index) { if (patcher.compatibleKernel(patch.minKernel, patch.maxKernel)) { patcher.applyLookupPatch(&patch.patch); // Do not really care for the errors for now patcher.clearError(); } } else if (patch.patch.kext->loadIndex == KernelPatcher::KextInfo::Unloaded) { auto loadIndex = patcher.loadKinfo(patch.patch.kext); if (patcher.getError() != KernelPatcher::Error::NoError) { patch.patch.kext->loadIndex = loadIndex; // A future recursion here auto handler = KernelPatcher::KextHandler::create(patch.patch.kext->id, patch.patch.kext->loadIndex, [](KernelPatcher::KextHandler *h) { if (h) { that->processKext(h->index, h->address, h->size); } else { SYSLOG("alc @ extra notification callback arrived at nowhere"); } }); if (handler) { patcher.waitOnKext(handler); } else { SYSLOG("alc @ failed to allocate an extra KextHandler"); } } // Do not really care for the errors for now patcher.clearError(); } } } if (routeCallbacks) { auto layout = patcher.solveSymbol(index, "__ZN14AppleHDADriver18layoutLoadCallbackEjiPKvjPv"); auto platform = patcher.solveSymbol(index, "__ZN14AppleHDADriver20platformLoadCallbackEjiPKvjPv"); if (!layout || !platform) { SYSLOG("alc @ failed to find AppleHDA layout or platform callback symbols (%llX, %llX)", layout, platform); return; } orgLayoutLoadCallback = reinterpret_cast<t_callback>(patcher.routeFunction(layout, reinterpret_cast<mach_vm_address_t>(layoutLoadCallback), true)); if (patcher.getError() != KernelPatcher::Error::NoError) { SYSLOG("alc @ failed to hook layout callback"); return; } orgPlatformLoadCallback = reinterpret_cast<t_callback>(patcher.routeFunction(platform, reinterpret_cast<mach_vm_address_t>(platformLoadCallback), true)); if (patcher.getError() != KernelPatcher::Error::NoError) { SYSLOG("alc @ failed to hook platform callback"); return; } } }