EXPORT extern "C" kern_return_t ADDPR(kern_start)(kmod_info_t *, void *) { LiluAPI::Error error = lilu.requestAccess(); if (error != LiluAPI::Error::NoError) { SYSLOG("init @ failed to call parent %d", error); return KERN_FAILURE; } error = lilu.shouldLoad(ADDPR(config).product, ADDPR(config).disableArg, ADDPR(config).disableArgNum, ADDPR(config).debugArg, ADDPR(config).debugArgNum, ADDPR(config).betaArg, ADDPR(config).betaArgNum, ADDPR(config).minKernel, ADDPR(config).maxKernel, ADDPR(debugEnabled)); if (error == LiluAPI::Error::NoError) { ADDPR(config).pluginStart(); } else { SYSLOG("init @ parent said we should not continue %d", error); } lilu.releaseAccess(); return KERN_SUCCESS; }
IOService *AppleALCAudio::probe(IOService *hdaService, SInt32 *score) { if (!ADDPR(startSuccess)) return nullptr; if (!hdaService) { DBGLOG("audio", "received null digitial audio device"); return nullptr; } uint32_t hdaVen, hdaDev; if (!WIOKit::getOSDataValue(hdaService, "vendor-id", hdaVen) || !WIOKit::getOSDataValue(hdaService, "device-id", hdaDev)) { SYSLOG("audio", "found an unknown device"); return nullptr; } auto hdaPlaneName = hdaService->getName(); DBGLOG("audio", "corrects analog audio for hdef at %s with %04X:%04X", safeString(hdaPlaneName), hdaVen, hdaDev); if (hdaVen != WIOKit::VendorID::Intel) { DBGLOG("audio", "unsupported hdef vendor"); return nullptr; } // HDEF device is always named and is not named as B0D3 or HDAU. bool isAnalog = hdaPlaneName && strcmp(hdaPlaneName, "B0D3") && strcmp(hdaPlaneName, "HDAU"); if (!isAnalog) { DBGLOG("audio", "found digital audio, ignoring."); return nullptr; } // AppleHDAController only recognises HDEF and HDAU. if (!hdaPlaneName || strcmp(hdaPlaneName, "HDEF")) { DBGLOG("audio", "fixing audio plane name to HDEF"); WIOKit::renameDevice(hdaService, "HDEF"); } uint32_t layout = 0; if (PE_parse_boot_argn("alcid", &layout, sizeof(layout))) { DBGLOG("audio", "found layout-id override %d", layout); hdaService->setProperty("layout-id", &layout, sizeof(layout)); } if (!hdaService->getProperty("built-in")) { DBGLOG("audio", "fixing built-in in hdef"); uint8_t builtBytes[] { 0x00 }; hdaService->setProperty("built-in", builtBytes, sizeof(builtBytes)); } else { DBGLOG("audio", "found existing built-in in hdef"); } // These seem to fix AppleHDA warnings, perhaps research them later. // They are probably related to the current volume of the boot bell sound. if (!hdaService->getProperty("MaximumBootBeepVolume")) { DBGLOG("audio", "fixing MaximumBootBeepVolume in hdef"); uint8_t bootBeepBytes[] { 0xEE }; hdaService->setProperty("MaximumBootBeepVolume", bootBeepBytes, sizeof(bootBeepBytes)); } if (!hdaService->getProperty("MaximumBootBeepVolumeAlt")) { DBGLOG("audio", "fixing MaximumBootBeepVolumeAlt in hdef"); uint8_t bootBeepBytes[] { 0xEE }; hdaService->setProperty("MaximumBootBeepVolumeAlt", bootBeepBytes, sizeof(bootBeepBytes)); } if (!hdaService->getProperty("PinConfigurations")) { DBGLOG("audio", "fixing PinConfigurations in hdef"); uint8_t pinBytes[] { 0x00 }; hdaService->setProperty("PinConfigurations", pinBytes, sizeof(pinBytes)); } return nullptr; }
bool Configuration::getBootArguments() { if (readArguments) return !isDisabled; isDisabled = false; char tmp[16]; isDisabled |= PE_parse_boot_argn(bootargOff, tmp, sizeof(tmp)); if (!PE_parse_boot_argn(bootargForce, tmp, sizeof(tmp))) { isDisabled |= PE_parse_boot_argn("-s", tmp, sizeof(tmp)); isDisabled |= PE_parse_boot_argn("-x", tmp, sizeof(tmp)); if (!KernelPatcher::compatibleKernel(minKernel, maxKernel)) { if (!PE_parse_boot_argn(bootargBeta, tmp, sizeof(tmp))) { SYSLOG("config @ automatically disabling on an unsupported operating system"); isDisabled = true; } else if (!isDisabled) { SYSLOG("config @ force enabling on an unsupported operating system due to beta flag"); } } } else if (!isDisabled) { SYSLOG("config @ force enabling due to force flag"); } ADDPR(debugEnabled) = PE_parse_boot_argn(bootargDebug, tmp, sizeof(tmp)); allowDecompress = !PE_parse_boot_argn(bootargLowMem, tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("rp0", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("rp", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("container-dmg", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("root-dmg", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("auth-root-dmg", tmp, sizeof(tmp)); preferSlowMode = getKernelVersion() <= KernelVersion::Mavericks || installOrRecovery; if (PE_parse_boot_argn(bootargSlow, tmp, sizeof(tmp))) { preferSlowMode = true; } else if (PE_parse_boot_argn(bootargFast, tmp, sizeof(tmp))) { preferSlowMode = false; } if (!preferSlowMode && getKernelVersion() <= KernelVersion::Mavericks) { // Since vm_shared_region_map_file interface is a little different if (!isDisabled) SYSLOG("config @ enforcing -liluslow on Mavericks and lower"); preferSlowMode = true; } if (!preferSlowMode && installOrRecovery) { // Since vdyld shared cache is not available if (!isDisabled) SYSLOG("config @ enforcing -liluslow in installer or recovery"); preferSlowMode = true; } readArguments = true; DBGLOG("config @ boot arguments disabled %d, debug %d, slow %d, decompress %d", isDisabled, ADDPR(debugEnabled), preferSlowMode, allowDecompress); if (isDisabled) { SYSLOG("init @ found a disabling argument or no arguments, exiting"); } else { // Decide on booter if (!preferSlowMode) { policyOps.mpo_cred_check_label_update_execve = reinterpret_cast<mpo_cred_check_label_update_execve_t *>(policyCredCheckLabelUpdateExecve); } else { policyOps.mpo_mount_check_remount = policyCheckRemount; } } return !isDisabled; }
void UserPatcher::patchSharedCache(vm_map_t taskPort, uint32_t slide, cpu_type_t cpu, bool applyChanges) { // Save the slide for restoration if (applyChanges && !sharedCacheSlideStored) { storedSharedCacheSlide = slide; sharedCacheSlideStored = true; } for (size_t i = 0, sz = lookupStorage.size(); i < sz; i++) { auto &storageEntry = lookupStorage[i]; auto &mod = storageEntry->mod; for (size_t j = 0, rsz = storageEntry->refs.size(); j < rsz; j++) { auto &ref = storageEntry->refs[j]; auto &patch = storageEntry->mod->patches[ref->i]; size_t offNum = ref->segOffs.size(); vm_address_t modStart = 0; vm_address_t modEnd = 0; if (patch.segment >= FileSegment::SegmentsTextStart && patch.segment <= FileSegment::SegmentsTextEnd) { modStart = mod->startTEXT; modEnd = mod->endTEXT; } else if (patch.segment >= FileSegment::SegmentsDataStart && patch.segment <= FileSegment::SegmentsDataEnd) { modStart = mod->startDATA; modEnd = mod->endDATA; } if (modStart && modEnd && offNum && patch.cpu == cpu) { DBGLOG("user @ patch for %s in %lX %lX\n", mod->path, modStart, modEnd); auto tmp = Buffer::create<uint8_t>(patch.size); if (tmp) { for (size_t k = 0; k < offNum; k++) { auto place = modStart+ref->segOffs[k]+slide; auto r = orgVmMapReadUser(taskPort, place, tmp, patch.size); if (!r) { bool comparison = !memcmp(tmp, applyChanges? patch.find : patch.replace, patch.size); DBGLOG("user @ %d/%d found %X %X %X %X", applyChanges, comparison, tmp[0], tmp[1], tmp[2], tmp[3]); if (comparison) { if (vm_protect(taskPort, (place & -PAGE_SIZE), PAGE_SIZE, FALSE, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) == KERN_SUCCESS) { DBGLOG("user @ obtained write permssions\n"); r = orgVmMapWriteUser(taskPort, applyChanges ? patch.replace : patch.find, place, patch.size); DBGLOG("user @ patching %llX -> res %d", place, r); if (vm_protect(taskPort, (place & -PAGE_SIZE), PAGE_SIZE, FALSE, VM_PROT_READ|VM_PROT_EXECUTE) == KERN_SUCCESS) { DBGLOG("user @ restored write permssions\n"); } } else { SYSLOG("user @ failed to obtain write permissions for patching"); } } else if (ADDPR(debugEnabled)) { for (size_t i = 0; i < patch.size; i++) { auto v = (applyChanges? patch.find : patch.replace)[i]; if (tmp[i] != v) { DBGLOG("user @ miss at %zu: %0.2X vs %0.2X", i, tmp[i], v); break; } } } } DBGLOG("user @ done reading patches for %llX", ref->segOffs[k]); } Buffer::deleter(tmp); } } } } }