<commit_before>//
//  kern_alc.cpp
//  AppleALC
//
//  Copyright © 2016-2017 vit9696. All rights reserved.
//

#include <Headers/kern_api.hpp>
#include <Headers/plugin_start.hpp>
#include <Library/LegacyIOService.h>

#include <mach/vm_map.h>
#include <IOKit/IORegistryEntry.h>

#include "kern_alc.hpp"
#include "kern_resources.hpp"

// Only used in apple-driven callbacks
static AlcEnabler *callbackAlc = nullptr;
static KernelPatcher *callbackPatcher = nullptr;

bool AlcEnabler::init() {
	LiluAPI::Error error = lilu.onKextLoad(ADDPR(kextList), ADDPR(kextListSize),
	[](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
		callbackAlc = static_cast<AlcEnabler *>(user);
		callbackPatcher = &patcher;
		callbackAlc->processKext(patcher, index, address, size);
	}, this);
	
	if (error != LiluAPI::Error::NoError) {
		SYSLOG("alc", "failed to register onKextLoad method %d", error);
		return false;
	}
	
	if (getKernelVersion() >= KernelVersion::Sierra) {
		char tmp[16];
		// Unlock custom audio engines by disabling Apple private entitlement verification
		if (PE_parse_boot_argn("-alcdhost", tmp, sizeof(tmp))) {
			error = lilu.onPatcherLoad([](void *user, KernelPatcher &patcher) {
				callbackAlc = static_cast<AlcEnabler *>(user);
				callbackPatcher = &patcher;
				callbackAlc->hookEntitlementVerification(patcher);
			}, this);
			if (error != LiluAPI::Error::NoError)
				DBGLOG("alc", "failed to register onPatcherLoad method %d", error);
		}
	}
	
	
	return true;
}

void AlcEnabler::deinit() {
	controllers.deinit();
	codecs.deinit();
}

void AlcEnabler::layoutLoadCallback(uint32_t requestTag, kern_return_t result, const void *resourceData, uint32_t resourceDataLength, void *context) {
	if (callbackAlc && callbackPatcher && callbackAlc->orgLayoutLoadCallback) {
		DBGLOG("alc", "layoutLoadCallback %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->updateResource(*callbackPatcher, Resource::Layout, result, resourceData, resourceDataLength);
		DBGLOG("alc", "layoutLoadCallback done %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->orgLayoutLoadCallback(requestTag, result, resourceData, resourceDataLength, context);
	} else {
		SYSLOG("alc", "layout callback arrived at nowhere");
	}
}

void AlcEnabler::platformLoadCallback(uint32_t requestTag, kern_return_t result, const void *resourceData, uint32_t resourceDataLength, void *context) {
	if (callbackAlc && callbackPatcher && callbackAlc->orgPlatformLoadCallback) {
		DBGLOG("alc", "platformLoadCallback %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->updateResource(*callbackPatcher, Resource::Platform, result, resourceData, resourceDataLength);
		DBGLOG("alc", "platformLoadCallback done %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->orgPlatformLoadCallback(requestTag, result, resourceData, resourceDataLength, context);
	} else {
		SYSLOG("alc", "platform callback arrived at nowhere");
	}
}

bool AlcEnabler::isAnalogAudio(IOService *hdaDriver, uint32_t *layout) {
	auto parent = hdaDriver->getParentEntry(gIOServicePlane);
	bool valid = false;
	while (parent) {
		auto name = parent->getName();
		if (name) {
			valid = !strcmp(name, "HDEF");
			if (valid && layout) {
				auto p = OSDynamicCast(OSData, parent->getProperty("layout-id"));
				if (p && p->getLength() == sizeof(uint32_t)) {
					*layout = *static_cast<const uint32_t *>(p->getBytesNoCopy());
					DBGLOG("alc", "isAnalogAudio found %d represented layout", *layout);
				} else {
					SYSLOG("alc", "isAnalogAudio found invalid represented layout in HDEF");
				}
			}
			if (valid || !strcmp(name, "HDAU"))
				break;
		}
		parent = parent->getParentEntry(gIOServicePlane);
	}
	return valid;
}

IOReturn AlcEnabler::performPowerChange(IOService *hdaDriver, uint32_t from, uint32_t to, unsigned int *timer) {
	IOReturn ret = kIOReturnError;
	if (callbackAlc && callbackAlc->orgPerformPowerChange && callbackAlc->orgInitializePinConfig) {
		bool valid = isAnalogAudio(hdaDriver);
		DBGLOG("alc", "performPowerChange %s from %d to %d in from sleep %d hdef %d detect %d",
			safeString(hdaDriver->getName()), from, to, callbackAlc->receivedSleepEvent, valid, callbackAlc->hasHDAConfigDefault);
		ret = callbackAlc->orgPerformPowerChange(hdaDriver, from, to, timer);
		if (valid && callbackAlc->hasHDAConfigDefault == WakeVerbMode::Enable) {
			if (to == ALCAudioDeviceSleep) {
				callbackAlc->receivedSleepEvent = true;
			} else if (callbackAlc->receivedSleepEvent &&
				(to == ALCAudioDeviceIdle || to == ALCAudioDeviceActive)) {
				auto parent = OSDynamicCast(IOService, hdaDriver->getParentEntry(gIOServicePlane));
				if (parent) {
					DBGLOG("alc", "performPowerChange %s forcing wake verbs on %s", safeString(hdaDriver->getName()), safeString(parent->getName()));
					auto forceRet = callbackAlc->orgInitializePinConfig(parent, ADDPR(selfInstance));
					SYSLOG_COND(forceRet != kIOReturnSuccess, "alc", "force config reinitialize returned %08X", forceRet);
				} else {
					SYSLOG("alc", "cannot get hda driver parent for wake");
				}
				callbackAlc->receivedSleepEvent = false;
			}
		}
	} else {
		SYSLOG("alc", "performPowerChange arrived at nowhere");
	}
	return ret;
}

IOReturn AlcEnabler::initializePinConfig(IOService *hdaCodec, IOService *configDevice) {
	IOReturn ret = kIOReturnError;
	if (callbackAlc && callbackAlc->orgInitializePinConfig && configDevice) {
		uint32_t appleLayout = 0;
		bool valid = isAnalogAudio(hdaCodec, &appleLayout);
		DBGLOG("alc", "initializePinConfig %s received hda " PRIKADDR ", config " PRIKADDR " config name %s, detect %d valid %d apple layout %d",
			   safeString(hdaCodec->getName()), CASTKADDR(hdaCodec), CASTKADDR(configDevice), configDevice ? safeString(configDevice->getName()) : "(null config)",
			   callbackAlc->hasHDAConfigDefault, valid, appleLayout);

		if (valid && callbackAlc->hasHDAConfigDefault == WakeVerbMode::Detect) {
			uint32_t analogCodec = 0;
			uint32_t analogLayout = 0;
			for (size_t i = 0, s = callbackAlc->codecs.size(); i < s; i++) {
				if (callbackAlc->controllers[callbackAlc->codecs[i]->controller]->layout > 0) {
					analogCodec = static_cast<uint32_t>(callbackAlc->codecs[i]->vendor) << 16 | callbackAlc->codecs[i]->codec;
					analogLayout = callbackAlc->controllers[callbackAlc->codecs[i]->controller]->layout;
					DBGLOG("alc", "discovered analog codec %08X and layout %d", analogCodec, analogLayout);
					break;
				}
			}

			callbackAlc->hasHDAConfigDefault = WakeVerbMode::Disable;
			auto configList = analogCodec > 0 ? OSDynamicCast(OSArray, configDevice->getProperty("HDAConfigDefault")) : nullptr;
			if (configList) {
				unsigned int total = configList->getCount();
				DBGLOG("alc", "discovered HDAConfigDefault with %d entries", total);

				for (unsigned int i = 0; i < total; i++) {
					auto config = OSDynamicCast(OSDictionary, configList->getObject(i));
					if (config) {
						auto currCodec = OSDynamicCast(OSNumber, config->getObject("CodecID"));
						auto currLayout = OSDynamicCast(OSNumber, config->getObject("LayoutID"));
						if (currCodec && currLayout) {
							if (currCodec->unsigned32BitValue() == analogCodec && currLayout->unsigned32BitValue() == analogLayout) {
								auto configData = OSDynamicCast(OSData, config->getObject("ConfigData"));
								auto wakeConfigData = OSDynamicCast(OSData, config->getObject("WakeConfigData"));
								auto reinit = OSDynamicCast(OSBoolean, config->getObject("WakeVerbReinit"));
								DBGLOG("alc", "current config entry has boot %d, wake %d, reinit %d", configData != nullptr,
									   wakeConfigData != nullptr, reinit ? reinit->getValue() : -1);

								auto newConfig = OSDynamicCast(OSDictionary, config->copyCollection());
								if (newConfig) {
									// Replace the config list with a new list to avoid multiple iterations,
									// and actually fix the LayoutID number we hook in.
									newConfig->setObject("LayoutID", OSNumber::withNumber(appleLayout, 32));
									const OSObject *obj {OSDynamicCast(OSObject, newConfig)};
									configDevice->setProperty("HDAConfigDefault", OSArray::withObjects(&obj, 1));
									if (reinit && reinit->getValue()) {
										if (wakeConfigData) {
											if (configData)
												newConfig->setObject("BootConfigData", configData);
											newConfig->setObject("ConfigData", wakeConfigData);
											newConfig->removeObject("WakeConfigData");
										}
										obj = OSDynamicCast(OSObject, newConfig);
										ADDPR(selfInstance)->setProperty("HDAConfigDefault", OSArray::withObjects(&obj, 1));
										callbackAlc->hasHDAConfigDefault = WakeVerbMode::Enable;
									}
								} else {
									SYSLOG("alc", "failed to copy HDAConfigDefault %d collection", i);
								}

								break;
							}
						} else {
							SYSLOG("alc", "invalid CodecID %d or LayoutID %d at entry %d, pinconfigs are broken",
								currCodec != nullptr, currLayout != nullptr, i);
						}
					} else {
						SYSLOG("alc", "invalid HDAConfigDefault entry at %d, pinconfigs are broken", i);
					}
				}
			} else {
				SYSLOG("alc", "invalid HDAConfigDefault, pinconfigs are broken");
			}
		}
		ret = callbackAlc->orgInitializePinConfig(hdaCodec, configDevice);
	} else {
		SYSLOG("alc", "initializePinConfig arrived at nowhere");
	}
	return ret;
}

OSObject *AlcEnabler::copyClientEntitlement(task_t task, const char *entitlement) {
	if (callbackAlc && callbackAlc->orgCopyClientEntitlement) {
		auto obj = callbackAlc->orgCopyClientEntitlement(task, entitlement);
		if ((!obj || obj != kOSBooleanTrue) && !strcmp(entitlement, "com.apple.private.audio.driver-host"))<commit_msg>Fix ownership issues on codecs with eapd<commit_after>//
//  kern_alc.cpp
//  AppleALC
//
//  Copyright © 2016-2017 vit9696. All rights reserved.
//

#include <Headers/kern_api.hpp>
#include <Headers/plugin_start.hpp>
#include <Library/LegacyIOService.h>

#include <mach/vm_map.h>
#include <IOKit/IORegistryEntry.h>

#include "kern_alc.hpp"
#include "kern_resources.hpp"

// Only used in apple-driven callbacks
static AlcEnabler *callbackAlc = nullptr;
static KernelPatcher *callbackPatcher = nullptr;

bool AlcEnabler::init() {
	LiluAPI::Error error = lilu.onKextLoad(ADDPR(kextList), ADDPR(kextListSize),
	[](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
		callbackAlc = static_cast<AlcEnabler *>(user);
		callbackPatcher = &patcher;
		callbackAlc->processKext(patcher, index, address, size);
	}, this);
	
	if (error != LiluAPI::Error::NoError) {
		SYSLOG("alc", "failed to register onKextLoad method %d", error);
		return false;
	}
	
	if (getKernelVersion() >= KernelVersion::Sierra) {
		char tmp[16];
		// Unlock custom audio engines by disabling Apple private entitlement verification
		if (PE_parse_boot_argn("-alcdhost", tmp, sizeof(tmp))) {
			error = lilu.onPatcherLoad([](void *user, KernelPatcher &patcher) {
				callbackAlc = static_cast<AlcEnabler *>(user);
				callbackPatcher = &patcher;
				callbackAlc->hookEntitlementVerification(patcher);
			}, this);
			if (error != LiluAPI::Error::NoError)
				DBGLOG("alc", "failed to register onPatcherLoad method %d", error);
		}
	}
	
	
	return true;
}

void AlcEnabler::deinit() {
	controllers.deinit();
	codecs.deinit();
}

void AlcEnabler::layoutLoadCallback(uint32_t requestTag, kern_return_t result, const void *resourceData, uint32_t resourceDataLength, void *context) {
	if (callbackAlc && callbackPatcher && callbackAlc->orgLayoutLoadCallback) {
		DBGLOG("alc", "layoutLoadCallback %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->updateResource(*callbackPatcher, Resource::Layout, result, resourceData, resourceDataLength);
		DBGLOG("alc", "layoutLoadCallback done %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->orgLayoutLoadCallback(requestTag, result, resourceData, resourceDataLength, context);
	} else {
		SYSLOG("alc", "layout callback arrived at nowhere");
	}
}

void AlcEnabler::platformLoadCallback(uint32_t requestTag, kern_return_t result, const void *resourceData, uint32_t resourceDataLength, void *context) {
	if (callbackAlc && callbackPatcher && callbackAlc->orgPlatformLoadCallback) {
		DBGLOG("alc", "platformLoadCallback %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->updateResource(*callbackPatcher, Resource::Platform, result, resourceData, resourceDataLength);
		DBGLOG("alc", "platformLoadCallback done %d %d %d %d %d", requestTag, result, resourceData != nullptr, resourceDataLength, context != nullptr);
		callbackAlc->orgPlatformLoadCallback(requestTag, result, resourceData, resourceDataLength, context);
	} else {
		SYSLOG("alc", "platform callback arrived at nowhere");
	}
}

bool AlcEnabler::isAnalogAudio(IOService *hdaDriver, uint32_t *layout) {
	auto parent = hdaDriver->getParentEntry(gIOServicePlane);
	bool valid = false;
	while (parent) {
		auto name = parent->getName();
		if (name) {
			valid = !strcmp(name, "HDEF");
			if (valid && layout) {
				auto p = OSDynamicCast(OSData, parent->getProperty("layout-id"));
				if (p && p->getLength() == sizeof(uint32_t)) {
					*layout = *static_cast<const uint32_t *>(p->getBytesNoCopy());
					DBGLOG("alc", "isAnalogAudio found %d represented layout", *layout);
				} else {
					SYSLOG("alc", "isAnalogAudio found invalid represented layout in HDEF");
				}
			}
			if (valid || !strcmp(name, "HDAU"))
				break;
		}
		parent = parent->getParentEntry(gIOServicePlane);
	}
	return valid;
}

IOReturn AlcEnabler::performPowerChange(IOService *hdaDriver, uint32_t from, uint32_t to, unsigned int *timer) {
	IOReturn ret = kIOReturnError;
	if (callbackAlc && callbackAlc->orgPerformPowerChange && callbackAlc->orgInitializePinConfig) {
		bool valid = isAnalogAudio(hdaDriver);
		DBGLOG("alc", "performPowerChange %s from %d to %d in from sleep %d hdef %d detect %d",
			safeString(hdaDriver->getName()), from, to, callbackAlc->receivedSleepEvent, valid, callbackAlc->hasHDAConfigDefault);
		ret = callbackAlc->orgPerformPowerChange(hdaDriver, from, to, timer);
		if (valid && callbackAlc->hasHDAConfigDefault == WakeVerbMode::Enable) {
			if (to == ALCAudioDeviceSleep) {
				callbackAlc->receivedSleepEvent = true;
			} else if (callbackAlc->receivedSleepEvent &&
				(to == ALCAudioDeviceIdle || to == ALCAudioDeviceActive)) {
				auto parent = OSDynamicCast(IOService, hdaDriver->getParentEntry(gIOServicePlane));
				if (parent) {
					DBGLOG("alc", "performPowerChange %s forcing wake verbs on %s", safeString(hdaDriver->getName()), safeString(parent->getName()));
					auto forceRet = callbackAlc->orgInitializePinConfig(parent, ADDPR(selfInstance));
					SYSLOG_COND(forceRet != kIOReturnSuccess, "alc", "force config reinitialize returned %08X", forceRet);
				} else {
					SYSLOG("alc", "cannot get hda driver parent for wake");
				}
				callbackAlc->receivedSleepEvent = false;
			}
		}
	} else {
		SYSLOG("alc", "performPowerChange arrived at nowhere");
	}
	return ret;
}

IOReturn AlcEnabler::initializePinConfig(IOService *hdaCodec, IOService *configDevice) {
	IOReturn ret = kIOReturnError;
	if (callbackAlc && callbackAlc->orgInitializePinConfig && configDevice) {
		uint32_t appleLayout = 0;
		bool valid = isAnalogAudio(hdaCodec, &appleLayout);
		DBGLOG("alc", "initializePinConfig %s received hda " PRIKADDR ", config " PRIKADDR " config name %s, detect %d valid %d apple layout %d",
			   safeString(hdaCodec->getName()), CASTKADDR(hdaCodec), CASTKADDR(configDevice), configDevice ? safeString(configDevice->getName()) : "(null config)",
			   callbackAlc->hasHDAConfigDefault, valid, appleLayout);

		if (valid && callbackAlc->hasHDAConfigDefault == WakeVerbMode::Detect) {
			uint32_t analogCodec = 0;
			uint32_t analogLayout = 0;
			for (size_t i = 0, s = callbackAlc->codecs.size(); i < s; i++) {
				if (callbackAlc->controllers[callbackAlc->codecs[i]->controller]->layout > 0) {
					analogCodec = static_cast<uint32_t>(callbackAlc->codecs[i]->vendor) << 16 | callbackAlc->codecs[i]->codec;
					analogLayout = callbackAlc->controllers[callbackAlc->codecs[i]->controller]->layout;
					DBGLOG("alc", "discovered analog codec %08X and layout %d", analogCodec, analogLayout);
					break;
				}
			}

			callbackAlc->hasHDAConfigDefault = WakeVerbMode::Disable;
			auto configList = analogCodec > 0 ? OSDynamicCast(OSArray, configDevice->getProperty("HDAConfigDefault")) : nullptr;
			if (configList) {
				unsigned int total = configList->getCount();
				DBGLOG("alc", "discovered HDAConfigDefault with %d entries", total);

				for (unsigned int i = 0; i < total; i++) {
					auto config = OSDynamicCast(OSDictionary, configList->getObject(i));
					if (config) {
						auto currCodec = OSDynamicCast(OSNumber, config->getObject("CodecID"));
						auto currLayout = OSDynamicCast(OSNumber, config->getObject("LayoutID"));
						if (currCodec && currLayout) {
							if (currCodec->unsigned32BitValue() == analogCodec && currLayout->unsigned32BitValue() == analogLayout) {
								auto configData = OSDynamicCast(OSData, config->getObject("ConfigData"));
								auto wakeConfigData = OSDynamicCast(OSData, config->getObject("WakeConfigData"));
								auto reinit = OSDynamicCast(OSBoolean, config->getObject("WakeVerbReinit"));
								DBGLOG("alc", "current config entry has boot %d, wake %d, reinit %d", configData != nullptr,
									   wakeConfigData != nullptr, reinit ? reinit->getValue() : -1);

								auto newConfig = OSDynamicCast(OSDictionary, config->copyCollection());
								if (newConfig) {
									// Replace the config list with a new list to avoid multiple iterations,
									// and actually fix the LayoutID number we hook in.
									newConfig->setObject("LayoutID", OSNumber::withNumber(appleLayout, 32));
									const OSObject *obj {OSDynamicCast(OSObject, newConfig)};
									configDevice->setProperty("HDAConfigDefault", OSArray::withObjects(&obj, 1));
									if (reinit && reinit->getValue()) {
										newConfig = OSDynamicCast(OSDictionary, newConfig->copyCollection());
										if (newConfig) {
											obj = OSDynamicCast(OSObject, newConfig);
											if (wakeConfigData) {
												if (configData)
													newConfig->setObject("BootConfigData", configData);
												newConfig->setObject("ConfigData", wakeConfigData);
												newConfig->removeObject("WakeConfigData");
											}
											ADDPR(selfInstance)->setProperty("HDAConfigDefault", OSArray::withObjects(&obj, 1));
											callbackAlc->hasHDAConfigDefault = WakeVerbMode::Enable;
										} else {
											SYSLOG("alc", "failed to copy new HDAConfigDefault collection");
										}
									}
								} else {
									SYSLOG("alc", "failed to copy HDAConfigDefault %d collection", i);
								}

								break;
							}
						} else {
							SYSLOG("alc", "invalid CodecID %d or LayoutID %d at entry %d, pinconfigs are broken",
								currCodec != nullptr, currLayout != nullptr, i);
						}
					} else {
						SYSLOG("alc", "invalid HDAConfigDefault entry at %d, pinconfigs are broken", i);
					}
				}
			} else {
				SYSLOG("alc", "invalid HDAConfigDefault, pinconfigs are broken");
			}
		}
		ret = callbackAlc->orgInitializePinConfig(hdaCodec, configDevice);
	} else {
		SYSLOG("alc", "initializePinConfig arrived at nowhere");
	}
	return ret;
}

OSObject *AlcEnabler::copyClientEntitlement(task_t task, const char *entitlement) {
	if (callbackAlc && callbackAlc->orgCopyClientEntitlement) {
		auto obj = callbackAlc->orgCopyClientEntitlement(task, entitlement);
		if ((!obj || obj != kOSBooleanTrue) && !strcmp(entitlement, "com.apple.private.audio.driver-host"))
{'fraction_non_alphanumeric': 0.13248502994011976, 'fraction_numerical': 0.006187624750499002, 'mean_word_length': 4.613725490196078, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 168, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1509343', 'n_tokens_mistral': 7443, 'n_tokens_neox': 6310, 'n_words': 1464}