diff --git a/ATH9KFixup.xcodeproj/project.pbxproj b/ATH9KFixup.xcodeproj/project.pbxproj index 03ecd89..fe62890 100644 --- a/ATH9KFixup.xcodeproj/project.pbxproj +++ b/ATH9KFixup.xcodeproj/project.pbxproj @@ -287,6 +287,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -328,6 +329,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; SDKROOT = macosx; }; name = Release; @@ -356,7 +358,7 @@ MODULE_NAME = com.chunnann.ATH9KFixup; MODULE_START = "$(PRODUCT_NAME)_kern_start"; MODULE_STOP = "$(PRODUCT_NAME)_kern_stop"; - MODULE_VERSION = 1.1.0; + MODULE_VERSION = 1.2.6; OTHER_CFLAGS = ( "-mmmx", "-msse", @@ -400,7 +402,7 @@ MODULE_NAME = com.chunnann.ATH9KFixup; MODULE_START = "$(PRODUCT_NAME)_kern_start"; MODULE_STOP = "$(PRODUCT_NAME)_kern_stop"; - MODULE_VERSION = 1.1.0; + MODULE_VERSION = 1.2.6; OTHER_CFLAGS = ( "-mmmx", "-msse", diff --git a/ATH9KFixup.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ATH9KFixup.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ATH9KFixup.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ATH9KFixup.xcodeproj/project.xcworkspace/xcuserdata/nick.xcuserdatad/UserInterfaceState.xcuserstate b/ATH9KFixup.xcodeproj/project.xcworkspace/xcuserdata/nick.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..dc238da Binary files /dev/null and b/ATH9KFixup.xcodeproj/project.xcworkspace/xcuserdata/nick.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ATH9KFixup.xcodeproj/xcuserdata/nick.xcuserdatad/xcschemes/ATH9KFixup.xcscheme b/ATH9KFixup.xcodeproj/xcuserdata/nick.xcuserdatad/xcschemes/ATH9KFixup.xcscheme new file mode 100644 index 0000000..75f0850 --- /dev/null +++ b/ATH9KFixup.xcodeproj/xcuserdata/nick.xcuserdatad/xcschemes/ATH9KFixup.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ATH9KFixup.xcodeproj/xcuserdata/nick.xcuserdatad/xcschemes/xcschememanagement.plist b/ATH9KFixup.xcodeproj/xcuserdata/nick.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..7424cef --- /dev/null +++ b/ATH9KFixup.xcodeproj/xcuserdata/nick.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + ATH9KFixup.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 1C748C261C21952C0024EED2 + + primary + + + + + diff --git a/ATH9KFixup/Info.plist b/ATH9KFixup/Info.plist index 3a94af2..f2cad96 100644 --- a/ATH9KFixup/Info.plist +++ b/ATH9KFixup/Info.plist @@ -37,13 +37,13 @@ NSHumanReadableCopyright - Copyright © 2017 chunnann. All rights reserved. + Copyright © 2017 chunnann, black.dragon74. All rights reserved. OSBundleCompatibleVersion 1.0 OSBundleLibraries as.vit9696.Lilu - 1.1.6 + 1.2.6 com.apple.kpi.bsd 12.0.0 com.apple.kpi.dsep diff --git a/ATH9KFixup/kern_ath9k.cpp b/ATH9KFixup/kern_ath9k.cpp index 9d75912..d8bf312 100644 --- a/ATH9KFixup/kern_ath9k.cpp +++ b/ATH9KFixup/kern_ath9k.cpp @@ -21,12 +21,15 @@ static const char *kextAirPortAtheros40[] { }; static KernelPatcher::KextInfo kextList[] { - { "com.apple.driver.AirPort.Atheros40", kextAirPortAtheros40, 1, true, {}, KernelPatcher::KextInfo::Unloaded } + { "com.apple.driver.AirPort.Atheros40", kextAirPortAtheros40, 1, {true,true}, {}, KernelPatcher::KextInfo::Unloaded } }; static size_t kextListSize {1}; bool ATH9K::init() { + // So that user can identify successful kext injection. + SYSLOG("ATH9KFixup", "Kext loaded. Patching will start now.\n"); + LiluAPI::Error error = lilu.onKextLoad(kextList, kextListSize, [](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) { ATH9K *ath9k = static_cast(user); @@ -34,7 +37,7 @@ bool ATH9K::init() { }, this); if (error != LiluAPI::Error::NoError) { - SYSLOG("ath9k @ failed to register onPatcherLoad method %d", error); + SYSLOG("ath9k", "failed to register onPatcherLoad method %d", error); return false; } @@ -49,7 +52,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t for (size_t i = 0; i < kextListSize; i++) { if (kextList[i].loadIndex == index) { if (!(progressState & ProcessingState::AirPortAtheros40Patched) && !strcmp(kextList[i].id, "com.apple.driver.AirPort.Atheros40")) { - DBGLOG("ath9k @ found com.apple.driver.AirPort.Atheros40"); + DBGLOG("ath9k", "found com.apple.driver.AirPort.Atheros40"); if (getKernelVersion() == KernelVersion::Mavericks){ const uint8_t find1[] = {0x66, 0x89, 0x83, 0x20, 0x02, 0x00, 0x00}; @@ -60,7 +63,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch1, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched 10.9.x start"); + DBGLOG("ath9k", "patched 10.9.x start"); const uint8_t find2[] = {0x66, 0x83, 0xFA, 0x30}; const uint8_t replace2[] = {0x66, 0x83, 0xFA, 0x00}; @@ -70,7 +73,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch2, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched ___ath_attach"); + DBGLOG("ath9k", "patched ___ath_attach"); } else if (getKernelVersion() == KernelVersion::Yosemite){ const uint8_t find1[] = {0x66, 0x89, 0x83, 0x48, 0x02, 0x00, 0x00}; @@ -81,7 +84,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch1, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched 10.10.x start"); + DBGLOG("ath9k", "patched 10.10.x start"); const uint8_t find2[] = {0x41, 0x0F, 0xB7, 0xFE, 0x83, 0xFF, 0x30}; const uint8_t replace2[] = {0x41, 0x0F, 0xB7, 0xFE, 0x83, 0xFF, 0x00}; @@ -91,7 +94,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch2, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched ___ath_attach"); + DBGLOG("ath9k" ,"patched ___ath_attach"); } else if (getKernelVersion() == KernelVersion::ElCapitan){ const uint8_t find1[] = {0x66, 0x89, 0x83, 0x10, 0x04, 0x00, 0x00}; @@ -102,7 +105,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch1, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched 10.11.x start"); + DBGLOG("ath9k" ,"patched 10.11.x start"); const uint8_t find2[] = {0x0F, 0xB7, 0xF8, 0x83, 0xFF, 0x30}; const uint8_t replace2[] = {0x0F, 0xB7, 0xF8, 0x83, 0xFF, 0x00}; @@ -112,7 +115,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch2, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched ___ath_attach"); + DBGLOG("ath9k", "patched ___ath_attach"); } else if (getKernelVersion() == KernelVersion::Sierra){ const uint8_t find1[] = {0x66, 0x89, 0x83, 0x38, 0x04, 0x00, 0x00}; @@ -123,7 +126,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch1, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched 10.12.x start"); + DBGLOG("ath9k", "patched 10.12.x start"); const uint8_t find2[] = {0x0F, 0xB7, 0xF8, 0x83, 0xFF, 0x30}; const uint8_t replace2[] = {0x0F, 0xB7, 0xF8, 0x83, 0xFF, 0x00}; @@ -133,7 +136,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch2, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched ___ath_attach"); + DBGLOG("ath9k", "patched ___ath_attach"); } else if (getKernelVersion() == KernelVersion::HighSierra){ const uint8_t find1[] = {0x66, 0x89, 0x83, 0x38, 0x04, 0x00, 0x00}; @@ -144,7 +147,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch1, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched 10.13.x start"); + DBGLOG("ath9k", " patched 10.13.x start"); const uint8_t find2[] = {0x41, 0x0F, 0xB7, 0xFD, 0x83, 0xFF, 0x30}; const uint8_t replace2[] = {0x41, 0x0F, 0xB7, 0xFD, 0x83, 0xFF, 0x00}; @@ -154,18 +157,41 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch2, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched ___ath_attach"); + DBGLOG("ath9k", " patched ___ath_attach"); + } + + // Patch is same as macOS High Sierra (as of now), Just adding patcher support for Mojave + else if (getKernelVersion() == KernelVersion::Mojave){ + const uint8_t find1[] = {0x66, 0x89, 0x83, 0x38, 0x04, 0x00, 0x00}; + const uint8_t replace1[] = {0xC6, 0x83, 0x38, 0x04, 0x00, 0x00, 0x30}; + KextPatch kext_patch1 { + {&kextList[i], find1, replace1, sizeof(find1), 1}, + KernelVersion::Mojave, KernelVersion::Mojave + }; + applyPatches(patcher, index, &kext_patch1, 1); + progressState |= ProcessingState::AirPortAtheros40Patched; + DBGLOG("ath9k", "patched 10.14.x start"); + + const uint8_t find2[] = {0x41, 0x0F, 0xB7, 0xFD, 0x83, 0xFF, 0x30}; + const uint8_t replace2[] = {0x41, 0x0F, 0xB7, 0xFD, 0x83, 0xFF, 0x00}; + KextPatch kext_patch2 { + {&kextList[i], find2, replace2, sizeof(find2), 1}, + KernelVersion::Mojave, KernelVersion::Mojave + }; + applyPatches(patcher, index, &kext_patch2, 1); + progressState |= ProcessingState::AirPortAtheros40Patched; + DBGLOG("ath9k", "patched ___ath_attach"); } const uint8_t find3[] = {0xC1, 0xE9, 0x0C, 0x81, 0xE1, 0xC0, 0xFF, 0x0F, 0x00}; const uint8_t replace3[] = {0xC1, 0xE9, 0x0C, 0x90, 0xB9, 0xC0, 0x01, 0x00, 0x00}; KextPatch kext_patch3 { {&kextList[i], find3, replace3, sizeof(find3), 4}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch3, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300ReadRevisions"); + DBGLOG("ath9k", " patched _ar9300ReadRevisions"); const uint8_t find4[] = {0xC1, 0xE8, 0x0C, 0x25, 0xC0, 0xFF, 0x0F, 0x00}; const uint8_t replace4[] = {0xC1, 0xE8, 0x0C, 0xB8, 0xC0, 0x01, 0x00, 0x00}; @@ -175,67 +201,67 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch4, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300ReadRevisions #1"); + DBGLOG("ath9k", " patched _ar9300ReadRevisions #1"); const uint8_t find5[] = {0xC1, 0xE9, 0x08, 0x83, 0xE1, 0x0F}; const uint8_t replace5[] = {0x90, 0xB9, 0x02, 0x00, 0x00, 0x00}; KextPatch kext_patch5 { {&kextList[i], find5, replace5, sizeof(find5), 5}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch5, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300ReadRevisions #2"); + DBGLOG("ath9k", " patched _ar9300ReadRevisions #2"); const uint8_t find6[] = {0xC1, 0xE8, 0x08, 0x83, 0xE0, 0x0F}; const uint8_t replace6[] = {0x90, 0xB8, 0x02, 0x00, 0x00, 0x00}; KextPatch kext_patch6 { {&kextList[i], find6, replace6, sizeof(find6), 3}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch6, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300ReadRevisions #3"); + DBGLOG("ath9k", " patched _ar9300ReadRevisions #3"); const uint8_t find7[] = {0x0F, 0xB6, 0x87, 0x00, 0xB2, 0x00, 0x00, 0x83, 0xE0, 0x0F}; const uint8_t replace7[] = {0x0F, 0xB6, 0x87, 0x00, 0xB2, 0x00, 0x00, 0x90, 0x31, 0xC0}; KextPatch kext_patch7 { {&kextList[i], find7, replace7, sizeof(find7), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch7, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300RxGainIndexGet"); + DBGLOG("ath9k", " patched _ar9300RxGainIndexGet"); const uint8_t find8[] = {0x0F, 0xB6, 0x87, 0x00, 0xB2, 0x00, 0x00, 0xC1, 0xE8, 0x04}; const uint8_t replace8[] = {0x0F, 0xB6, 0x87, 0x00, 0xB2, 0x00, 0x00, 0x90, 0x31, 0xC0}; KextPatch kext_patch8 { {&kextList[i], find8, replace8, sizeof(find8), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch8, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300TxGainIndexGet"); + DBGLOG("ath9k", " patched _ar9300TxGainIndexGet"); const uint8_t find9[] = {0x66, 0x89, 0x83, 0x16, 0x09, 0x00, 0x00}; const uint8_t replace9[] = {0xC6, 0x83, 0x16, 0x09, 0x00, 0x00, 0x00}; KextPatch kext_patch9 { {&kextList[i], find9, replace9, sizeof(find9), 4}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch9, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300FillCapabilityInfo"); + DBGLOG("ath9k", " patched _ar9300FillCapabilityInfo"); const uint8_t find10[] = {0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00}; const uint8_t replace10[] = {0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00}; KextPatch kext_patch10 { {&kextList[i], find10, replace10, sizeof(find10), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch10, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300FillCapabilityInfo #2"); + DBGLOG("ath9k", " patched _ar9300FillCapabilityInfo #2"); char tmp[16]; if (PE_parse_boot_argn("-ath9485", tmp, sizeof(tmp))) { @@ -243,11 +269,11 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t const uint8_t replace[] = {0x39, 0x34, 0x38, 0x35}; KextPatch kext_patch { {&kextList[i], find, replace, sizeof(find), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched AR9485"); + DBGLOG("ath9k", " patched AR9485"); if (getKernelVersion() == KernelVersion::Mavericks){ const uint8_t find11[] = {0xFF, 0x03, 0x00, 0x00, 0x4C, 0x89, 0xFF, 0x4C, 0x89, 0xF6, 0x89, 0xDA, 0xB9, 0xFF, 0x03, 0x00, 0x00}; @@ -258,7 +284,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch11, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300EepromRestoreInternal"); + DBGLOG("ath9k", " patched _ar9300EepromRestoreInternal"); const uint8_t find12[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xD0}; const uint8_t replace12[] = {0xBA, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xD0}; @@ -268,7 +294,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0xFF, 0x13}; const uint8_t replace13[] = {0xBA, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x13}; @@ -278,7 +304,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); } else { const uint8_t find11[] = {0xFF, 0x03, 0x00, 0x00, 0xB9, 0xFF, 0x03, 0x00, 0x00}; @@ -289,7 +315,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch11, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300EepromRestoreInternal"); + DBGLOG("ath9k", " patched _ar9300EepromRestoreInternal"); const uint8_t find12[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0xFF, 0xD0}; const uint8_t replace12[] = {0xBA, 0x01, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0xFF, 0xD0}; @@ -299,7 +325,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0x41, 0xFF, 0x55, 0x00}; const uint8_t replace13[] = {0xBA, 0x01, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0x41, 0xFF, 0x55, 0x00}; @@ -309,173 +335,173 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); } /* const uint8_t find12[] = {0xA2, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x00}; const uint8_t replace12[] = {0xA2, 0x00, 0x00, 0xBA, 0x01, 0x00, 0x00, 0x00}; KextPatch kext_patch12 { {&kextList[i], find12, replace12, sizeof(find12), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0x83, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x00}; const uint8_t replace13[] = {0x83, 0x00, 0x00, 0xBA, 0x01, 0x00, 0x00, 0x00}; KextPatch kext_patch13 { {&kextList[i], find13, replace13, sizeof(find13), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); */ const uint8_t find14[] = {0xBE, 0x88, 0x62, 0x01, 0x00}; const uint8_t replace14[] = {0xBE, 0x84, 0x62, 0x01, 0x00}; KextPatch kext_patch14 { {&kextList[i], find14, replace14, sizeof(find14), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch14, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300 #1"); + DBGLOG("ath9k", " patched _ar9300 #1"); const uint8_t find15[] = {0xBE, 0x90, 0x62, 0x01, 0x00}; const uint8_t replace15[] = {0xBE, 0x8C, 0x62, 0x01, 0x00}; KextPatch kext_patch15 { {&kextList[i], find15, replace15, sizeof(find15), 4}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch15, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300 #2"); + DBGLOG("ath9k", " patched _ar9300 #2"); KextPatch kext_patch51 { {&kextList[i], _ar9300_osprey_2p0_mac_core, _ar9485_osprey_2p0_mac_core, sizeof(_ar9300_osprey_2p0_mac_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch51, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_mac_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_mac_core"); KextPatch kext_patch52 { {&kextList[i], _ar9300_osprey_2p0_mac_postamble, _ar9485_osprey_2p0_mac_postamble, sizeof(_ar9300_osprey_2p0_mac_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch52, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_mac_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_mac_postamble"); KextPatch kext_patch53 { {&kextList[i], _ar9300_osprey_2p0_baseband_core, _ar9485_osprey_2p0_baseband_core, sizeof(_ar9300_osprey_2p0_baseband_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch53, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_baseband_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_baseband_core"); KextPatch kext_patch54 { {&kextList[i], _ar9300_osprey_2p0_baseband_postamble, _ar9485_osprey_2p0_baseband_postamble, sizeof(_ar9300_osprey_2p0_baseband_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch54, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_baseband_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_baseband_postamble"); KextPatch kext_patch55 { {&kextList[i], _ar9300_osprey_2p0_radio_core, _ar9485_osprey_2p0_radio_core, sizeof(_ar9300_osprey_2p0_radio_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch55, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_radio_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_radio_core"); KextPatch kext_patch56 { {&kextList[i], _ar9300_osprey_2p0_radio_postamble, _ar9485_osprey_2p0_radio_postamble, sizeof(_ar9300_osprey_2p0_radio_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch56, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_radio_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_radio_postamble"); KextPatch kext_patch57 { {&kextList[i], _ar9300_osprey_2p0_soc_preamble, _ar9485_osprey_2p0_soc_preamble, sizeof(_ar9300_osprey_2p0_soc_preamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch57, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_soc_preamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_soc_preamble"); KextPatch kext_patch58 { {&kextList[i], _ar9300_osprey_2p0_soc_postamble, _ar9485_osprey_2p0_soc_postamble, sizeof(_ar9300_osprey_2p0_soc_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch58, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_soc_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_soc_postamble"); KextPatch kext_patch59 { {&kextList[i], _ar9300Common_rx_gain_table_osprey_2p0, _ar9485Common_rx_gain_table_osprey_2p0, sizeof(_ar9300Common_rx_gain_table_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch59, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Common_rx_gain_table_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Common_rx_gain_table_osprey_2p0"); KextPatch kext_patch60 { {&kextList[i], _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0, _ar9485Modes_lowest_ob_db_tx_gain_table_osprey_2p0, sizeof(_ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch60, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0"); KextPatch kext_patch61 { {&kextList[i], _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0, _ar9485PciePhy_pll_on_clkreq_disable_L1_osprey_2p0, sizeof(_ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch61, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0"); KextPatch kext_patch62 { {&kextList[i], _ar9300PciePhy_clkreq_enable_L1_osprey_2p0, _ar9485PciePhy_clkreq_enable_L1_osprey_2p0, sizeof(_ar9300PciePhy_clkreq_enable_L1_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch62, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300PciePhy_clkreq_enable_L1_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300PciePhy_clkreq_enable_L1_osprey_2p0"); KextPatch kext_patch63 { {&kextList[i], _ar9300Modes_fast_clock_osprey_2p0, _ar9485Modes_fast_clock_osprey_2p0, sizeof(_ar9300Modes_fast_clock_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch63, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Modes_fast_clock_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Modes_fast_clock_osprey_2p0"); } else if (PE_parse_boot_argn("-ath9565", tmp, sizeof(tmp))) { const uint8_t find[] = {0x39, 0x33, 0x38, 0x30}; const uint8_t replace[] = {0x39, 0x35, 0x36, 0x35}; KextPatch kext_patch { {&kextList[i], find, replace, sizeof(find), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched AR9565"); + DBGLOG("ath9k", " patched AR9565"); const uint8_t find11[] = {0x8D, 0x90, 0x00, 0x04, 0x00, 0x00}; const uint8_t replace11[] = {0x8D, 0x90, 0x00, 0x04, 0x08, 0x00}; KextPatch kext_patch11 { {&kextList[i], find11, replace11, sizeof(find11), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch11, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300SetRxFilter"); + DBGLOG("ath9k", " patched _ar9300SetRxFilter"); if (getKernelVersion() == KernelVersion::Mavericks){ const uint8_t find12[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xD0}; @@ -486,7 +512,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0xFF, 0x13}; const uint8_t replace13[] = {0xBA, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x13}; @@ -496,7 +522,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); } else { const uint8_t find12[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0xFF, 0xD0}; @@ -507,7 +533,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0x41, 0xFF, 0x55, 0x00}; const uint8_t replace13[] = {0xBA, 0x01, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0x41, 0xFF, 0x55, 0x00}; @@ -517,173 +543,173 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); } /* const uint8_t find12[] = {0xA2, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x00}; const uint8_t replace12[] = {0xA2, 0x00, 0x00, 0xBA, 0x01, 0x00, 0x00, 0x00}; KextPatch kext_patch12 { {&kextList[i], find12, replace12, sizeof(find12), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0x83, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x00}; const uint8_t replace13[] = {0x83, 0x00, 0x00, 0xBA, 0x01, 0x00, 0x00, 0x00}; KextPatch kext_patch13 { {&kextList[i], find13, replace13, sizeof(find13), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); */ const uint8_t find14[] = {0xBE, 0x88, 0x62, 0x01, 0x00}; const uint8_t replace14[] = {0xBE, 0x8C, 0x62, 0x01, 0x00}; KextPatch kext_patch14 { {&kextList[i], find14, replace14, sizeof(find14), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch14, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300 #1"); + DBGLOG("ath9k", " patched _ar9300 #1"); const uint8_t find15[] = {0xBE, 0x90, 0x62, 0x01, 0x00}; const uint8_t replace15[] = {0xBE, 0x94, 0x62, 0x01, 0x00}; KextPatch kext_patch15 { {&kextList[i], find15, replace15, sizeof(find15), 4}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch15, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300 #2"); + DBGLOG("ath9k", " patched _ar9300 #2"); KextPatch kext_patch51 { {&kextList[i], _ar9300_osprey_2p0_mac_core, _ar9565_osprey_2p0_mac_core, sizeof(_ar9300_osprey_2p0_mac_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch51, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_mac_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_mac_core"); KextPatch kext_patch52 { {&kextList[i], _ar9300_osprey_2p0_mac_postamble, _ar9565_osprey_2p0_mac_postamble, sizeof(_ar9300_osprey_2p0_mac_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch52, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_mac_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_mac_postamble"); KextPatch kext_patch53 { {&kextList[i], _ar9300_osprey_2p0_baseband_core, _ar9565_osprey_2p0_baseband_core, sizeof(_ar9300_osprey_2p0_baseband_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch53, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_baseband_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_baseband_core"); KextPatch kext_patch54 { {&kextList[i], _ar9300_osprey_2p0_baseband_postamble, _ar9565_osprey_2p0_baseband_postamble, sizeof(_ar9300_osprey_2p0_baseband_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch54, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_baseband_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_baseband_postamble"); KextPatch kext_patch55 { {&kextList[i], _ar9300_osprey_2p0_radio_core, _ar9565_osprey_2p0_radio_core, sizeof(_ar9300_osprey_2p0_radio_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch55, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_radio_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_radio_core"); KextPatch kext_patch56 { {&kextList[i], _ar9300_osprey_2p0_radio_postamble, _ar9565_osprey_2p0_radio_postamble, sizeof(_ar9300_osprey_2p0_radio_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch56, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_radio_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_radio_postamble"); KextPatch kext_patch57 { {&kextList[i], _ar9300_osprey_2p0_soc_preamble, _ar9565_osprey_2p0_soc_preamble, sizeof(_ar9300_osprey_2p0_soc_preamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch57, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_soc_preamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_soc_preamble"); KextPatch kext_patch58 { {&kextList[i], _ar9300_osprey_2p0_soc_postamble, _ar9565_osprey_2p0_soc_postamble, sizeof(_ar9300_osprey_2p0_soc_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch58, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_soc_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_soc_postamble"); KextPatch kext_patch59 { {&kextList[i], _ar9300Common_rx_gain_table_osprey_2p0, _ar9565Common_rx_gain_table_osprey_2p0, sizeof(_ar9300Common_rx_gain_table_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch59, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Common_rx_gain_table_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Common_rx_gain_table_osprey_2p0"); KextPatch kext_patch60 { {&kextList[i], _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0, _ar9565Modes_lowest_ob_db_tx_gain_table_osprey_2p0, sizeof(_ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch60, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0"); KextPatch kext_patch61 { {&kextList[i], _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0, _ar9565PciePhy_pll_on_clkreq_disable_L1_osprey_2p0, sizeof(_ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch61, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0"); KextPatch kext_patch62 { {&kextList[i], _ar9300PciePhy_clkreq_enable_L1_osprey_2p0, _ar9565PciePhy_clkreq_enable_L1_osprey_2p0, sizeof(_ar9300PciePhy_clkreq_enable_L1_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch62, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300PciePhy_clkreq_enable_L1_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300PciePhy_clkreq_enable_L1_osprey_2p0"); KextPatch kext_patch63 { {&kextList[i], _ar9300Modes_fast_clock_osprey_2p0, _ar9565Modes_fast_clock_osprey_2p0, sizeof(_ar9300Modes_fast_clock_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch63, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Modes_fast_clock_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Modes_fast_clock_osprey_2p0"); } else { const uint8_t find[] = {0x39, 0x33, 0x38, 0x30}; const uint8_t replace[] = {0x39, 0x34, 0x36, 0x58}; KextPatch kext_patch { {&kextList[i], find, replace, sizeof(find), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched AR946X"); + DBGLOG("ath9k", " patched AR946X"); const uint8_t find11[] = {0x8D, 0x90, 0x00, 0x04, 0x00, 0x00}; const uint8_t replace11[] = {0x8D, 0x90, 0x00, 0x04, 0x08, 0x00}; KextPatch kext_patch11 { {&kextList[i], find11, replace11, sizeof(find11), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch11, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300SetRxFilter"); + DBGLOG("ath9k", " patched _ar9300SetRxFilter"); if (getKernelVersion() == KernelVersion::Mavericks){ const uint8_t find12[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xD0}; @@ -694,7 +720,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0xFF, 0x13}; const uint8_t replace13[] = {0xBA, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x13}; @@ -704,7 +730,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); } else { const uint8_t find12[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0xFF, 0xD0}; @@ -715,7 +741,7 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0xBA, 0x07, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0x41, 0xFF, 0x55, 0x00}; const uint8_t replace13[] = {0xBA, 0x03, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xE7, 0x41, 0xFF, 0x55, 0x00}; @@ -725,152 +751,152 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); } /* const uint8_t find12[] = {0xA2, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x00}; const uint8_t replace12[] = {0xA2, 0x00, 0x00, 0xBA, 0x03, 0x00, 0x00, 0x00}; KextPatch kext_patch12 { {&kextList[i], find12, replace12, sizeof(find12), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch12, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset"); + DBGLOG("ath9k", " patched _ar9300Reset"); const uint8_t find13[] = {0x83, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x00}; const uint8_t replace13[] = {0x83, 0x00, 0x00, 0xBA, 0x03, 0x00, 0x00, 0x00}; KextPatch kext_patch13 { {&kextList[i], find13, replace13, sizeof(find13), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch13, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Reset #2"); + DBGLOG("ath9k", " patched _ar9300Reset #2"); */ const uint8_t find14[] = {0xBE, 0x88, 0x62, 0x01, 0x00}; const uint8_t replace14[] = {0xBE, 0x8C, 0x62, 0x01, 0x00}; KextPatch kext_patch14 { {&kextList[i], find14, replace14, sizeof(find14), 2}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch14, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300 #1"); + DBGLOG("ath9k", " patched _ar9300 #1"); const uint8_t find15[] = {0xBE, 0x90, 0x62, 0x01, 0x00}; const uint8_t replace15[] = {0xBE, 0x94, 0x62, 0x01, 0x00}; KextPatch kext_patch15 { {&kextList[i], find15, replace15, sizeof(find15), 4}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch15, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300 #2"); + DBGLOG("ath9k", " patched _ar9300 #2"); KextPatch kext_patch51 { {&kextList[i], _ar9300_osprey_2p0_mac_core, _ar946x_osprey_2p0_mac_core, sizeof(_ar9300_osprey_2p0_mac_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch51, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_mac_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_mac_core"); KextPatch kext_patch52 { {&kextList[i], _ar9300_osprey_2p0_mac_postamble, _ar946x_osprey_2p0_mac_postamble, sizeof(_ar9300_osprey_2p0_mac_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch52, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_mac_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_mac_postamble"); KextPatch kext_patch53 { {&kextList[i], _ar9300_osprey_2p0_baseband_core, _ar946x_osprey_2p0_baseband_core, sizeof(_ar9300_osprey_2p0_baseband_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch53, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_baseband_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_baseband_core"); KextPatch kext_patch54 { {&kextList[i], _ar9300_osprey_2p0_baseband_postamble, _ar946x_osprey_2p0_baseband_postamble, sizeof(_ar9300_osprey_2p0_baseband_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch54, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_baseband_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_baseband_postamble"); KextPatch kext_patch55 { {&kextList[i], _ar9300_osprey_2p0_radio_core, _ar946x_osprey_2p0_radio_core, sizeof(_ar9300_osprey_2p0_radio_core), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch55, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_radio_core"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_radio_core"); KextPatch kext_patch56 { {&kextList[i], _ar9300_osprey_2p0_radio_postamble, _ar946x_osprey_2p0_radio_postamble, sizeof(_ar9300_osprey_2p0_radio_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch56, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_radio_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_radio_postamble"); KextPatch kext_patch57 { {&kextList[i], _ar9300_osprey_2p0_soc_preamble, _ar946x_osprey_2p0_soc_preamble, sizeof(_ar9300_osprey_2p0_soc_preamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch57, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_soc_preamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_soc_preamble"); KextPatch kext_patch58 { {&kextList[i], _ar9300_osprey_2p0_soc_postamble, _ar946x_osprey_2p0_soc_postamble, sizeof(_ar9300_osprey_2p0_soc_postamble), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch58, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300_osprey_2p0_soc_postamble"); + DBGLOG("ath9k", " patched _ar9300_osprey_2p0_soc_postamble"); KextPatch kext_patch59 { {&kextList[i], _ar9300Common_rx_gain_table_osprey_2p0, _ar946xCommon_rx_gain_table_osprey_2p0, sizeof(_ar9300Common_rx_gain_table_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch59, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Common_rx_gain_table_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Common_rx_gain_table_osprey_2p0"); KextPatch kext_patch60 { {&kextList[i], _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0, _ar946xModes_lowest_ob_db_tx_gain_table_osprey_2p0, sizeof(_ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch60, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Modes_lowest_ob_db_tx_gain_table_osprey_2p0"); KextPatch kext_patch61 { {&kextList[i], _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0, _ar946xPciePhy_pll_on_clkreq_disable_L1_osprey_2p0, sizeof(_ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch61, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300PciePhy_pll_on_clkreq_disable_L1_osprey_2p0"); KextPatch kext_patch62 { {&kextList[i], _ar9300PciePhy_clkreq_enable_L1_osprey_2p0, _ar946xPciePhy_clkreq_enable_L1_osprey_2p0, sizeof(_ar9300PciePhy_clkreq_enable_L1_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch62, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300PciePhy_clkreq_enable_L1_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300PciePhy_clkreq_enable_L1_osprey_2p0"); KextPatch kext_patch63 { {&kextList[i], _ar9300Modes_fast_clock_osprey_2p0, _ar946xModes_fast_clock_osprey_2p0, sizeof(_ar9300Modes_fast_clock_osprey_2p0), 1}, - KernelVersion::Mavericks, KernelVersion::HighSierra + KernelVersion::Mavericks, KernelVersion::Mojave }; applyPatches(patcher, index, &kext_patch63, 1); progressState |= ProcessingState::AirPortAtheros40Patched; - DBGLOG("ath9k @ patched _ar9300Modes_fast_clock_osprey_2p0"); + DBGLOG("ath9k", " patched _ar9300Modes_fast_clock_osprey_2p0"); } } } @@ -882,12 +908,12 @@ void ATH9K::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t } void ATH9K::applyPatches(KernelPatcher &patcher, size_t index, const KextPatch *patches, size_t patchNum) { - DBGLOG("ath9k @ applying patches for %zu kext", index); + DBGLOG("ath9k", " applying patches for %zu kext", index); for (size_t p = 0; p < patchNum; p++) { auto &patch = patches[p]; if (patch.patch.kext->loadIndex == index) { if (patcher.compatibleKernel(patch.minKernel, patch.maxKernel)) { - DBGLOG("ath9k @ applying %zu patch for %zu kext", p, index); + DBGLOG("ath9k", " applying %zu patch for %zu kext", p, index); patcher.applyLookupPatch(&patch.patch); // Do not really care for the errors for now patcher.clearError(); diff --git a/ATH9KFixup/kern_start.cpp b/ATH9KFixup/kern_start.cpp index 9480791..3027c3b 100644 --- a/ATH9KFixup/kern_start.cpp +++ b/ATH9KFixup/kern_start.cpp @@ -29,14 +29,15 @@ static const char *bootargBeta[] { PluginConfiguration ADDPR(config) { xStringify(PRODUCT_NAME), parseModuleVersion(xStringify(MODULE_VERSION)), + LiluAPI::AllowNormal | LiluAPI::AllowInstallerRecovery, bootargOff, - sizeof(bootargOff)/sizeof(bootargOff[0]), + arrsize(bootargOff), bootargDebug, - sizeof(bootargDebug)/sizeof(bootargDebug[0]), + arrsize(bootargDebug), bootargBeta, - sizeof(bootargBeta)/sizeof(bootargBeta[0]), + arrsize(bootargBeta), KernelVersion::Mavericks, - KernelVersion::HighSierra, + KernelVersion::Mojave, []() { ath9k.init(); } diff --git a/ATH9KInjector.kext/Contents/Info.plist b/ATH9KInjector.kext/Contents/Info.plist index 1cb83ca..85c0a38 100644 --- a/ATH9KInjector.kext/Contents/Info.plist +++ b/ATH9KInjector.kext/Contents/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType KEXT CFBundleShortVersionString - 1.0.0 + 1.2.6 CFBundleSignature ???? CFBundleSupportedPlatforms @@ -23,7 +23,7 @@ MacOSX CFBundleVersion - 1.0.0 + 1.2.6 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild @@ -61,6 +61,6 @@ NSHumanReadableCopyright - Copyright © 2017 chunnann. All rights reserved. + Copyright © 2017 chunnann, black.dragon74. All rights reserved. diff --git a/Changelog.md b/Changelog.md index 010c868..7520fab 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,12 @@ ATH9KFixup Changelog ==================== +#### v1.2.6 +- Added Lilu 1.2.6 compatibility +- Added macOS Mojave support (untested) +- Updated injector kext to be in sync with plugin version. + +#### v1.2.0 +- Added Lilu 1.2.0 compatibility #### v1.1.0 - Added High Sierra compatibility diff --git a/Lilu.kext/Contents/Info.plist b/Lilu.kext/Contents/Info.plist index d26b6a3..91296fd 100644 --- a/Lilu.kext/Contents/Info.plist +++ b/Lilu.kext/Contents/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 16G29 + 17D102 CFBundleDevelopmentRegion en CFBundleExecutable @@ -17,7 +17,7 @@ CFBundlePackageType KEXT CFBundleShortVersionString - 1.1.7 + 1.2.6 CFBundleSignature ???? CFBundleSupportedPlatforms @@ -25,21 +25,21 @@ MacOSX CFBundleVersion - 1.1.7 + 1.2.6 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 8E3004b + 9F2000 DTPlatformVersion GM DTSDKBuild - 16E185 + 17E189 DTSDKName - macosx10.12 + macosx10.13 DTXcode - 0833 + 0941 DTXcodeBuild - 8E3004b + 9F2000 IOKitPersonalities as.vit9696.Lilu @@ -59,7 +59,7 @@ NSHumanReadableCopyright Copyright © 2016-2017 vit9696. All rights reserved. OSBundleCompatibleVersion - 1.1.0 + 1.2.0 OSBundleLibraries com.apple.kpi.bsd diff --git a/Lilu.kext/Contents/MacOS/Lilu b/Lilu.kext/Contents/MacOS/Lilu old mode 100644 new mode 100755 index 0327c4b..5bf4ab2 Binary files a/Lilu.kext/Contents/MacOS/Lilu and b/Lilu.kext/Contents/MacOS/Lilu differ diff --git a/Lilu.kext/Contents/Resources/Headers/Guid/LiluVariables.h b/Lilu.kext/Contents/Resources/Headers/Guid/LiluVariables.h new file mode 100644 index 0000000..4d23b4e --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/Guid/LiluVariables.h @@ -0,0 +1,38 @@ +/** @file + Lilu specific GUIDs for UEFI Variable Storage, version 1.0. + +Copyright (c) 2018, vit9696. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// 2660DD78-81D2-419D-8138-7B1F363F79A6 +// This GUID is specifically used for normal variable access by Lilu kernel extension and its plugins. +// +#define LILU_NORMAL_VARIABLE_GUID \ + { 0x2660DD78, 0x81D2, 0x419D, { 0x81, 0x38, 0x7B, 0x1F, 0x36, 0x3F, 0x79, 0xA6 } } + +// +// E09B9297-7928-4440-9AAB-D1F8536FBF0A +// This GUID is specifically used for reading variables by Lilu kernel extension and its plugins. +// Any writes to this GUID should be prohibited via EFI_RUNTIME_SERVICES after EXIT_BOOT_SERVICES. +// The expected return code on variable write is EFI_SECURITY_VIOLATION. +// +#define LILU_READ_ONLY_VARIABLE_GUID \ + { 0xE09B9297, 0x7928, 0x4440, { 0x9A, 0xAB, 0xD1, 0xF8, 0x53, 0x6F, 0xBF, 0x0A } } + +// +// F0B9AF8F-2222-4840-8A37-ECF7CC8C12E1 +// This GUID is specifically used for reading variables by Lilu and plugins. +// Any reads from this GUID should be prohibited via EFI_RUNTIME_SERVICES after EXIT_BOOT_SERVICES. +// The expected return code on variable read is EFI_SECURITY_VIOLATION. +// +#define LILU_WRITE_ONLY_VARIABLE_GUID \ + { 0xF0B9AF8F, 0x2222, 0x4840, { 0x8A, 0x37, 0xEC, 0xF7, 0xCC, 0x8C, 0x12, 0xE1 } } diff --git a/Lilu.kext/Contents/Resources/Headers/capstone/arm64.h b/Lilu.kext/Contents/Resources/Headers/capstone/arm64.h index 8814709..87504ba 100644 --- a/Lilu.kext/Contents/Resources/Headers/capstone/arm64.h +++ b/Lilu.kext/Contents/Resources/Headers/capstone/arm64.h @@ -659,8 +659,8 @@ typedef enum arm64_reg { //> alias registers - ARM64_REG_IP1 = ARM64_REG_X16, - ARM64_REG_IP0 = ARM64_REG_X17, + ARM64_REG_IP0 = ARM64_REG_X16, + ARM64_REG_IP1 = ARM64_REG_X17, ARM64_REG_FP = ARM64_REG_X29, ARM64_REG_LR = ARM64_REG_X30, } arm64_reg; diff --git a/Lilu.kext/Contents/Resources/Headers/kern_api.hpp b/Lilu.kext/Contents/Resources/Headers/kern_api.hpp index a7919cf..15711b1 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_api.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_api.hpp @@ -23,12 +23,12 @@ class LiluAPI { * Initialise lilu api */ void init(); - + /** * Deinitialise lilu api */ void deinit(); - + /** * Errors returned by functions */ @@ -39,15 +39,16 @@ class LiluAPI { UnsupportedFeature, IncompatibleOS, Disabled, - TooLate + TooLate, + Offline }; - + /** * Minimal API version that guarantees forward ABI compatibility * Present due to lack of OSBundleCompatibleVersion at kext injection */ - static constexpr size_t CompatibilityVersion {parseModuleVersion("1.1.0")}; - + static constexpr size_t CompatibilityVersion {parseModuleVersion("1.2.0")}; + /** * Obtains api access by holding a lock, which is required when accessing out of the main context * @@ -57,19 +58,43 @@ class LiluAPI { * @return Error::NoError on success */ EXPORT Error requestAccess(size_t version=CompatibilityVersion, bool check=false); - + /** * Releases api lock * * @return Error::NoError on success */ EXPORT Error releaseAccess(); - + + /** + * You are supposed declare that your plugins work in at least one of these modes + * It is assumed that single user mode is equal to normal, because it is generally + * used to continue the load of a complete OS, and by default Lilu itself ignores it. + */ + enum RunningMode : uint32_t { + RunningNormal = 1, + AllowNormal = RunningNormal, + RunningInstallerRecovery = 2, + AllowInstallerRecovery = RunningInstallerRecovery, + RunningSafeMode = 4, + AllowSafeMode = RunningSafeMode + }; + + /** + * Obtain current run mode similarly to requirements + * + * @return run mode mask (RunningMode) + */ + inline uint32_t getRunMode() { + return currentRunMode; + } + /** * Decides whether you are eligible to continue * * @param product product name * @param version product version + * @param runmode bitmask of allowed enviornments * @param disableArg pointer to disabling boot arguments array * @param disableArgNum number of disabling boot arguments * @param debugArg pointer to debug boot arguments array @@ -82,8 +107,8 @@ class LiluAPI { * * @return Error::NoError on success */ - EXPORT Error shouldLoad(const char *product, size_t version, const char **disableArg, size_t disableArgNum, const char **debugArg, size_t debugArgNum, const char **betaArg, size_t betaArgNum, KernelVersion min, KernelVersion max, bool &printDebug); - + EXPORT Error shouldLoad(const char *product, size_t version, uint32_t runmode, const char **disableArg, size_t disableArgNum, const char **debugArg, size_t debugArgNum, const char **betaArg, size_t betaArgNum, KernelVersion min, KernelVersion max, bool &printDebug); + /** * Kernel patcher loaded callback * @@ -91,7 +116,7 @@ class LiluAPI { * @param patcher kernel patcher instance */ using t_patcherLoaded = void (*)(void *user, KernelPatcher &patcher); - + /** * Registers custom provided callbacks for later invocation on kernel patcher initialisation * @@ -101,7 +126,22 @@ class LiluAPI { * @return Error::NoError on success */ EXPORT Error onPatcherLoad(t_patcherLoaded callback, void *user=nullptr); - + + /** + * Registers custom provided callbacks for later invocation on kernel patcher initialisation + * Enforced version, which panics on registration failure (assuming your code cannot continue otherwise) + * + * @param callback your callback function + * @param user your pointer that will be passed to the callback function + * + * @return Error::NoError on success + */ + inline void onPatcherLoadForce(t_patcherLoaded callback, void *user=nullptr) { + auto err = onPatcherLoad(callback, user); + if (err != Error::NoError) + PANIC("api", "onPatcherLoad failed with code %d", err); + } + /** * Kext loaded callback * Note that you will get notified of all the requested kexts for speed reasons @@ -113,21 +153,53 @@ class LiluAPI { * @param size loaded memory size */ using t_kextLoaded = void (*)(void *user, KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size); - + /** * Registers custom provided callbacks for later invocation on kext load * * @param infos your kext list (make sure to point to const memory) * @param num number of provided kext entries - * @param callback your callback function + * @param callback your callback function (optional) + * @param user your pointer that will be passed to the callback function (optional) + * + * @return Error::NoError on success + */ + EXPORT Error onKextLoad(KernelPatcher::KextInfo *infos, size_t num=1, t_kextLoaded callback=nullptr, void *user=nullptr); + + /** + * Registers custom provided callbacks for later invocation on kext load + * Enforced version, which panics on registration failure (assuming your code cannot continue otherwise) + * + * @param infos your kext list (make sure to point to const memory) + * @param num number of provided kext entries + * @param callback your callback function (optional) + * @param user your pointer that will be passed to the callback function (optional) + * + * @return Error::NoError on success + */ + inline void onKextLoadForce(KernelPatcher::KextInfo *infos, size_t num=1, t_kextLoaded callback=nullptr, void *user=nullptr) { + auto err = onKextLoad(infos, num, callback, user); + if (err != Error::NoError) + PANIC("api", "onKextLoad failed with code %d", err); + } + + /** + * Registers custom provided callbacks for later invocation on binary load + * + * @param infos your binary list (make sure to point to const memory) + * @param num number of provided binary entries + * @param callback your callback function (could be null) * @param user your pointer that will be passed to the callback function + * @param mods optional mod list (make sure to point to const memory) + * @param modnum number of provided mod entries * * @return Error::NoError on success */ - EXPORT Error onKextLoad(KernelPatcher::KextInfo *infos, size_t num, t_kextLoaded callback, void *user=nullptr); - + EXPORT Error onProcLoad(UserPatcher::ProcInfo *infos, size_t num=1, UserPatcher::t_BinaryLoaded callback=nullptr, void *user=nullptr, UserPatcher::BinaryModInfo *mods=nullptr, size_t modnum=0); + /** * Registers custom provided callbacks for later invocation on binary load + * Enforced version, which panics on registration failure (assuming your code cannot continue otherwise) * * @param infos your binary list (make sure to point to const memory) * @param num number of provided binary entries @@ -138,7 +210,47 @@ class LiluAPI { * * @return Error::NoError on success */ - EXPORT Error onProcLoad(UserPatcher::ProcInfo *infos, size_t num, UserPatcher::t_BinaryLoaded callback, void *user=nullptr, UserPatcher::BinaryModInfo *mods=nullptr, size_t modnum=0); + inline void onProcLoadForce(UserPatcher::ProcInfo *infos, size_t num=1, UserPatcher::t_BinaryLoaded callback=nullptr, void *user=nullptr, UserPatcher::BinaryModInfo *mods=nullptr, size_t modnum=0) { + auto err = onProcLoad(infos, num, callback, user, mods, modnum); + if (err != Error::NoError) + PANIC("api", "onProcLoad failed with code %d", err); + } + + /** + * Kext loaded callback + * Note that you will get notified of all the requested kexts for speed reasons + * + * @param user user provided pointer at registering + * @param task task + * @param entitlement loaded kinfo id + * @param original original entitlement value + */ + using t_entitlementRequested = void (*)(void *user, task_t task, const char *entitlement, OSObject *&original); + + /** + * Registers custom provided callbacks for later invocation on entitlement registration + * + * @param callback your callback function + * @param user your pointer that will be passed to the callback function + * + * @return Error::NoError on success + */ + EXPORT Error onEntitlementRequest(t_entitlementRequested callback, void *user=nullptr); + + /** + * Registers custom provided callbacks for later invocation on entitlement registration + * Enforced version, which panics on registration failure (assuming your code cannot continue otherwise) + * + * @param callback your callback function + * @param user your pointer that will be passed to the callback function + * + * @return Error::NoError on success + */ + inline void onEntitlementRequestForce(t_entitlementRequested callback, void *user=nullptr) { + auto err = onEntitlementRequest(callback, user); + if (err != Error::NoError) + PANIC("api", "onEntitlementRequest failed with code %d", err); + } /** * Processes all the registered patcher load callbacks @@ -157,14 +269,14 @@ class LiluAPI { * @param reloadable kinfo could be unloaded */ void processKextLoadCallbacks(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size, bool reloadable); - + /** * Processes all the registered user patcher load callbacks * * @param patcher user patcher instance */ void processUserLoadCallbacks(UserPatcher &patcher); - + /** * Processes all the registered binary load callbacks * @@ -174,7 +286,7 @@ class LiluAPI { * @param len path length excluding null terminator */ void processBinaryLoadCallbacks(UserPatcher &patcher, vm_map_t map, const char *path, size_t len); - + /** * Activates patchers * @@ -182,60 +294,85 @@ class LiluAPI { * @param upatcher user patcher instance */ void activate(KernelPatcher &kpatcher, UserPatcher &upatcher); - + private: - + /** * Api lock */ IOLock *access {nullptr}; - + + /** + * Defines current running modes + */ + uint32_t currentRunMode {}; + /** * No longer accept any requests */ bool apiRequestsOver {false}; - + /** * Stores call function and user pointer */ template using stored_pair = ppair; - + /** * Stores multiple callbacks */ template using stored_vector = evector *, stored_pair::deleter>; - + /** * List of patcher callbacks */ stored_vector patcherLoadedCallbacks; - + /** * List of kext callbacks */ stored_vector kextLoadedCallbacks; - + /** * List of binary callbacks */ stored_vector binaryLoadedCallbacks; - + + /** + * List of entitlement callbacks + */ + stored_vector entitlementRequestedCallbacks; + /** * List of processed kexts */ stored_vector storedKexts; - + /** * List of processed procs */ evector storedProcs; - + /** * List of processed binary mods */ evector storedBinaryMods; + + /** + * Copy client entitlement type (see IOUserClient) + */ + using t_copyClientEntitlement = OSObject *(*)(task_t, const char *); + + /** + * Hooked entitlement copying method + */ + static OSObject *copyClientEntitlement(task_t task, const char *entitlement); + + /** + * Trampoline for original entitlement copying method + */ + t_copyClientEntitlement orgCopyClientEntitlement {nullptr}; }; EXPORT extern LiluAPI lilu; diff --git a/Lilu.kext/Contents/Resources/Headers/kern_compat.hpp b/Lilu.kext/Contents/Resources/Headers/kern_compat.hpp new file mode 100644 index 0000000..7c0d49b --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_compat.hpp @@ -0,0 +1,78 @@ +// +// kern_compat.hpp +// Lilu +// +// Copyright © 2016-2017 vit9696. All rights reserved. +// + +#ifndef kern_compat_hpp +#define kern_compat_hpp + +#include +//Actually do not include to catch real errors +//#include +#include + +// Please do not use memcpy and similar functions, since they compile +// to macros unsupported by any other system with 10.13 SDK unless +// Availability.h header is included. +#define lilu_os_memcpy(...) (memcpy)(__VA_ARGS__) +#define lilu_os_memmove(...) (memmove)(__VA_ARGS__) +#define lilu_os_strncpy(...) (strncpy)(__VA_ARGS__) +#define lilu_os_strncat(...) (strncat)(__VA_ARGS__) +#define lilu_os_strlcat(...) (strlcat)(__VA_ARGS__) +#define lilu_os_strlcpy(...) (strlcpy)(__VA_ARGS__) +#define lilu_os_strcat(...) (strcat)(__VA_ARGS__) +#define lilu_os_bcopy(...) (bcopy)(__VA_ARGS__) + +// Additionally disallow the use of the original functions +#ifndef LILU_DISABLE_MEMFUNC_REDEFINE + +#ifdef memcpy +#undef memcpy +#define memcpy(...) _Pragma("GCC error \"Avoid memcpy due to 10.13 SDK bugs!\"") +#endif + +#ifdef memmove +#undef memmove +#define memmove(...) _Pragma("GCC error \"Avoid memmove due to 10.13 SDK bugs!\"") +#endif + +#ifdef strncpy +#undef strncpy +#define strncpy(...) _Pragma("GCC error \"Avoid strncpy due to 10.13 SDK bugs!\"") +#endif + +#ifdef strncat +#undef strncat +#define strncat(...) _Pragma("GCC error \"Avoid strncat due to 10.13 SDK bugs!\"") +#endif + +#ifdef strlcat +#undef strlcat +#define strlcat(...) _Pragma("GCC error \"Avoid strlcat due to 10.13 SDK bugs!\"") +#endif + +#ifdef strlcpy +#undef strlcpy +#define strlcpy(...) _Pragma("GCC error \"Avoid strlcpy due to 10.13 SDK bugs!\"") +#endif + +#ifdef strcat +#undef strcat +#define strcat(...) _Pragma("GCC error \"Avoid strcat due to 10.13 SDK bugs!\"") +#endif + +#ifdef bcopy +#undef bcopy +#define bcopy(...) _Pragma("GCC error \"Avoid bcopy due to 10.13 SDK bugs!\"") +#endif + +#endif /* LILU_DISABLE_MEMFUNC_REDEFINE */ + +// This may not be nice but will protect users from changes in KernInfo strcture. +#ifndef LILU_DISABLE_BRACE_WARNINGS +#pragma clang diagnostic error "-Wmissing-braces" +#endif + +#endif /* kern_compat_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_compression.hpp b/Lilu.kext/Contents/Resources/Headers/kern_compression.hpp index a656914..4e4fba9 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_compression.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_compression.hpp @@ -15,38 +15,56 @@ #include #include -/** - * CompressedHeader constants - */ -static constexpr uint32_t CompressedMagic {0x706D6F63}; //comp -static constexpr uint32_t CompressionLZVN {0x6E767A6C}; //lzvn -static constexpr uint32_t CompressionLZSS {0x73737A6C}; //lzss - -/** - * CompressedHeader structure - */ -struct CompressedHeader { - uint32_t magic; - uint32_t compression; - uint32_t hash; // adler32 - uint32_t decompressed; - uint32_t compressed; - uint32_t version; - uint32_t padding[90]; -}; - -/** - * Typed decompressing function - * - * @param compression compression type - * @param dstlen decompression buffer size - * @param src compressed data - * @param srclen compressed data size - * - * @return decompressed buffer - */ -EXPORT uint8_t *decompressData(uint32_t compression, uint32_t dstlen, uint8_t *src, uint32_t srclen); +namespace Compression { + /** + * Compression constants and modes + */ + static constexpr uint32_t Magic {0x706D6F63}; //comp + static constexpr uint32_t ModeLZVN {0x6E767A6C}; //lzvn + static constexpr uint32_t ModeLZSS {0x73737A6C}; //lzss + + /** + * Compressed header structure + */ + struct Header { + uint32_t magic; + uint32_t compression; + uint32_t hash; // adler32 + uint32_t decompressed; + uint32_t compressed; + uint32_t version; + uint32_t padding[90]; + }; + + /** + * Typed decompressing function (currently for lzvn and lzss) + * + * @param compression compression type + * @param dstlen decompression buffer size + * @param src compressed data + * @param srclen compressed data size + * @param buffer preallocated buffer to use + * + * @return decompressed buffer (must be freeded by Buffer::deleter if not preallocated) + */ + EXPORT uint8_t *decompress(uint32_t compression, uint32_t dstlen, const uint8_t *src, uint32_t srclen, uint8_t *buffer=nullptr); + + /** + * Typed compressing function (currently for lzss) + * + * @param compression compression type + * @param dstlen maximum compression buffer size + * @param src uncompressed data + * @param srclen uncompressed data size + * @param buffer preallocated buffer to use + * + * @return compressed buffer with its actual size in dstlen (must be freeded by Buffer::deleter if not preallocated) + */ + EXPORT uint8_t *compress(uint32_t compression, uint32_t &dstlen, const uint8_t *src, uint32_t srclen, uint8_t *buffer=nullptr); + +} + #endif /* LILU_COMPRESSION_SUPPORT */ #endif /* kern_compression_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_config.hpp b/Lilu.kext/Contents/Resources/Headers/kern_config.hpp index fe4116a..d5cdbf2 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_config.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_config.hpp @@ -8,11 +8,25 @@ #ifndef kern_config_hpp #define kern_config_hpp -// As for now claim to support all the features +/** + * Enable kext patching support + */ #define LILU_KEXTPATCH_SUPPORT 1 + +/** + * Enable compression and decompression support + */ #define LILU_COMPRESSION_SUPPORT 1 -// Use these in plugins in Xcode Project Preprocessor Macros section +/** + * Enable advanced disassembly API based on capstone + */ +// #define LILU_ADVANCED_DISASSEMBLY 1 + +/** + * Specify custom initialisation code + * Use these in plugins in Xcode Project Preprocessor Macros section. + */ // #define LILU_CUSTOM_IOKIT_INIT 1 // #define LILU_CUSTOM_KMOD_INIT 1 diff --git a/Lilu.kext/Contents/Resources/Headers/kern_cpu.hpp b/Lilu.kext/Contents/Resources/Headers/kern_cpu.hpp new file mode 100644 index 0000000..31e4d70 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_cpu.hpp @@ -0,0 +1,409 @@ +// +// kern_cpu.hpp +// Lilu +// +// Copyright © 2018 vit9696. All rights reserved. +// + +#ifndef kern_cpu_h +#define kern_cpu_h + +#include +#include +#include + +#include + +/** + * XNU CPU-related exports missing from headers + */ +extern "C" { + int cpu_number(void); + void mp_rendezvous_no_intrs(void (*action_func)(void *), void *arg); +}; + +namespace CPUInfo { + /** + * Keep this in sync to XNU MAX_CPUS from osfmk/i386/mp.h + */ + static constexpr size_t MaxCpus {64}; + + /** + * Contents of CPUID(1) eax register contents describing model version + */ + struct CpuVersion { + uint32_t stepping : 4; + uint32_t model : 4; + uint32_t family : 4; + uint32_t type : 2; + uint32_t reserved1 : 2; + uint32_t extendedModel : 4; + uint32_t extendedFamily : 8; + uint32_t reserved2 : 4; + }; + + static_assert(sizeof(CpuVersion) == sizeof(uint32_t), "CpuVersion size mismatch!"); + + /** + * Intel CPU models as returned by CPUID + * The list is synchronised and updated with XNU source code (osfmk/i386/cpuid.h). + * Names are altered to avoid conflicts just in case. + * Last update: xnu-4570.41.2 + * Some details could be found on http://instlatx64.atw.hu and https://en.wikichip.org/wiki/64-bit_architecture#x86 + */ + enum CpuModel { + CPU_MODEL_UNKNOWN = 0x00, + CPU_MODEL_PENRYN = 0x17, + CPU_MODEL_NEHALEM = 0x1A, + CPU_MODEL_FIELDS = 0x1E, /* Lynnfield, Clarksfield */ + CPU_MODEL_DALES = 0x1F, /* Havendale, Auburndale */ + CPU_MODEL_NEHALEM_EX = 0x2E, + CPU_MODEL_DALES_32NM = 0x25, /* Clarkdale, Arrandale */ + CPU_MODEL_WESTMERE = 0x2C, /* Gulftown, Westmere-EP/-WS */ + CPU_MODEL_WESTMERE_EX = 0x2F, + CPU_MODEL_SANDYBRIDGE = 0x2A, + CPU_MODEL_JAKETOWN = 0x2D, + CPU_MODEL_IVYBRIDGE = 0x3A, + CPU_MODEL_IVYBRIDGE_EP = 0x3E, + CPU_MODEL_CRYSTALWELL = 0x46, + CPU_MODEL_HASWELL = 0x3C, + CPU_MODEL_HASWELL_EP = 0x3F, + CPU_MODEL_HASWELL_ULT = 0x45, + CPU_MODEL_BROADWELL = 0x3D, + CPU_MODEL_BROADWELL_ULX = 0x3D, + CPU_MODEL_BROADWELL_ULT = 0x3D, + CPU_MODEL_BRYSTALWELL = 0x47, + CPU_MODEL_SKYLAKE = 0x4E, + CPU_MODEL_SKYLAKE_ULT = 0x4E, + CPU_MODEL_SKYLAKE_ULX = 0x4E, + CPU_MODEL_SKYLAKE_DT = 0x5E, + CPU_MODEL_SKYLAKE_W = 0x55, + CPU_MODEL_KABYLAKE = 0x8E, + CPU_MODEL_KABYLAKE_ULT = 0x8E, + CPU_MODEL_KABYLAKE_ULX = 0x8E, + CPU_MODEL_KABYLAKE_DT = 0x9E, + CPU_MODEL_COFFEELAKE = 0x9E, + CPU_MODEL_COFFEELAKE_ULT = 0x9E, + CPU_MODEL_COFFEELAKE_ULX = 0x9E, + CPU_MODEL_COFFEELAKE_DT = 0x9E, + CPU_MODEL_CANNONLAKE = 0x66, + CPU_MODEL_ICELAKE = 0x7E + }; + + /** + * Known CPU vendors + */ + enum class CpuVendor { + Unknown, + AMD, + Intel + /* Add more processors here if needed */ + }; + + /** + * Intel CPU generations (starting from 0) + */ + enum class CpuGeneration { + Unknown, + Penryn, + Nehalem, + Westmere, + SandyBridge, + IvyBridge, + Haswell, + Broadwell, + Skylake, + KabyLake, + CoffeeLake, + CannonLake, + IceLake, + MaxGeneration + }; + + /* Responses identification request with %eax 0 */ + /* AMD: "AuthenticAMD" */ + static constexpr uint32_t signature_AMD_ebx = 0x68747541; + static constexpr uint32_t signature_AMD_edx = 0x69746e65; + static constexpr uint32_t signature_AMD_ecx = 0x444d4163; + /* CENTAUR: "CentaurHauls" */ + static constexpr uint32_t signature_CENTAUR_ebx = 0x746e6543; + static constexpr uint32_t signature_CENTAUR_edx = 0x48727561; + static constexpr uint32_t signature_CENTAUR_ecx = 0x736c7561; + /* CYRIX: "CyrixInstead" */ + static constexpr uint32_t signature_CYRIX_ebx = 0x69727943; + static constexpr uint32_t signature_CYRIX_edx = 0x736e4978; + static constexpr uint32_t signature_CYRIX_ecx = 0x64616574; + /* INTEL: "GenuineIntel" */ + static constexpr uint32_t signature_INTEL_ebx = 0x756e6547; + static constexpr uint32_t signature_INTEL_edx = 0x49656e69; + static constexpr uint32_t signature_INTEL_ecx = 0x6c65746e; + /* TM1: "TransmetaCPU" */ + static constexpr uint32_t signature_TM1_ebx = 0x6e617254; + static constexpr uint32_t signature_TM1_edx = 0x74656d73; + static constexpr uint32_t signature_TM1_ecx = 0x55504361; + /* TM2: "GenuineTMx86" */ + static constexpr uint32_t signature_TM2_ebx = 0x756e6547; + static constexpr uint32_t signature_TM2_edx = 0x54656e69; + static constexpr uint32_t signature_TM2_ecx = 0x3638784d; + /* NSC: "Geode by NSC" */ + static constexpr uint32_t signature_NSC_ebx = 0x646f6547; + static constexpr uint32_t signature_NSC_edx = 0x43534e20; + static constexpr uint32_t signature_NSC_ecx = 0x79622065; + /* NEXGEN: "NexGenDriven" */ + static constexpr uint32_t signature_NEXGEN_ebx = 0x4778654e; + static constexpr uint32_t signature_NEXGEN_edx = 0x72446e65; + static constexpr uint32_t signature_NEXGEN_ecx = 0x6e657669; + /* RISE: "RiseRiseRise" */ + static constexpr uint32_t signature_RISE_ebx = 0x65736952; + static constexpr uint32_t signature_RISE_edx = 0x65736952; + static constexpr uint32_t signature_RISE_ecx = 0x65736952; + /* SIS: "SiS SiS SiS " */ + static constexpr uint32_t signature_SIS_ebx = 0x20536953; + static constexpr uint32_t signature_SIS_edx = 0x20536953; + static constexpr uint32_t signature_SIS_ecx = 0x20536953; + /* UMC: "UMC UMC UMC " */ + static constexpr uint32_t signature_UMC_ebx = 0x20434d55; + static constexpr uint32_t signature_UMC_edx = 0x20434d55; + static constexpr uint32_t signature_UMC_ecx = 0x20434d55; + /* VIA: "VIA VIA VIA " */ + static constexpr uint32_t signature_VIA_ebx = 0x20414956; + static constexpr uint32_t signature_VIA_edx = 0x20414956; + static constexpr uint32_t signature_VIA_ecx = 0x20414956; + /* VORTEX: "Vortex86 SoC" */ + static constexpr uint32_t signature_VORTEX_ebx = 0x74726f56; + static constexpr uint32_t signature_VORTEX_edx = 0x36387865; + static constexpr uint32_t signature_VORTEX_ecx = 0x436f5320; + + /* Features in %ecx for leaf 1 */ + static constexpr uint32_t bit_SSE3 = 0x00000001; + static constexpr uint32_t bit_PCLMULQDQ = 0x00000002; + static constexpr uint32_t bit_DTES64 = 0x00000004; + static constexpr uint32_t bit_MONITOR = 0x00000008; + static constexpr uint32_t bit_DSCPL = 0x00000010; + static constexpr uint32_t bit_VMX = 0x00000020; + static constexpr uint32_t bit_SMX = 0x00000040; + static constexpr uint32_t bit_EIST = 0x00000080; + static constexpr uint32_t bit_TM2 = 0x00000100; + static constexpr uint32_t bit_SSSE3 = 0x00000200; + static constexpr uint32_t bit_CNXTID = 0x00000400; + static constexpr uint32_t bit_FMA = 0x00001000; + static constexpr uint32_t bit_CMPXCHG16B = 0x00002000; + static constexpr uint32_t bit_xTPR = 0x00004000; + static constexpr uint32_t bit_PDCM = 0x00008000; + static constexpr uint32_t bit_PCID = 0x00020000; + static constexpr uint32_t bit_DCA = 0x00040000; + static constexpr uint32_t bit_SSE41 = 0x00080000; + static constexpr uint32_t bit_SSE42 = 0x00100000; + static constexpr uint32_t bit_x2APIC = 0x00200000; + static constexpr uint32_t bit_MOVBE = 0x00400000; + static constexpr uint32_t bit_POPCNT = 0x00800000; + static constexpr uint32_t bit_TSCDeadline = 0x01000000; + static constexpr uint32_t bit_AESNI = 0x02000000; + static constexpr uint32_t bit_XSAVE = 0x04000000; + static constexpr uint32_t bit_OSXSAVE = 0x08000000; + static constexpr uint32_t bit_AVX = 0x10000000; + static constexpr uint32_t bit_F16C = 0x20000000; + static constexpr uint32_t bit_RDRND = 0x40000000; + + /* Features in %edx for leaf 1 */ + static constexpr uint32_t bit_FPU = 0x00000001; + static constexpr uint32_t bit_VME = 0x00000002; + static constexpr uint32_t bit_DE = 0x00000004; + static constexpr uint32_t bit_PSE = 0x00000008; + static constexpr uint32_t bit_TSC = 0x00000010; + static constexpr uint32_t bit_MSR = 0x00000020; + static constexpr uint32_t bit_PAE = 0x00000040; + static constexpr uint32_t bit_MCE = 0x00000080; + static constexpr uint32_t bit_CX8 = 0x00000100; + static constexpr uint32_t bit_APIC = 0x00000200; + static constexpr uint32_t bit_SEP = 0x00000800; + static constexpr uint32_t bit_MTRR = 0x00001000; + static constexpr uint32_t bit_PGE = 0x00002000; + static constexpr uint32_t bit_MCA = 0x00004000; + static constexpr uint32_t bit_CMOV = 0x00008000; + static constexpr uint32_t bit_PAT = 0x00010000; + static constexpr uint32_t bit_PSE36 = 0x00020000; + static constexpr uint32_t bit_PSN = 0x00040000; + static constexpr uint32_t bit_CLFSH = 0x00080000; + static constexpr uint32_t bit_DS = 0x00200000; + static constexpr uint32_t bit_ACPI = 0x00400000; + static constexpr uint32_t bit_MMX = 0x00800000; + static constexpr uint32_t bit_FXSR = 0x01000000; + static constexpr uint32_t bit_SSE = 0x02000000; + static constexpr uint32_t bit_SSE2 = 0x04000000; + static constexpr uint32_t bit_SS = 0x08000000; + static constexpr uint32_t bit_HTT = 0x10000000; + static constexpr uint32_t bit_TM = 0x20000000; + static constexpr uint32_t bit_PBE = 0x80000000; + + /* Features in %ebx for leaf 7 sub-leaf 0 */ + static constexpr uint32_t bit_FSGSBASE = 0x00000001; + static constexpr uint32_t bit_SGX = 0x00000004; + static constexpr uint32_t bit_BMI = 0x00000008; + static constexpr uint32_t bit_HLE = 0x00000010; + static constexpr uint32_t bit_AVX2 = 0x00000020; + static constexpr uint32_t bit_SMEP = 0x00000080; + static constexpr uint32_t bit_BMI2 = 0x00000100; + static constexpr uint32_t bit_ENH_MOVSB = 0x00000200; + static constexpr uint32_t bit_RTM = 0x00000800; + static constexpr uint32_t bit_MPX = 0x00004000; + static constexpr uint32_t bit_AVX512F = 0x00010000; + static constexpr uint32_t bit_AVX512DQ = 0x00020000; + static constexpr uint32_t bit_RDSEED = 0x00040000; + static constexpr uint32_t bit_ADX = 0x00080000; + static constexpr uint32_t bit_AVX512IFMA = 0x00200000; + static constexpr uint32_t bit_CLFLUSHOPT = 0x00800000; + static constexpr uint32_t bit_CLWB = 0x01000000; + static constexpr uint32_t bit_AVX512PF = 0x04000000; + static constexpr uint32_t bit_AVX51SER = 0x08000000; + static constexpr uint32_t bit_AVX512CD = 0x10000000; + static constexpr uint32_t bit_SHA = 0x20000000; + static constexpr uint32_t bit_AVX512BW = 0x40000000; + static constexpr uint32_t bit_AVX512VL = 0x80000000; + + /* Features in %ecx for leaf 7 sub-leaf 0 */ + static constexpr uint32_t bit_PREFTCHWT1 = 0x00000001; + static constexpr uint32_t bit_AVX512VBMI = 0x00000002; + static constexpr uint32_t bit_PKU = 0x00000004; + static constexpr uint32_t bit_OSPKE = 0x00000010; + static constexpr uint32_t bit_AVX512VPOPCNTDQ = 0x00004000; + static constexpr uint32_t bit_RDPID = 0x00400000; + + /* Features in %edx for leaf 7 sub-leaf 0 */ + static constexpr uint32_t bit_AVX5124VNNIW = 0x00000004; + static constexpr uint32_t bit_AVX5124FMAPS = 0x00000008; + + /* Features in %eax for leaf 13 sub-leaf 1 */ + static constexpr uint32_t bit_XSAVEOPT = 0x00000001; + static constexpr uint32_t bit_XSAVEC = 0x00000002; + static constexpr uint32_t bit_XSAVES = 0x00000008; + + /* Features in %ecx for leaf = 0x80000001 */; + static constexpr uint32_t bit_LAHF_LM = 0x00000001; + static constexpr uint32_t bit_ABM = 0x00000020; + static constexpr uint32_t bit_SSE4a = 0x00000040; + static constexpr uint32_t bit_PRFCHW = 0x00000100; + static constexpr uint32_t bit_XOP = 0x00000800; + static constexpr uint32_t bit_LWP = 0x00008000; + static constexpr uint32_t bit_FMA4 = 0x00010000; + static constexpr uint32_t bit_TBM = 0x00200000; + static constexpr uint32_t bit_MWAITX = 0x20000000; + + /* Features in %edx for leaf = 0x80000001 */; + static constexpr uint32_t bit_MMXEXT = 0x00400000; + static constexpr uint32_t bit_LM = 0x20000000; + static constexpr uint32_t bit_3DNOWP = 0x40000000; + static constexpr uint32_t bit_3DNOW = 0x80000000; + + /* Features in %ebx for leaf = 0x80000001 */; + static constexpr uint32_t bit_CLZERO = 0x00000001; + + /** + * Reads CPU information and other data. + */ + void loadCpuInformation(); + + /** + * Installed CPU information mapping + */ + struct CpuTopology { + /** + * Number of physical processors installed + */ + uint8_t packageCount {0}; + + /** + * Number of physical cores per package + */ + uint8_t physicalCount[MaxCpus] {}; + + /** + * Number of logical cores per package + */ + uint8_t logicalCount[MaxCpus] {}; + + /** + * Total number of physical cores + */ + inline uint8_t totalPhysical() { + uint8_t count = physicalCount[0]; + for (uint8_t i = 1; i < packageCount; i++) + count += physicalCount[i]; + return count; + } + + /** + * Total number of logical cores + */ + inline uint8_t totalLogical() { + uint8_t count = logicalCount[0]; + for (uint8_t i = 1; i < packageCount; i++) + count += logicalCount[i]; + return count; + } + + /** + * Mapping of cpu_number() to CPU package from 0 to packageCount + */ + uint8_t numberToPackage[MaxCpus] {}; + + /** + * Mapping of cpu_number() to physical core from 0 to physicalCount in package + */ + uint8_t numberToPhysical[MaxCpus] {}; + + /** + * Mapping of cpu_number() to physical cores from 0 to totalPhysical. + */ + inline uint8_t numberToPhysicalUnique(uint8_t i) { + uint8_t num = 0; + uint8_t package = numberToPackage[i]; + for (uint8_t i = 0; i < package; i++) + num += physicalCount[i]; + return num + numberToPhysical[i]; + } + + /** + * Mapping of cpu_number() to logical thread from 0 to logicalCount in package + * Note, that the list is sorted, and the first physicalCount logical threads + * correspond to their corresponding physical cores. + */ + uint8_t numberToLogical[MaxCpus] {}; + }; + + /** + * Get running CPU generation. + * + * @param ofamily a pointer to store CPU family in + * @param omodel a pointer to store CPU model in + * @param ostepping a pointer to store CPU stepping in + * + * @return detected Intel CPU generation + */ + EXPORT CpuGeneration getGeneration(uint32_t *ofamily=nullptr, uint32_t *omodel=nullptr, uint32_t *ostepping=nullptr); + + /** + * Obtain CPU topology. + * + * @param topology parsed cpu topology, must be passed zeroed. + * + * @return true on success + */ + EXPORT bool getCpuTopology(CpuTopology &topology); + + /** + * Obtain cpuid registers + * + * @param no cpuid number + * @param count cpuid count + * @param a eax output pointer (optional) + * @param b ebx output pointer (optional) + * @param c ecx output pointer (optional) + * @param d edx output pointer (optional) + * + * @return true if supported + */ + EXPORT bool getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b=nullptr, uint32_t *c=nullptr, uint32_t *d=nullptr); +} + +#endif /* kern_cpu_h */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_crypto.hpp b/Lilu.kext/Contents/Resources/Headers/kern_crypto.hpp new file mode 100644 index 0000000..d8fc594 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_crypto.hpp @@ -0,0 +1,111 @@ +// +// kern_crypto.hpp +// Lilu +// +// Copyright © 2017 vit9696. All rights reserved. +// + +#ifndef kern_crypto_h +#define kern_crypto_h + +#include +#include +#include + +namespace Crypto { + /** + * Currently this is equal to both key size and block size + */ + static constexpr uint32_t BlockSize = 16; + + /** + * Currently this is guaranteed hash size + */ + static constexpr uint32_t MinDigestSize = 32; + + /** + * Encrypted data format + */ + struct PACKED Encrypted { + uint8_t iv[BlockSize]; // Initialisation vector + struct PACKED Data { + uint32_t size; // Actual encrypted buffer size + uint8_t buf[BlockSize - sizeof(uint32_t)]; // Encrypted buffer >= BlockSize + }; + + union { + Data enc; + uint8_t buf[BlockSize]; + }; + }; + + /** + * Securely erase memory buffer + * Based off cc_clear from corecrypto (src/cc_clear.c) + * + * @param len buffer length + * @param dst buffer pointer + */ + inline void zeroMemory(size_t len, void *dst) { + auto vptr = reinterpret_cast(dst); + while (len--) + *vptr++ = '\0'; + } + + /** + * Generates a platform specific encryption key to be used for later encryption/decryption. + * Use very cautiously, this generates a key that should be reproducible on the same hardware. + * This means that the key is NOT meant protect the data from decryption on the same machine, + * but it only tries to circumvent cases when some blobs containing sensitive information + * (e.g. nvram dumps) were accidentally shared. + * + * This is currently UNIMPLEMENTED + * + * @param seed prefixed data blob used for key generation + * @param size seed size + * + * @return generated key of at least BlockSize bits long (must be freeded by Buffer::deleter) or nullptr + */ + EXPORT uint8_t *genPlatformKey(const uint8_t *seed=nullptr, uint32_t size=0); + + /** + * Generates cryptographically secure encryption key (from /dev/random) + * + * @return generated key of at least BlockSize bits long (must be freeded by Buffer::deleter) or nullptr + */ + EXPORT uint8_t *genUniqueKey(uint32_t size=BlockSize); + + /** + * Encrypts data of specified size and stores in Encrypted format + * + * @param key encryption key returned by genUniqueKey, genPlatformKey (default if null) + * @param src source data + * @param size data size, encrypted size is returned on success + * + * @param encrypted data in Encrypted format (must be freeded by Buffer::deleter) or nullptr + */ + EXPORT uint8_t *encrypt(const uint8_t *key, const uint8_t *src, uint32_t &size); + + /** + * Decrypts data of specified size stored in Encrypted format + * + * @param key encryption key returned by genUniqueKey, genPlatformKey (default if null) + * @param src source data + * @param size data size, decrypted size is returned on success + * + * @param decrypted data (must be freeded by Buffer::deleter) or nullptr + */ + EXPORT uint8_t *decrypt(const uint8_t *key, const uint8_t *src, uint32_t &size); + + /** + * Calculate digest of given size + * + * @param src source data + * @param size data size + * + * @return digest hash of at least MinDigestSize bytes (must be freeded by Buffer::deleter) or nullptr + */ + EXPORT uint8_t *hash(const uint8_t *src, uint32_t size); +} + +#endif /* kern_crypto_h */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_devinfo.hpp b/Lilu.kext/Contents/Resources/Headers/kern_devinfo.hpp new file mode 100644 index 0000000..ab22669 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_devinfo.hpp @@ -0,0 +1,255 @@ +// +// kern_devinfo.hpp +// Lilu +// +// Copyright © 2018 vit9696. All rights reserved. +// + +#ifndef kern_devinfo_h +#define kern_devinfo_h + +#include +#include +#include + +/** + * Obtain installed devices split into categories. + * Should be used from onPatcherLoad and onwards. + */ +class DeviceInfo { + /** + * Updates reportedLayoutId + */ + void updateLayoutId(); + + /** + * Updates reportedFramebufferId + */ + void updateFramebufferId(); + + /** + * Updates firmwareVendor + */ + void updateFirmwareVendor(); + + /** + * Obtains devices from PCI root + * + * @param pciRoot PCI root instance (commonly PCI0@0 device) + */ + void grabDevicesFromPciRoot(IORegistryEntry *pciRoot); + +public: + /** + * Obtains autodetected legacy framebuffer if applicable + * + * @return framebuffer or 0xFFFFFFFF + */ + static uint32_t getLegacyFramebufferId(); + + /** + * Checks whether the framebuffer has connectors or not. + * + * @return true if the framebuffer has no connectors + */ + static bool isConnectorLessPlatformId(uint32_t id); + + /** + * Common external GPU parameter list + */ + struct ExternalVideo { + /** + * Aka GFX0 device + */ + IORegistryEntry *video {nullptr}; + + /** + * Aka HDAU device + */ + IORegistryEntry *audio {nullptr}; + + /** + * External GPU vendor + */ + uint32_t vendor {0}; + }; + + /** + * Aka HDEF device + */ + IORegistryEntry *audioBuiltinAnalog {nullptr}; + + /** + * Aka HDAU device for builtin GPU + */ + IORegistryEntry *audioBuiltinDigital {nullptr}; + + /** + * Aka IGPU device + */ + IORegistryEntry *videoBuiltin {nullptr}; + + /** + * Aka IMEI device + */ + IORegistryEntry *managementEngine {nullptr}; + + /** + * Aka GFX0 devices (kept in sync with audioExternal) + */ + evector videoExternal; + +private: + /** + * This is the default reported layout-id passed to reportedLayoutId. + * The reason for choosing 7 is its presence in 10.14 and the fact + * Apple frameworks still communicate to the files present on disk. + * For information purposes only! Use reportedLayoutId! + */ + static constexpr uint32_t DefaultReportedLayoutId = 7; + + /** + * The boot-arg to override the reported layout-id to AppleHDA. + * For user configuration only! Use reportedLayoutId! + */ + static constexpr const char *ReportedLayoutIdArg = "alcapplid"; + + /** + * The property to override the reported layout-id to AppleHDA. + * For user configuration only! Use reportedLayoutId! + */ + static constexpr const char *ReportedLayoutIdName = "apple-layout-id"; + +public: + /** + * Layout id to be reported by all audio devices (you must update it yourself). + * This follows the standard convention initially found in AppleALC: + * alcapplid=X boot-arg has highest priority and overrides any other value. + * apple-layout-id HDEF prop has normal priority, you may use it if you need. + * DefaultReportedLayoutId will be used if both of the above are not set. + */ + uint32_t reportedLayoutId {0}; + +private: + /** + * The boot-arg to override the reported AAPL,ig-platform-id to Intel drivers. + * For user configuration only! Use reportedFramebufferId! + */ + static constexpr const char *ReportedFrameIdArg = "igfxframe"; + + /** + * The boot-arg to override the reported AAPL,ig-platform-id to Intel drivers. + * Sets VESA framebuffer id (0xFFFFFFFF). + * For user configuration only! Use reportedFramebufferId! + */ + static constexpr const char *ReportedVesaIdArg = "-igfxvesa"; + + /** + * The property to set your platform id for Intel drivers (Ivy and newer). + * For user configuration only! Use reportedFramebufferName! + */ + static constexpr const char *ReportedFrameIdName = "AAPL,ig-platform-id"; + + /** + * The property to set your platform id for Intel drivers (Sandy). + * For user configuration only! Use reportedFramebufferName! + */ + static constexpr const char *ReportedFrameIdLegacyName = "AAPL,snb-platform-id"; + + /** + * Known platform ids used by Intel GPU kexts + * For user configuration only! + */ + static constexpr uint32_t DefaultAppleSkylakePlatformId {0x19120000}; + static constexpr uint32_t DefaultAppleKabyLakePlatformId {0x59160000}; + static constexpr uint32_t DefaultAppleCoffeeLakePlatformId {0x3EA50000}; + static constexpr uint32_t DefaultAppleCannonLakePlatformId {0x5A520000}; + static constexpr uint32_t DefaultAppleIceLakeRealPlatformId {0x8A520000}; + static constexpr uint32_t DefaultAppleIceLakeSimulatorPlatformId {0xFF050000}; + + /** + * Framebuffers without any ports used for hardware acceleration only + * Note 1: Broadwell framebuffers all have connectors added. + * Note 2: Coffee Lake framebuffers without connectors are only present in 10.14. + * Note 3: prerelease Cannon Lake and Ice Lake framebuffers are without connectors. + * For user configuration only! + */ + static constexpr uint32_t ConnectorLessSandyBridgePlatformId1 {0x00030030}; + static constexpr uint32_t ConnectorLessSandyBridgePlatformId2 {0x00050000}; + static constexpr uint32_t ConnectorLessIvyBridgePlatformId1 {0x01620006}; + static constexpr uint32_t ConnectorLessIvyBridgePlatformId2 {0x01620007}; + static constexpr uint32_t ConnectorLessHaswellPlatformId1 {0x04120004}; + static constexpr uint32_t ConnectorLessHaswellPlatformId2 {0x0412000B}; + static constexpr uint32_t ConnectorLessSkylakePlatformId1 {0x19020001}; + static constexpr uint32_t ConnectorLessSkylakePlatformId2 {0x19170001}; + static constexpr uint32_t ConnectorLessSkylakePlatformId3 {0x19120001}; + static constexpr uint32_t ConnectorLessSkylakePlatformId4 {0x19320001}; + static constexpr uint32_t ConnectorLessKabyLakePlatformId1 {0x59180002}; + static constexpr uint32_t ConnectorLessKabyLakePlatformId2 {0x59120003}; + static constexpr uint32_t ConnectorLessCoffeeLakePlatformId1 {0x3E920003}; + static constexpr uint32_t ConnectorLessCoffeeLakePlatformId2 {0x3E910003}; + +public: + /** + * Vesa framebuffer identifier + */ + static constexpr uint32_t DefaultVesaPlatformId {0xFFFFFFFF}; + + /** + * Framebuffer id to be reported to IGPU. + * This follows the standard convention initially found in IntelGraphicsFixup: + * igfxframe=X boot-arg has highest priority and overrides any other value. + * -igfxvesa forces 0xFFFFFFFF frame to get into VESA mode. + * Manually specified AAPL,ig-platform-id or AAPL,snb-platform-id go next. + * On Sandy Bridge processors a default AAPL,snb-platform-id will be tried afterwards. + * On Skylake and Kaby Lake processors some default id will be tried afterwards. + */ + uint32_t reportedFramebufferId {0}; + + /** + * Compatible platform id property name for this IGPU + */ + const char *reportedFramebufferName {nullptr}; + + /** + * Set to true if the framebuffer has no connectors + */ + bool reportedFramebufferIsConnectorLess {false}; + + /** + * Known variants of firmware vendors + * Please note, that it may not be possible to always detect the right vendor + */ + enum class FirmwareVendor { + Unknown, + Apple, + VMware, + EDKII, + Parallels, + AMI, + Insyde, + Phoenix, + HP + }; + + /** + * Firmware vendor manufacturer + */ + FirmwareVendor firmwareVendor {FirmwareVendor::Unknown}; + + /** + * Allocate and initialise the device list. + * + * @return device list or nullptr + */ + EXPORT static DeviceInfo *create(); + + /** + * Release initialised device list. + * + * @param d device list + */ + EXPORT static void deleter(DeviceInfo *d); +}; + +#endif /* kern_devinfo_h */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_disasm.hpp b/Lilu.kext/Contents/Resources/Headers/kern_disasm.hpp index 2243217..fbabac7 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_disasm.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_disasm.hpp @@ -8,18 +8,21 @@ #ifndef kern_disasm_hpp #define kern_disasm_hpp +#include +#include + +#ifdef LILU_ADVANCED_DISASSEMBLY #ifndef CAPSTONE_HAS_OSXKERNEL #define CAPSTONE_HAS_OSXKERNEL 1 #endif - -#include -#include #include +#endif /* LILU_ADVANCED_DISASSEMBLY */ #include #include class Disassembler { +#ifdef LILU_ADVANCED_DISASSEMBLY /** * Because captsone handle can be 0 */ @@ -28,7 +31,8 @@ class Disassembler { /** * Internal capstone handle */ - size_t handle; + size_t handle {}; +#endif /** * Max instruction size @@ -36,23 +40,10 @@ class Disassembler { static constexpr size_t MaxInstruction {15}; public: - /** - * Initialise dissassembling framework - * - * @param detailed debugging output necessity - * - * @return true on success - */ - EXPORT bool init(bool detailed=false); - - /** - * Deinitialise dissassembling framework, must be called regardless of the init error - */ - EXPORT void deinit(); - /** * Return the real instruction size contained within min bytes * Unlike instructionSize this uses HDE engine and at the cost of reduced compatibility it is much faster + * Note: instruction pointer should point to at least min + 32 valid bytes. * * @param ptr instruction pointer * @param min minimal possible size @@ -60,7 +51,23 @@ class Disassembler { * @return instruction size >= min on success or 0 */ EXPORT static size_t quickInstructionSize(mach_vm_address_t ptr, size_t min); + +#ifdef LILU_ADVANCED_DISASSEMBLY + + /** + * Initialise advanced dissassembling framework + * + * @param detailed debugging output necessity + * + * @return true on success + */ + EXPORT bool init(bool detailed=false); + /** + * Deinitialise advanced dissassembling framework, must be called regardless of the init error + */ + EXPORT void deinit(); + /** * Reads size bytes from addr and disassembles them. * @@ -148,6 +155,8 @@ class Disassembler { * @return direct address of pattern start on success, else 0 */ EXPORT mach_vm_address_t disasmSig(mach_vm_address_t addr, evector &sig, size_t num, size_t lookup_size); + +#endif /* LILU_ADVANCED_DISASSEMBLY */ }; #endif /* kern_disasm_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_efi.hpp b/Lilu.kext/Contents/Resources/Headers/kern_efi.hpp new file mode 100644 index 0000000..48c6fa5 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_efi.hpp @@ -0,0 +1,86 @@ +// +// kern_efi.hpp +// Lilu +// +// Copyright © 2018 vit9696. All rights reserved. +// + +#ifndef kern_efi_h +#define kern_efi_h + +#include + +#include + +/** + * Convert 32-bit EFI errors provided by Apple to 64-bit EFI errors + */ +#define EFI_ERROR64(x) (((x) & ~(1ULL << 31)) | (1ULL << 63)) +static_assert(EFI_LOAD_ERROR == 0x80000001 && EFI_ERROR64(EFI_LOAD_ERROR) == 0x8000000000000001, + "Apple has finally upgraded EFI headers!"); + +class EfiRuntimeServices { + IOLock *accessLock {nullptr}; + static EfiRuntimeServices *instance; +public: + /** + * Activates EFI Runtime Services + */ + static void activate(); + + /** + * Lilu custom GUIDs exports, see Headers/Guid/LiluVariables.h + */ + EXPORT static const EFI_GUID LiluNormalGuid; + EXPORT static const EFI_GUID LiluReadOnlyGuid; + EXPORT static const EFI_GUID LiluWriteOnlyGuid; + + /** + * Get EFI Runtime Services wrapper if supported + * + * @param lock lock instance during the run, must be put back + * + * @return wrapper instance + */ + EXPORT static EfiRuntimeServices *get(bool lock=false); + + /** + * Put EFI Runtime Services wrapper to unlock + */ + EXPORT void put(); + + /** + * Perform system reset (does not return on success) + * + * @param type reset type + */ + EXPORT void resetSystem(EFI_RESET_TYPE type); + + /** + * Obtain EFI variable, invokes EFI_RUNTIME_SERVICES::GetVariable. + * + * @param name variable name + * @param guid vendor guid + * @param attr variable attributes + * @param size data buffer size updated on read + * @param data read data + * + * @return EFI_STATUS code + */ + EXPORT uint64_t getVariable(const char16_t *name, const EFI_GUID *guid, uint32_t *attr, uint64_t *size, void *data); + + /** + * Set EFI variable, invokes EFI_RUNTIME_SERVICES::SetVariable. + * + * @param name variable name + * @param guid vendor guid + * @param attr variable attributes + * @param size data buffer size + * @param data data to write + * + * @return EFI_STATUS code + */ + EXPORT uint64_t setVariable(const char16_t *name, const EFI_GUID *guid, uint32_t attr, uint64_t size, void *data); +}; + +#endif /* kern_efi_h */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_iokit.hpp b/Lilu.kext/Contents/Resources/Headers/kern_iokit.hpp index b37953b..6c753dd 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_iokit.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_iokit.hpp @@ -34,42 +34,82 @@ namespace WIOKit { * @return true on success */ template - bool getOSDataValue(const OSObject *obj, const char *name, T &value) { + inline bool getOSDataValue(const OSObject *obj, const char *name, T &value) { if (obj) { auto data = OSDynamicCast(OSData, obj); if (data && data->getLength() == sizeof(T)) { value = *static_cast(data->getBytesNoCopy()); - DBGLOG("iokit @ getOSData %s has %llX value", name, static_cast(value)); + DBGLOG("iokit", "getOSData %s has %llX value", name, static_cast(value)); return true; } else { - SYSLOG("iokit @ getOSData %s has unexpected format", name); + SYSLOG("iokit", "getOSData %s has unexpected format", name); } } else { - DBGLOG("iokit @ getOSData %s was not found", name); + DBGLOG("iokit", "getOSData %s was not found", name); } return false; } - + + /** + * Read typed OSData through a temp type + * + * @param obj read object + * @param value read value + * @param name propert name + * + * @return true on success + */ + template + inline bool getOSDataValue(const OSObject *obj, const char *name, T &value) { + AS tmp; + if (getOSDataValue(obj, name, tmp)) { + value = static_cast(tmp); + return true; + } + + return false; + } + /** * Read typed OSData from IORegistryEntry * * @see getOSDataValue */ template - bool getOSDataValue(const IORegistryEntry *sect, const char *name, T &value) { + inline bool getOSDataValue(const IORegistryEntry *sect, const char *name, T &value) { return getOSDataValue(sect->getProperty(name), name, value); } - + + /** + * Read typed OSData from IORegistryEntry + * + * @see getOSDataValue + */ + template + inline bool getOSDataValue(const IORegistryEntry *sect, const char *name, T &value) { + return getOSDataValue(sect->getProperty(name), name, value); + } + /** * Read typed OSData from IORegistryEntry * * @see getOSDataValue */ template - bool getOSDataValue(const OSDictionary *dict, const char *name, T &value) { + inline bool getOSDataValue(const OSDictionary *dict, const char *name, T &value) { return getOSDataValue(dict->getObject(name), name, value); } + /** + * Read typed OSData from IORegistryEntry + * + * @see getOSDataValue + */ + template + inline bool getOSDataValue(const OSDictionary *dict, const char *name, T &value) { + return getOSDataValue(dict->getObject(name), name, value); + } + /** * Retrieve property object * @@ -79,26 +119,132 @@ namespace WIOKit { * @return property object (must be released) or nullptr */ EXPORT OSSerialize *getProperty(IORegistryEntry *entry, const char *property); - + /** * Model variants */ struct ComputerModel { enum { ComputerInvalid = 0x0, - ComputerLaptop = 0x1, + ComputerLaptop = 0x1, ComputerDesktop = 0x2, ComputerAny = ComputerLaptop | ComputerDesktop }; }; - + + /** + * PCI GPU Vendor identifiers + */ + struct VendorID { + enum : uint16_t { + ATIAMD = 0x1002, + NVIDIA = 0x10de, + Intel = 0x8086 + }; + }; + + /** + * PCI class codes + */ + struct ClassCode { + enum : uint32_t { + VGAController = 0x30000, + DisplayController = 0x38000, + PCIBridge = 0x60400, + HDADevice = 0x040300, + // This does not seem to be documented. It works on Haswell at least. + IMEI = 0x78000 + }; + }; + + /** + * Definitions of PCI Config Registers + */ + enum PCIRegister : uint8_t { + kIOPCIConfigVendorID = 0x00, + kIOPCIConfigDeviceID = 0x02, + kIOPCIConfigCommand = 0x04, + kIOPCIConfigStatus = 0x06, + kIOPCIConfigRevisionID = 0x08, + kIOPCIConfigClassCode = 0x09, + kIOPCIConfigCacheLineSize = 0x0C, + kIOPCIConfigLatencyTimer = 0x0D, + kIOPCIConfigHeaderType = 0x0E, + kIOPCIConfigBIST = 0x0F, + kIOPCIConfigBaseAddress0 = 0x10, + kIOPCIConfigBaseAddress1 = 0x14, + kIOPCIConfigBaseAddress2 = 0x18, + kIOPCIConfigBaseAddress3 = 0x1C, + kIOPCIConfigBaseAddress4 = 0x20, + kIOPCIConfigBaseAddress5 = 0x24, + kIOPCIConfigCardBusCISPtr = 0x28, + kIOPCIConfigSubSystemVendorID = 0x2C, + kIOPCIConfigSubSystemID = 0x2E, + kIOPCIConfigExpansionROMBase = 0x30, + kIOPCIConfigCapabilitiesPtr = 0x34, + kIOPCIConfigInterruptLine = 0x3C, + kIOPCIConfigInterruptPin = 0x3D, + kIOPCIConfigMinimumGrant = 0x3E, + kIOPCIConfigMaximumLatency = 0x3F + }; + + /** + * Fixed offsets for PCI Config I/O virtual methods + */ + struct PCIConfigOffset { + enum : size_t { + ConfigRead32 = 0x10A, + ConfigWrite32 = 0x10B, + ConfigRead16 = 0x10C, + ConfigWrite16 = 0x10D, + ConfigRead8 = 0x10E, + ConfigWrite8 = 0x10F, + GetBusNumber = 0x11D, + GetDeviceNumber = 0x11E, + GetFunctionNumber = 0x11F + }; + }; + + /** + * PCI Config I/O method prototypes + */ + using t_PCIConfigRead32 = uint32_t (*)(IORegistryEntry *service, uint32_t space, uint8_t offset); + using t_PCIConfigRead16 = uint16_t (*)(IORegistryEntry *service, uint32_t space, uint8_t offset); + using t_PCIConfigRead8 = uint8_t (*)(IORegistryEntry *service, uint32_t space, uint8_t offset); + using t_PCIConfigWrite32 = void (*)(IORegistryEntry *service, uint32_t space, uint8_t offset, uint32_t data); + using t_PCIConfigWrite16 = void (*)(IORegistryEntry *service, uint32_t space, uint8_t offset, uint16_t data); + using t_PCIConfigWrite8 = void (*)(IORegistryEntry *service, uint32_t space, uint8_t offset, uint8_t data); + using t_PCIGetBusNumber = uint8_t (*)(IORegistryEntry *service); + using t_PCIGetDeviceNumber = uint8_t (*)(IORegistryEntry *service); + using t_PCIGetFunctionNumber = uint8_t (*)(IORegistryEntry *service); + + /** + * Read PCI Config register + * + * @param service IOPCIDevice-compatible service. + * @param reg PCI config register + * @param space adress space + * @param size read size for reading custom registers + */ + EXPORT uint32_t readPCIConfigValue(IORegistryEntry *service, uint32_t reg, uint32_t space = 0, uint32_t size = 0); + + /** + * Retrieve PCI device address + * + * @param service IOPCIDevice-compatible service. + * @param bus bus address + * @param device device address + * @param function function address + */ + EXPORT void getDeviceAddress(IORegistryEntry *service, uint8_t &bus, uint8_t &device, uint8_t &function); + /** * Retrieve the computer type * * @return valid computer type or ComputerAny */ EXPORT int getComputerModel(); - + /** * Retrieve computer model and/or board-id properties * @@ -110,7 +256,7 @@ namespace WIOKit { * @return true if relevant properties already are available, otherwise buffers are unchanged */ EXPORT bool getComputerInfo(char *model, size_t modelsz, char *board, size_t boardsz); - + /** * Retrieve an ioreg entry by path/prefix * @@ -124,7 +270,7 @@ namespace WIOKit { * @return entry pointer (must NOT be released) or nullptr (on failure or in proc mode) */ EXPORT IORegistryEntry *findEntryByPrefix(const char *path, const char *prefix, const IORegistryPlane *plane, bool (*proc)(void *, IORegistryEntry *)=nullptr, bool brute=false, void *user=nullptr); - + /** * Retrieve an ioreg entry by path/prefix * @@ -138,6 +284,24 @@ namespace WIOKit { * @return entry pointer (must NOT be released) or nullptr (on failure or in proc mode) */ EXPORT IORegistryEntry *findEntryByPrefix(IORegistryEntry *entry, const char *prefix, const IORegistryPlane *plane, bool (*proc)(void *, IORegistryEntry *)=nullptr, bool brute=false, void *user=nullptr); + + /** + * Check if we are using prelinked kernel/kexts or not + * + * @return true when confirmed that we definitely are + */ + EXPORT bool usingPrelinkedCache(); + + /** + * Properly rename the device + * + * @param entry device to rename + * @param name new name + * @param compat correct compatible + * + * @return true on success + */ + EXPORT bool renameDevice(IORegistryEntry *entry, const char *name, bool compat=true); } #endif /* kern_iokit_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_mach.hpp b/Lilu.kext/Contents/Resources/Headers/kern_mach.hpp index aa16c9b..329ee08 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_mach.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_mach.hpp @@ -18,14 +18,17 @@ #include #include #include +#include class MachInfo { mach_vm_address_t running_text_addr {0}; // the address of running __TEXT segment mach_vm_address_t disk_text_addr {0}; // the same address at from a file mach_vm_address_t kaslr_slide {0}; // the kernel aslr slide, computed as the difference between above's addresses -#ifdef LILU_COMPRESSION_SUPPORT - uint8_t *file_buf {nullptr}; // read file data if decompression was used -#endif /* LILU_COMPRESSION_SUPPORT */ + uint8_t *file_buf {nullptr}; // read file data + OSDictionary *prelink_dict {nullptr}; // read prealinked kext dictionary + uint8_t *prelink_addr {nullptr}; // prelink text base address + mach_vm_address_t prelink_vmaddr {0}; // prelink text base vm address (for kexts this is their actual slide) + uint32_t file_buf_size {0}; // read file data size uint8_t *linkedit_buf {nullptr}; // pointer to __LINKEDIT buffer containing symbols to solve uint64_t linkedit_fileoff {0}; // __LINKEDIT file offset so we can read uint64_t linkedit_size {0}; @@ -37,45 +40,34 @@ class MachInfo { size_t memory_size {HeaderSize}; // memory size bool kaslr_slide_set {false}; // kaslr can be null, used for disambiguation bool allow_decompress {true}; // allows mach decompression - - /** - * 16 byte IDT descriptor, used for 32 and 64 bits kernels (64 bit capable cpus!) - */ - struct descriptor_idt { - uint16_t offset_low; - uint16_t seg_selector; - uint8_t reserved; - uint8_t flag; - uint16_t offset_middle; - uint32_t offset_high; - uint32_t reserved2; - }; - + bool prelink_slid {false}; // assume kaslr-slid kext addresses + uint64_t self_uuid[2] {}; // saved uuid of the loaded kext or kernel + /** - * retrieve the address of the IDT - * - * @return always returns the IDT address + * Kernel slide is aligned by 20 bits */ - mach_vm_address_t getIDTAddress(); - + static constexpr size_t KASLRAlignment {0x100000}; + /** - * calculate the address of the kernel int80 handler + * Retrieve LC_UUID command value from a mach header * - * @return always returns the int80 handler address + * @param header mach header pointer + * + * @return UUID or nullptr */ - mach_vm_address_t calculateInt80Address(); - + uint64_t *getUUID(void *header); + /** - * retrieve LC_UUID command value from a mach header + * Retrieve and preserve LC_UUID command value from a mach header * * @param header mach header pointer * - * @return UUID or nullptr + * @return true on success */ - uint64_t *getUUID(void *header); + bool loadUUID(void *header); /** - * enable/disable the Write Protection bit in CR0 register + * Enable/disable the Write Protection bit in CR0 register * * @param enable the desired value * @@ -84,8 +76,8 @@ class MachInfo { static kern_return_t setWPBit(bool enable); /** - * retrieve the first pages of a binary at disk into a buffer - * version that uses KPI VFS functions and a ripped uio_createwithbuffer() from XNU + * Retrieve the first pages of a binary at disk into a buffer + * Version that uses KPI VFS functions and a ripped uio_createwithbuffer() from XNU * * @param buffer allocated buffer sized no less than HeaderSize * @param vnode file node @@ -98,7 +90,7 @@ class MachInfo { kern_return_t readMachHeader(uint8_t *buffer, vnode_t vnode, vfs_context_t ctxt, off_t off=0); /** - * retrieve the whole linkedit segment into target buffer from kernel binary at disk + * Retrieve the whole linkedit segment into target buffer from kernel binary at disk * * @param vnode file node * @param ctxt filesystem context @@ -108,18 +100,54 @@ class MachInfo { kern_return_t readLinkedit(vnode_t vnode, vfs_context_t ctxt); /** - * retrieve necessary mach-o header information from the mach header + * Retrieve necessary mach-o header information from the mach header * * @param header read header sized no less than HeaderSize */ void processMachHeader(void *header); + + /** + * Load kext info dictionary and addresses if they were not loaded previously + */ + void updatePrelinkInfo(); + + /** + * Lookup mach image in prelinked image + * + * @param identifier identifier + * @param imageSize size of the returned buffer + * @param slide actual slide for symbols (normally kaslr or 0) + * @param missing set to true on successful prelink parsing when image is not needed + * + * @return pointer to const buffer on success or nullptr + */ + uint8_t *findImage(const char *identifier, uint32_t &imageSize, mach_vm_address_t &slide, bool &missing); MachInfo(bool asKernel, const char *id) : isKernel(asKernel), objectId(id) { - DBGLOG("mach @ MachInfo asKernel %d object constructed", asKernel); + DBGLOG("mach", "MachInfo asKernel %d object constructed", asKernel); } MachInfo(const MachInfo &) = delete; MachInfo &operator =(const MachInfo &) = delete; - + + /** + * Resolve mach data in the kernel via prelinked cache + * + * @param prelink prelink information source (i.e. Kernel MachInfo) + * + * @return KERN_SUCCESS if loaded + */ + kern_return_t initFromPrelinked(MachInfo *prelink); + + /** + * Resolve mach data in the kernel via filesystem access + * + * @param paths filesystem paths for lookup + * @param num the number of paths passed + * + * @return KERN_SUCCESS if loaded + */ + kern_return_t initFromFileSystem(const char * const paths[], size_t num); + public: /** @@ -135,12 +163,13 @@ class MachInfo { /** * Specified file identifier */ - const char *objectId {nullptr}; + EXPORT const char *objectId {nullptr}; /** * MachInfo object generator * * @param asKernel this MachInfo represents a kernel + * @param id kinfo identifier (e.g. CFBundleIdentifier) * * @return MachInfo object or nullptr */ @@ -150,12 +179,14 @@ class MachInfo { /** * Resolve mach data in the kernel * - * @param paths filesystem paths for lookup - * @param num the number of paths passed + * @param paths filesystem paths for lookup + * @param num the number of paths passed + * @param prelink prelink information source (i.e. Kernel MachInfo) + * @param fsfallback fallback to reading from filesystem if prelink failed * * @return KERN_SUCCESS if loaded */ - EXPORT kern_return_t init(const char * const paths[], size_t num = 1); + EXPORT kern_return_t init(const char * const paths[], size_t num = 1, MachInfo *prelink=nullptr, bool fsfallback=false); /** * Release the allocated memory, must be called regardless of the init error @@ -163,7 +194,7 @@ class MachInfo { EXPORT void deinit(); /** - * retrieve the mach header and __TEXT addresses + * Retrieve the mach header and __TEXT addresses * * @param slide load slide if calculating for kexts * @param size memory size @@ -184,7 +215,7 @@ class MachInfo { EXPORT kern_return_t setRunningAddresses(mach_vm_address_t slide=0, size_t size=0); /** - * retrieve running mach positions + * Retrieve running mach positions * * @param header pointer to header * @param size file size @@ -192,7 +223,7 @@ class MachInfo { EXPORT void getRunningPosition(uint8_t * &header, size_t &size); /** - * solve a mach symbol (running addresses must be calculated) + * Solve a mach symbol (running addresses must be calculated) * * @param symbol symbol to solve * @@ -201,41 +232,40 @@ class MachInfo { EXPORT mach_vm_address_t solveSymbol(const char *symbol); /** - * find the kernel base address (mach-o header) - * by searching backwards using the int80 handler as starting point + * Find the kernel base address (mach-o header) * * @return kernel base address or 0 */ EXPORT mach_vm_address_t findKernelBase(); /** - * enable/disable interrupt handling - * this is similar to ml_set_interrupts_enabled except the return value + * Compare the loaded kernel with the current UUID (see loadUUID) * - * @param enable the desired value + * @param base image base, pass 0 to use kernel base * - * @return true if changed the value and false if it is unchanged + * @return true if image uuids match */ - EXPORT static bool setInterrupts(bool enable); - + EXPORT bool isCurrentBinary(mach_vm_address_t base=0); + /** - * enable/disable kernel memory write protection + * Enable/disable interrupt handling + * this is similar to ml_set_interrupts_enabled except the return value * * @param enable the desired value - * @param sync for synchronous execution, calls in the middle will be ignored * - * @return KERN_SUCCESS if succeeded + * @return true if changed the value and false if it is unchanged */ - EXPORT static kern_return_t setKernelWriting(bool enable, bool sync=false); + EXPORT static bool setInterrupts(bool enable); /** - * Compare the loaded kernel with the passed kernel header + * Enable/disable kernel memory write protection * - * @param kernel_header 64-bit mach header of at least HeaderSize size + * @param enable the desired value + * @param lock use spinlock to disable cpu preemption (see KernelPatcher::kernelWriteLock) * - * @return true if the kernel uuids match + * @return KERN_SUCCESS if succeeded */ - EXPORT bool isCurrentKernel(void *kernelHeader); + EXPORT static kern_return_t setKernelWriting(bool enable, IOSimpleLock *lock); /** * Find section bounds in a passed binary for provided cpu @@ -250,6 +280,11 @@ class MachInfo { * @param cpu cpu to look for in case of fat binaries */ EXPORT static void findSectionBounds(void *ptr, vm_address_t &vmsegment, vm_address_t &vmsection, void *§ionptr, size_t &size, const char *segmentName="__TEXT", const char *sectionName="__text", cpu_type_t cpu=CPU_TYPE_X86_64); + + /** + * Request to free file buffer resources (not including linkedit symtable) + */ + void freeFileBufferResources(); }; #endif /* kern_mach_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_nvram.hpp b/Lilu.kext/Contents/Resources/Headers/kern_nvram.hpp new file mode 100644 index 0000000..2dcb07d --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_nvram.hpp @@ -0,0 +1,198 @@ +// +// kern_nvram.hpp +// Lilu +// +// Copyright © 2017 vit9696. All rights reserved. +// + +#ifndef kern_nvram_hpp +#define kern_nvram_hpp + +#include +#include +#include +#include +#include + +/** + * Some of the most common GUIDs used for variable storage on macOS + */ +#define NVRAM_GLOBAL_GUID "8BE4DF61-93CA-11D2-AA0D-00E098032B8C" +#define NVRAM_APPLE_BOOT_GUID "7C436110-AB2A-4BBB-A880-FE41995C9F82" +#define NVRAM_APPLE_VENDOR_GUID "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14" +#define NVRAM_APPLE_FILEVAULT_GUID "8D63D4FE-BD3C-4AAD-881D-86FD974BC1DF" +#define NVRAM_APPLE_PASSWORD_UI_GUID "9EBA2D25-BBE3-4AC2-A2C6-C87F44A1278C" + +/** + * Custom GUIDs used for Lilu preferences + * Must be kept in sync to Headers/Guid/LiluVariables.h + */ +#define LILU_NORMAL_GUID "2660DD78-81D2-419D-8138-7B1F363F79A6" +#define LILU_READ_ONLY_GUID "E09B9297-7928-4440-9AAB-D1F8536FBF0A" +#define LILU_WRITE_ONLY_GUID "F0B9AF8F-2222-4840-8A37-ECF7CC8C12E1" + +/** + * Prefix variable name with a GUID + */ +#define NVRAM_PREFIX(x, y) x ":" y + +class NVStorage { + /** + * Local nvram controller reference + */ + IORegistryEntry *dtEntry {nullptr}; + +public: + /** + * Compress data with a default compression algorithm + * + * @param src source data + * @param size data size (updated with new size) + * @param sensitive contains sensitive data + * + * @return compressed data (must be freed with Buffer::deleter) or nullptr + */ + EXPORT uint8_t *compress(const uint8_t *src, uint32_t &size, bool sensitive=false); + + /** + * Decompress data compressed with compress + * + * @param src compressed data + * @param size data size (updated with new size) + * @param sensitive contains sensitive data + * + * @return decompressed data (must be freed with Buffer::deleter) or nullptr + */ + EXPORT uint8_t *decompress(const uint8_t *src, uint32_t &size, bool sensitive=false); + + /** + * Value storage options + */ + enum Options { + OptAuto = 0, // Default options + OptRaw = 1, // i/o as raw buffer + OptCompressed = 2, // Apply compression (see kern_compression.hpp) + OptEncrypted = 4, // Apply encryption with device-unique key (see kern_crypto.hpp) + OptChecksum = 8, // Append CRC32 checksum to the end + OptSensitive = 16 // Value contains sensitive data + }; + + /** + * Prepended value header unless OptRaw is used + * After the header the following fields should go: + * uint8_t iv[16]; aes initialisation vector (if OptEncrypted is set) + * uint32_t size; decryption size (if OptEncrypted is set, encrypted) + * uint32_t size; decompression size (if OptCompressed is set, encrypted if OptEncrypted) + * uint8_t data[]; content data (encrypted if OptEncrypted) + * uint32_t crc32; CRC32 cheksum (if OptChecksum is set) + */ + struct PACKED Header { + static constexpr uint16_t Magic = 0xC717; + static constexpr uint8_t MaxVer = 1; + using Checksum = uint32_t; + + uint16_t magic {Magic}; + uint8_t version {MaxVer}; + uint8_t opts {OptAuto}; + }; + + /** + * Attempt to connect to active nvram, may fail at early stages + * + * @return true on success + */ + EXPORT bool init(); + + /** + * Relinquish resources used, must be called regardless of the init error + */ + EXPORT void deinit(); + + /** + * Read data from nvram + * + * @param key key name + * @param size amount of data read + * @param opts bitmask of Options, may set option requirements + * @param enckey encryption key (platform-defined if OptEncrypted is set) + * + * @return pointer to data (must be freed via Buffer::deleter), nullptr on failure + */ + EXPORT uint8_t *read(const char *key, uint32_t &size, uint8_t opts=OptAuto, const uint8_t *enckey=nullptr); + + /** + * Read data from nvram + * + * @param key key name + * @param opts bitmask of Options, may set option requirements + * @param enckey encryption key (platform-defined if OptEncrypted is set) + * + * @return pointer to data (must be freed via OSData::release), nullptr on failure + */ + EXPORT OSData *read(const char *key, uint8_t opts=OptAuto, const uint8_t *enckey=nullptr); + + /** + * Write data to nvram + * + * @param key key name + * @param src source buffer + * @param size buffer size + * @param opts bitmask of Options + * @param enckey encryption key (platform-defined if OptEncrypted is set) + * + * @return true on success + */ + EXPORT bool write(const char *key, const uint8_t *src, uint32_t sz, uint8_t opts=OptAuto, const uint8_t *enckey=nullptr); + + /** + * Write data to nvram + * + * @param key key name + * @param data data object to write + * @param opts bitmask of Options + * @param enckey encryption key (platform-defined if OptEncrypted is set) + * + * @return true on success + */ + EXPORT bool write(const char *key, const OSData *data, uint8_t opts=OptAuto, const uint8_t *enckey=nullptr); + + /** + * Delete key from nvram + * + * @param key key name + * @param sensitive sensitive data + * + * @return true on successful deletion or if key is missing + */ + EXPORT bool remove(const char *key, bool sensitive=false); + + /** + * Synchronize with nvram controller + * This method might fail if synchronisation was done recently. + * + * @return true if synchronised + */ + EXPORT bool sync(); + + /** + * Exports nvram to a plist file + * + * @param filename file path + * @oaram max max output size + * @param sensitive contains sensitive data + * + * @return true if saved + */ + EXPORT bool save(const char *filename, uint32_t max=0x20000, bool sensitive=false); + + /** + * Check whether key exists + * + * @param key key name + * + * @return true if key exists + */ + EXPORT bool exists(const char *key); +}; + +#endif /* kern_nvram_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_patcher.hpp b/Lilu.kext/Contents/Resources/Headers/kern_patcher.hpp index 684981b..1ca78e1 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_patcher.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_patcher.hpp @@ -9,6 +9,7 @@ #define kern_patcher_hpp #include +#include #include #include #include @@ -38,7 +39,10 @@ class KernelPatcher { MemoryIssue, MemoryProtection, PointerRange, - AlreadyDone + AlreadyDone, + LockError, + Unsupported, + InvalidSymbolFound }; /** @@ -63,6 +67,12 @@ class KernelPatcher { */ void deinit(); + /** + * Kernel write lock used for performing kernel & kext writes to disable cpu preemption + * See MachInfo::setKernelWriting + */ + EXPORT static IOSimpleLock *kernelWriteLock; + /** * Kext information */ @@ -71,27 +81,49 @@ class KernelPatcher { #ifdef LILU_KEXTPATCH_SUPPORT struct KextInfo { static constexpr size_t Unloaded {0}; - const char *id; - const char **paths; - size_t pathNum; - bool loaded; // invoke for kext if it is already loaded - bool reloadable; // allow the kext to unload and get patched again - bool user[6]; - size_t loadIndex; // Updated after loading + enum SysFlags : size_t { + Loaded, // invoke for kext if it is already loaded + Reloadable, // allow the kext to unload and get patched again + Disabled, // do not load this kext (formerly achieved pathNum = 0, this no longer works) + FSOnly, // do not use prelinkedkernel (kextcache) as a symbol source + FSFallback, // perform fs fallback if kextcache failed + Reserved, + SysFlagNum, + }; + static constexpr size_t UserFlagNum {sizeof(size_t)-SysFlagNum}; + static_assert(UserFlagNum > 0, "There should be at least one user flag"); + const char *id {nullptr}; + const char **paths {nullptr}; + size_t pathNum {0}; + bool sys[SysFlagNum] {}; + bool user[UserFlagNum] {}; + size_t loadIndex {Unloaded}; // Updated after loading + + /** + * Disable this info from being used + * May be called from onPatcherLoad callbacks to disable certain kexts + */ + void switchOff() { + sys[KernelPatcher::KextInfo::Disabled] = true; + } }; + + static_assert(sizeof(KextInfo) == 5 * sizeof(size_t), "KextInfo is no longer ABI compatible"); #endif /* LILU_KEXTPATCH_SUPPORT */ /** * Loads and stores kinfo information locally * - * @param id kernel item identifier - * @param paths item filesystem path array - * @param num number of path entries - * @param isKernel kinfo is kernel info + * @param id kernel item identifier + * @param paths item filesystem path array + * @param num number of path entries + * @param isKernel kinfo is kernel info + * @param fsonly avoid using prelinkedkernel for kexts + * @param fsfallback fallback to reading from filesystem if prelink failed * * @return loaded kinfo id */ - EXPORT size_t loadKinfo(const char *id, const char * const paths[], size_t num=1, bool isKernel=false); + EXPORT size_t loadKinfo(const char *id, const char * const paths[], size_t num=1, bool isKernel=false, bool fsonly=false, bool fsfallback=false); #ifdef LILU_KEXTPATCH_SUPPORT /** @@ -143,12 +175,46 @@ class KernelPatcher { * @return running symbol address or 0 */ EXPORT mach_vm_address_t solveSymbol(size_t id, const char *symbol); - + + /** + * Solve a kinfo symbol in range with designated type + * + * @param id loaded kinfo id + * @param symbol symbol to solve + * @param start start address range + * @param size address range size + * @param crash kernel panic on invalid non-zero address + * + * @return running symbol address or 0 casted to type T (mach_vm_address_t) + */ + template + inline T solveSymbol(size_t id, const char *symbol, mach_vm_address_t start, size_t size, bool crash=false) { + auto addr = solveSymbol(id, symbol); + if (addr) { + if (addr >= start && addr < start + size) + return (T)addr; + + code = Error::InvalidSymbolFound; + SYSTRACE("patcher", "address " PRIKADDR " is out of range " PRIKADDR " with size %lX", + CASTKADDR(addr), CASTKADDR(start), size); + + PANIC_COND(crash, "patcher", "address " PRIKADDR " is out of range " PRIKADDR " with size %lX", + CASTKADDR(addr), CASTKADDR(start), size); + } + + return (T)nullptr; + } + /** * Hook kext loading and unloading to access kexts at early stage */ EXPORT void setupKextListening(); - + + /** + * Free file buffer resources and effectively make prelinked kext loading impossible + */ + void freeFileBufferResources(); + /** * Activates monitoring functions if necessary */ @@ -211,6 +277,15 @@ class KernelPatcher { * @param patch patch to apply */ EXPORT void applyLookupPatch(const LookupPatch *patch); + + /** + * Apply a find/replace patch with additional constraints + * + * @param patch patch to apply + * @param startingAddress start with this address (or kext/kernel lowest address) + * @param maxSize maximum size to look for (or kext/kernel max size) + */ + EXPORT void applyLookupPatch(const LookupPatch *patch, uint8_t *startingAddress, size_t maxSize); #endif /* LILU_KEXTPATCH_SUPPORT */ /** @@ -220,10 +295,11 @@ class KernelPatcher { * @param to routed function * @param buildWrapper create entrance wrapper * @param kernelRoute kernel change requiring memory protection changes and patch reverting at unload + * @param revertible patches could be reverted * * @return wrapper pointer or 0 on success */ - EXPORT mach_vm_address_t routeFunction(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true); + EXPORT mach_vm_address_t routeFunction(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true); /** * Route block at assembly level @@ -238,6 +314,98 @@ class KernelPatcher { */ EXPORT mach_vm_address_t routeBlock(mach_vm_address_t from, const uint8_t *opcodes, size_t opnum, bool buildWrapper=false, bool kernelRoute=true); + /** + * Route virtual function to function + * + * @param obj OSObject-compatible instance + * @param off function offset in a virtual table (arch-neutral, i.e. divided by sizeof(uintptr_t) + * @param func function to replace with + * @param orgFunc pointer to store the original function + * + * @return true on success + */ + template + static inline bool routeVirtual(void *obj, size_t off, T func, T *orgFunc=nullptr) { + // First OSObject (and similar) field is its virtual table. + auto vt = obj ? reinterpret_cast(obj)[0] : nullptr; + if (vt) { + // Do not try to replace twice! + if (vt[off] == func) + return false; + if (orgFunc) *orgFunc = vt[off]; + vt[off] = func; + return true; + } + return false; + } + + /** + * Route request to simplify casting and error handling + * See routeMultiple. + * + * symbol symbol to lookup + * from solved symbol (assigned by routeMultiple) + * to destination address + * org trampoline storage to the original symbol + */ + struct RouteRequest { + const char *symbol {nullptr}; + mach_vm_address_t from {0}; + const mach_vm_address_t to {0}; + mach_vm_address_t *org {nullptr}; + + /** + * Construct RouteRequest for wrapping a function + * @param s symbol to lookup + * @param t destination address + * @param o trampoline storage to the original symbol + */ + template + RouteRequest(const char *s, T t, mach_vm_address_t &o) : + symbol(s), to(reinterpret_cast(t)), org(&o) { } + + /** + * Construct RouteRequest for routing a function + * @param s symbol to lookup + * @param t destination address + */ + template + RouteRequest(const char *s, T t) : + symbol(s), to(reinterpret_cast(t)) { } + }; + + /** + * Simple route multiple functions with basic error handling + * + * @param id kernel item identifier + * @param requests an array of requests to replace + * @param num requests array size + * @param start start address range + * @param size address range size + * @param kernelRoute kernel change requiring memory protection changes and patch reverting at unload + * @param force continue on first error + * + * @return false if it at least one error happened + */ + EXPORT bool routeMultiple(size_t id, RouteRequest *requests, size_t num, mach_vm_address_t start=0, size_t size=0, bool kernelRoute=true, bool force=false); + + /** + * Simple route multiple functions with basic error handling + * + * @param id kernel item identifier + * @param requests an array of requests to replace + * @param start start address range + * @param size address range size + * @param kernelRoute kernel change requiring memory protection changes and patch reverting at unload + * @param force continue on first error + * + * @return false if it at least one error happened + */ + template + inline bool routeMultiple(size_t id, RouteRequest (&requests)[N], mach_vm_address_t start=0, size_t size=0, bool kernelRoute=true, bool force=false) { + return routeMultiple(id, requests, N, start, size, kernelRoute, force); + } + private: /** @@ -253,7 +421,7 @@ class KernelPatcher { /** * Offset to tempExecutableMemory that is safe to use */ - off_t tempExecutableMemoryOff {0}; + size_t tempExecutableMemoryOff {0}; /** * Patcher status @@ -299,9 +467,9 @@ class KernelPatcher { #endif /* LILU_KEXTPATCH_SUPPORT */ /** - * Local disassmebler instance, initialised on demand + * Kernel prelink image in case prelink is used */ - Disassembler disasm; + MachInfo *prelinkInfo {nullptr}; /** * Loaded kernel items @@ -341,26 +509,28 @@ class KernelPatcher { * Jump instruction sizes */ static constexpr size_t SmallJump {1 + sizeof(int32_t)}; - static constexpr size_t LongJump {2 * sizeof(uint64_t)}; + static constexpr size_t LongJump {6 + sizeof(uint64_t)}; /** * Possible kernel paths */ #ifdef LILU_COMPRESSION_SUPPORT - static constexpr size_t kernelPathsNum {6}; -#else - static constexpr size_t kernelPathsNum {4}; -#endif /* LILU_COMPRESSION_SUPPORT */ - const char *kernelPaths[kernelPathsNum] { - "/mach_kernel", - "/System/Library/Kernels/kernel", //since 10.10 - "/System/Library/Kernels/kernel.debug", - "/System/Library/Kernels/kernel.development", -#ifdef LILU_COMPRESSION_SUPPORT + const char *prelinkKernelPaths[6] { + // This is the usual kernel cache place, which often the best thing to use "/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache", - "/System/Library/PrelinkedKernels/prelinkedkernel" -#endif /* LILU_COMPRESSION_SUPPORT */ - + // Otherwise fallback to one of the prelinked kernels + // Since we always verify the LC_UUID value, trying the kernels could be done in any order. + "/System/Library/PrelinkedKernels/prelinkedkernel", // normal + "/macOS Install Data/Locked Files/Boot Files/prelinkedkernel", // 10.13 installer + "/com.apple.boot.R/prelinkedkernel", // 10.12+ fusion drive installer + "/com.apple.boot.S/System/Library/PrelinkedKernels/prelinkedkernel", // 10.11 fusion drive installer + "/com.apple.recovery.boot/prelinkedkernel" // recovery + }; +#endif + + const char *kernelPaths[2] { + "/System/Library/Kernels/kernel", //since 10.10 + "/mach_kernel" }; }; diff --git a/Lilu.kext/Contents/Resources/Headers/kern_policy.hpp b/Lilu.kext/Contents/Resources/Headers/kern_policy.hpp index ec17f3d..6f61320 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_policy.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_policy.hpp @@ -34,7 +34,7 @@ class Policy { * @param conf policy configuration */ static void dummyPolicyInitBSD(mac_policy_conf *conf) { - DBGLOG("policy @ init bsd"); + DBGLOG("policy", "init bsd"); } /** diff --git a/Lilu.kext/Contents/Resources/Headers/kern_rtc.hpp b/Lilu.kext/Contents/Resources/Headers/kern_rtc.hpp new file mode 100644 index 0000000..c4bd831 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_rtc.hpp @@ -0,0 +1,229 @@ +// +// kern_rtc.hpp +// Lilu +// +// Copyright © 2018 vit9696. All rights reserved. +// + +#ifndef kern_rtc_h +#define kern_rtc_h + +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winconsistent-missing-override" +#include +#pragma clang diagnostic pop + +class RTCStorage { + /** + * General access RTC ports on x86 systems. + */ + static constexpr uint8_t R_PCH_RTC_INDEX = 0x70; + static constexpr uint8_t R_PCH_RTC_TARGET = 0x71; + static constexpr uint8_t R_PCH_RTC_EXT_INDEX = 0x72; + static constexpr uint8_t R_PCH_RTC_EXT_TARGET = 0x73; + + /** + * RTC has N banks (we support up to 2) of memory. + */ + static constexpr uint8_t RTC_BANK_SIZE = 0x80; + + /** + * Non-ext RTC index register uses higher bit for nmi. + */ + static constexpr uint8_t RTC_DATA_MASK = 0x7F; + static constexpr uint8_t RTC_NMI_MASK = 0x80; + + /** + * Apple-specific RTC checksum addresses + */ + static constexpr uint8_t APPLERTC_HASHED_ADDR = 0x0E; + static constexpr uint8_t APPLERTC_CHECKSUM_ADDR1 = 0x58; + static constexpr uint8_t APPLERTC_CHECKSUM_ADDR2 = 0x59; + + /** + * AppleRTC service handle + */ + IOService *rtcSrv {nullptr}; + + /** + * Low-level RTC read (does not check memory availability). + * + * @param dev RTC ACPI device + * @param offset offset + * + * @result read value + */ + static uint8_t readByte(IOACPIPlatformDevice *dev, uint8_t offset); + + /** + * Low-level RTC write (does not check memory availability). + * + * @param dev RTC ACPI device + * @param offset offset + * @param value value + */ + static void writeByte(IOACPIPlatformDevice *dev, uint8_t offset, uint8_t value); +public: + /** + * Attempt to connect to active RTC service + * + * @param wait wait for service availability + * + * @return true on success + */ + EXPORT bool init(bool wait=true); + + /** + * Release obtained RTC service + */ + EXPORT void deinit(); + + /** + * Check whether extended (higher 128 bytes) is available + * + * @return true on success + */ + EXPORT bool checkExtendedMemory(); + + /** + * Read memory from RTC + * + * @param off offset to read data from + * @param size data size + * @param buffer data buffer to read to + * + * @return true on success + */ + EXPORT bool read(uint64_t off, uint32_t size, uint8_t *buffer); + + /** + * Write memory to RTC + * + * @param off offset to write data to + * @param size data size + * @param buffer data buffer to write from + * + * @return true on success + */ + EXPORT bool write(uint64_t off, uint32_t size, uint8_t *buffer); + + /** + * Obtain RTC device for direct writing. + * Written as inline to avoid IOACPIPlatformDevice dependency. + * + * @param name device name + * + * @return RTC ACPI device for I/O access, must be released + */ + static inline IOACPIPlatformDevice *getRTCDevice(const char *name = "PNP0B00") { + IOService *rtcDev = nullptr; + auto matching = IOService::nameMatching(name); + if (matching) { + rtcDev = IOService::waitForMatchingService(matching); + matching->release(); + } else { + SYSLOG("rtc", "failed to allocate rtc device matching"); + } + + if (rtcDev) { + DBGLOG("rtc", "got rtc device"); + auto acpiDev = OSDynamicCast(IOACPIPlatformDevice, rtcDev); + if (acpiDev) { + DBGLOG("rtc", "got rtc acpi device"); + return acpiDev; + } else { + SYSLOG("rtc", "failed to obtain rtc acpi device"); + rtcDev->release(); + } + } + + SYSLOG("rtc", "failed to get rtc device"); + return nullptr; + } + + /** + * Directly read RTC memory (UNSAFE, usage with caution!) + * + * @param dev RTC device + * @param off offset to read data from + * @param size data size + * @param buffer data buffer to read to + * @param introff turn interrupts off + * + * @return true on success + */ + EXPORT static void readDirect(IOACPIPlatformDevice *dev, uint8_t off, uint16_t size, uint8_t *buffer, bool introff); + + /** + * Directly write RTC memory (UNSAFE, usage with caution!) + * + * @param dev RTC device + * @param off offset to read data from + * @param size data size + * @param buffer data buffer to read to + * @param updatecrc recalculate crc on write + * @param introff turn interrupts off + * + * @return true on success + */ + EXPORT static void writeDirect(IOACPIPlatformDevice *dev, uint8_t off, uint16_t size, uint8_t *buffer, bool updatecrc, bool introff); + + + /** + * Directly read RTC memory (UNSAFE, usage with caution!), this is just a compatibility function. + * + * @param off offset to read data from + * @param size data size + * @param buffer data buffer to read to + * @param introff turn interrupts off + * + * @return true on success + */ + static inline bool readDirect(uint8_t off, uint16_t size, uint8_t *buffer, bool introff) { + if (size > RTC_BANK_SIZE*2 - off) { + SYSLOG("rtc", "reading unsupported size"); + return false; + } + + auto rtc = getRTCDevice(); + if (rtc) { + readDirect(rtc, off, size, buffer, introff); + rtc->release(); + return true; + } + + return false; + } + + /** + * Directly write RTC memory (UNSAFE, usage with caution!), this is just a compatibility function. + * + * @param off offset to read data from + * @param size data size + * @param buffer data buffer to read to + * @param updatecrc recalculate crc on write + * @param introff turn interrupts off + * + * @return true on success + */ + static inline bool writeDirect(uint8_t off, uint16_t size, uint8_t *buffer, bool updatecrc, bool introff) { + if (size > RTC_BANK_SIZE*2 - off) { + SYSLOG("rtc", "writing unsupported size"); + return false; + } + + auto rtc = getRTCDevice(); + if (rtc) { + writeDirect(rtc, off, size, buffer, updatecrc, introff); + rtc->release(); + return true; + } + + return false; + } +}; + +#endif /* kern_rtc_h */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_time.hpp b/Lilu.kext/Contents/Resources/Headers/kern_time.hpp new file mode 100644 index 0000000..41d2f91 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Headers/kern_time.hpp @@ -0,0 +1,135 @@ +// +// kern_time.hpp +// Lilu +// +// Copyright © 2018 vit9696. All rights reserved. +// + +#ifndef kern_time_hpp +#define kern_time_hpp + +#include + +/** + * Obtain current system time in nanoseconds + * + * @return current time + */ +inline uint64_t getCurrentTimeNs() { + uint64_t currt = 0; + absolutetime_to_nanoseconds(mach_absolute_time(), &currt); + return currt; +} + +/** + * Obtain current calendar system time in nanoseconds + * + * @return current time + */ +inline uint64_t getCalendarTimeNs() { + clock_sec_t sc; + clock_nsec_t ns; + clock_get_calendar_nanotime(&sc, &ns); + return static_cast(sc) * NSEC_PER_SEC + ns; +} + +/** + * Obtain time passed since some timestamp in nanoseconds + * + * @param start starting timestamp + * @param current timestamp to check against (pass 0 for current time) + * + * @return delta or 0 (if current time equals or precedeces the start) + */ +inline uint64_t getTimeSinceNs(uint64_t start, uint64_t current = 0) { + if (current == 0) + current = getCurrentTimeNs(); + if (current > start) + return current - start; + return 0; +} + +/** + * Obtain time left till a timestamp in the future in nanoseconds + * + * @param start starting timestamp + * @param timeout timeout for the event + * @param current timestamp to check against (pass 0 for current time) + * + * @return delta or 0 (if the timeout is over) + */ +inline uint64_t getTimeLeftNs(uint64_t start, uint64_t timeout, uint64_t current = 0) { + if (current == 0) + current = getCurrentTimeNs(); + if (start + timeout > current) + return start + timeout - current; + return 0; +} + +/** + * Convert from nanoseconds to milliseconds + * + * @param t timestamp in ns + * + * @return timestamp in ms + */ +constexpr uint64_t convertNsToMs(uint64_t t) { + return t / 1000000; +} + +/** + * Convert from nanoseconds to seconds + * + * @param t timestamp in ns + * + * @return timestamp in s + */ +constexpr uint64_t convertNsToSc(uint64_t t) { + return t / 1000000000; +} + +/** + * Convert from milliseconds to seconds + * + * @param t timestamp in ms + * + * @return timestamp in s + */ +constexpr uint64_t convertMsToSc(uint64_t t) { + return t / 1000; +} + +/** + * Convert from milliseconds to nanoseconds + * + * @param t timestamp in ms + * + * @return timestamp in ns + */ +constexpr uint64_t convertMsToNs(uint64_t t) { + return t * 1000000; +} + +/** + * Convert from seconds to nanoseconds + * + * @param t timestamp in s + * + * @return timestamp in ns + */ +constexpr uint64_t convertScToNs(uint64_t t) { + return t * 1000000000; +} + +/** + * Convert from seconds to milliseconds + * + * @param t timestamp in s + * + * @return timestamp in ms + */ +constexpr uint64_t convertScToMs(uint64_t t) { + return t * 1000; +} + +#endif /* kern_time_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/kern_user.hpp b/Lilu.kext/Contents/Resources/Headers/kern_user.hpp index 0816828..26df5a0 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_user.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_user.hpp @@ -114,14 +114,31 @@ class UserPatcher { vm_address_t startDATA; vm_address_t endDATA; }; - + /** * Structure describing relevant processes run */ struct ProcInfo { - const char *path; - uint32_t len; - uint32_t section; + /** + * Process matching flags + */ + enum ProcFlags { + MatchExact = 0, + MatchAny = 1, + MatchPrefix = 2, + MatchSuffix = 4, + MatchMask = MatchExact | MatchAny | MatchPrefix | MatchSuffix + }; + + /** + * Unused (aka disabled) proc info section + */ + static constexpr uint32_t SectionDisabled {0}; + + const char *path {nullptr}; + uint32_t len {0}; + uint32_t section {SectionDisabled}; + uint32_t flags {MatchExact}; }; /** @@ -146,7 +163,51 @@ class UserPatcher { * @param user pointer that will be passed to the callback function */ bool registerPatches(ProcInfo **procs, size_t procNum, BinaryModInfo **mods, size_t modNum, t_BinaryLoaded callback, void *user); - + + /** + * Reads current process header + * + * @param map vm map + * @param header Mach-O header + * + * @return false on failure + */ + EXPORT bool getTaskHeader(vm_map_t map, mach_header_64 &header); + + /** + * Disables dyld_shared_cache for the current process + * + * @param map vm map + * + * @return false on mach image failure + */ + EXPORT bool injectRestrict(vm_map_t map); + + /** + * Injects payload into the process right after the header with EP replacement. + * + * @param map vm map + * @param payload code + * @param size code size (up to PAGE_SIZE) + * @param ep original entrypoint (may be written to code before copying) + * + * @return false on mach image failure + */ + EXPORT bool injectPayload(vm_map_t map, uint8_t *payload, size_t size, void *ep=nullptr); + + /** + * Allocates a new segment in the process. + * + * @param map vm map + * @param addr allocation address (e.g. a little below SHARED_REGION_BASE_X86_64) + * @param payload code + * @param size code size (must be PAGE_SIZE-aligned) + * @param prot segment protection + * + * @return allocated address or 0 on failure + */ + EXPORT vm_address_t injectSegment(vm_map_t taskPort, vm_address_t addr, uint8_t *payload, size_t size, vm_prot_t prot); + /** * Activates monitoring functions if necessary */ @@ -163,6 +224,7 @@ class UserPatcher { using t_codeSignValidateRangeWrapper = boolean_t (*)(void *, memory_object_t, memory_object_offset_t, const void *, memory_object_size_t, unsigned *); using t_vmSharedRegionMapFile = kern_return_t (*)(vm_shared_region_t, unsigned int, shared_file_mapping_np *, memory_object_control_t, memory_object_size_t, void *, uint32_t, user_addr_t slide_start, user_addr_t); using t_vmSharedRegionSlide = int (*)(uint32_t, mach_vm_offset_t, mach_vm_size_t, mach_vm_offset_t, mach_vm_size_t, memory_object_control_t); + using t_vmSharedRegionSlideMojave = int (*)(uint32_t, mach_vm_offset_t, mach_vm_size_t, mach_vm_offset_t, mach_vm_size_t, mach_vm_offset_t, memory_object_control_t); using t_currentMap = vm_map_t (*)(void); using t_getTaskMap = vm_map_t (*)(task_t); using t_getMapMin = vm_map_offset_t (*)(vm_map_t); @@ -178,6 +240,7 @@ class UserPatcher { t_codeSignValidateRangeWrapper orgCodeSignValidateRangeWrapper {nullptr}; t_vmSharedRegionMapFile orgVmSharedRegionMapFile {nullptr}; t_vmSharedRegionSlide orgVmSharedRegionSlide {nullptr}; + t_vmSharedRegionSlideMojave orgVmSharedRegionSlideMojave {nullptr}; t_currentMap orgCurrentMap {nullptr}; t_getMapMin orgGetMapMin {nullptr}; t_getTaskMap orgGetTaskMap {nullptr}; @@ -196,6 +259,7 @@ class UserPatcher { static kern_return_t vmSharedRegionMapFile(vm_shared_region_t shared_region, unsigned int mappings_count, shared_file_mapping_np *mappings, memory_object_control_t file_control, memory_object_size_t file_size, void *root_dir, uint32_t slide, user_addr_t slide_start, user_addr_t slide_size); static void execsigs(proc_t p, thread_t thread); static int vmSharedRegionSlide(uint32_t slide, mach_vm_offset_t entry_start_address, mach_vm_size_t entry_size, mach_vm_offset_t slide_start, mach_vm_size_t slide_size, memory_object_control_t sr_file_control); + static int vmSharedRegionSlideMojave(uint32_t slide, mach_vm_offset_t entry_start_address, mach_vm_size_t entry_size, mach_vm_offset_t slide_start, mach_vm_size_t slide_size, mach_vm_offset_t slid_mapping, memory_object_control_t sr_file_control); static proc_t procExecSwitchTask(proc_t p, task_t current_task, task_t new_task, thread_t new_thread); /** @@ -293,7 +357,7 @@ class UserPatcher { /** * Provided global callback for on proc invocation */ - ppair userCallback; + ppair userCallback {}; /** * Applies dyld shared cache patches @@ -351,7 +415,7 @@ class UserPatcher { }; struct Lookup { - uint32_t offs[4]; + uint32_t offs[4] {}; static constexpr size_t matchNum {4}; evector c[matchNum]; }; @@ -367,7 +431,7 @@ class UserPatcher { sizeof(segment_command_64), "__RESTRICT", SHARED_REGION_BASE_X86_64, - 1 + 1, 0, 0, 0, 0, 0, 0 }; /** @@ -378,14 +442,14 @@ class UserPatcher { sizeof(segment_command), "__RESTRICT", SHARED_REGION_BASE_I386, - 1 + 1, 0, 0, 0, 0, 0, 0 }; /** - * Temporary header for reading data + * Temporary buffer for reading image data */ - mach_header_64 tmpHeader; - + uint8_t tmpBufferData[PAGE_SIZE*3] {}; + /** * Kernel auth listener handle */ @@ -399,7 +463,7 @@ class UserPatcher { /** * Validation cookie */ - void *cookie = {reinterpret_cast(0xB16B00B5)}; + void *cookie {nullptr}; /** * Exec callback @@ -451,16 +515,7 @@ class UserPatcher { * @return true on success */ bool hookMemoryAccess(); - - /** - * Disables dyld_shared_cache for the current process - * - * @param map vm map - * - * @return false on mach image failure - */ - bool injectRestrict(vm_map_t map); - + /** * Peforms the actual binary patching * @@ -471,13 +526,14 @@ class UserPatcher { void patchBinary(vm_map_t map, const char *path, uint32_t len); /** - * Possible dyld shared cache map paths + * Dyld shared cache map path for 10.10+ on Haswell */ - static constexpr size_t sharedCacheMapPathsNum {2}; - const char *sharedCacheMap[sharedCacheMapPathsNum] { - "/private/var/db/dyld/dyld_shared_cache_x86_64h.map", //since 10.10 - "/private/var/db/dyld/dyld_shared_cache_x86_64.map" - }; + static constexpr const char *SharedCacheMapHaswell {"/private/var/db/dyld/dyld_shared_cache_x86_64h.map"}; + + /** + * Dyld shared cache map path for all other systems and older CPUs + */ + static constexpr const char *SharedCacheMapLegacy {"/private/var/db/dyld/dyld_shared_cache_x86_64.map"}; }; diff --git a/Lilu.kext/Contents/Resources/Headers/kern_util.hpp b/Lilu.kext/Contents/Resources/Headers/kern_util.hpp index ddc64bb..727f086 100644 --- a/Lilu.kext/Contents/Resources/Headers/kern_util.hpp +++ b/Lilu.kext/Contents/Resources/Headers/kern_util.hpp @@ -9,10 +9,13 @@ #define kern_util_hpp #include +#include #include +#include #include #include +#include #include #define xStringify(a) Stringify(a) @@ -21,30 +24,212 @@ #define xConcat(a, b) Concat(a, b) #define Concat(a, b) a ## b +/** + * Prefix name with your plugin name (to ease symbolication and avoid conflicts) + */ #define ADDPR(a) xConcat(xConcat(PRODUCT_NAME, _), a) +/** + * Debugging state exported for your plugin + */ extern bool ADDPR(debugEnabled); -// Kernel version major + +/** + * Debugging print delay used as an ugly hack around printf bufferisation, + * which results in messages not appearing in the boot log. + * Use liludelay=1000 (1 second) boot-arg to put a second after each message. + */ +extern uint32_t ADDPR(debugPrintDelay); + +/** + * Kernel version major + */ extern const int version_major; -// Kernel version minor + +/** + * Kernel version minor + */ extern const int version_minor; -// Kernel map + +/** + * Kernel map + */ extern vm_map_t kernel_map; -#define SYSLOG(str, ...) IOLog( xStringify(PRODUCT_NAME) ": " str "\n", ## __VA_ARGS__) +/** + * Kernel proc + */ +extern proc_t kernproc; + +/** + * For noreturn failures + */ +#define UNREACHABLE() do { __builtin_unreachable(); } while (0) + +/** + * Conditional logging to system log prefixed with you plugin name + * + * @param cond precondition + * @param str printf-like string + */ +#define SYSLOG_COND(cond, module, str, ...) \ + do { \ + if (cond) { \ + IOLog( "%s%10s" str "\n", xStringify(PRODUCT_NAME) ": ", module " @ ", ## __VA_ARGS__); \ + if (ADDPR(debugPrintDelay) > 0) IOSleep(ADDPR(debugPrintDelay)); \ + } \ + } while (0) + +/** + * Write to system log prefixed with you plugin name + * + * @param module log module + * @param str printf-like string + */ +#define SYSLOG(module, str, ...) SYSLOG_COND(true, module, str, ## __VA_ARGS__) + +/** + * Conditional tracing to system log prefixed with you plugin name + * + * @param cond precondition + * @param module log module + * @param str printf-like string + */ +#define SYSTRACE_COND(cond, module, str, ...) \ + do { \ + if (cond) { \ + SYSLOG(module, str, ## __VA_ARGS__); \ + OSReportWithBacktrace( "%s%10s" str "\n", xStringify(PRODUCT_NAME) ": ", module " @ ", ## __VA_ARGS__); \ + } \ + } while (0) + +/** + * Write call trace to system log prefixed with you plugin name + * + * @param module log module + * @param str printf-like string + */ +#define SYSTRACE(module, str, ...) SYSTRACE_COND(true, module, str, ## __VA_ARGS__) + +/** + * Conditional panic prefixed with you plugin name + * + * @param cond precondition + * @param module log module + * @param str printf-like string + */ +#define PANIC_COND(cond, module, str, ...) \ + do { \ + if (cond) { \ + (panic)( "%s%10s" str "\n", xStringify(PRODUCT_NAME) ": ", module " @ ", ## __VA_ARGS__); \ + UNREACHABLE(); \ + } \ + } while (0) + +/** + * Cause immediate kernel panic prefixed with you plugin name + * + * @param module log module + * @param str printf-like string + */ +#define PANIC(module, str, ...) PANIC_COND(true, module, str, ## __VA_ARGS__) #ifdef DEBUG -#define DBGLOG(str, ...) \ - do { \ - if (ADDPR(debugEnabled)) \ - SYSLOG( "(DEBUG) " str, ## __VA_ARGS__); \ - } while(0) -#else -#define DBGLOG(str, ...) do { } while(0) + +/** + * Conditional debug logging to system log prefixed with you plugin name + * + * @param cond precondition + * @param module log module + * @param str printf-like string + */ +#define DBGLOG_COND(cond, module, str, ...) \ + do { \ + SYSLOG_COND(ADDPR(debugEnabled) && (cond), module, "%s" str, "(DBG) ", ## __VA_ARGS__); \ + } while (0) + +/** + * Write debug message to system log prefixed with you plugin name + * + * @param module log module + * @param str printf-like string + */ +#define DBGLOG(module, str, ...) DBGLOG_COND(true, module, str, ## __VA_ARGS__) + +/** + * Conditional debug tracing to system log prefixed with you plugin name + * + * @param cond precondition + * @param module log module + * @param str printf-like string + */ +#define DBGTRACE_COND(cond, module, str, ...) \ + do { \ + SYSTRACE_COND(ADDPR(debugEnabled) && (cond), module, "%s" str, "(DBG) ", ## __VA_ARGS__); \ + } while (0) + +/** + * Write debug call trace to system log prefixed with you plugin name + * + * @param module log module + * @param str printf-like string + */ +#define DBGTRACE(module, str, ...) DBGTRACE_COND(true, module, str, ## __VA_ARGS__) + +#else /* DEBUG */ + +#define DBGLOG_COND(module, str, ...) do { } while (0) +#define DBGLOG(module, str, ...) do { } while (0) +#define DBGTRACE_COND(module, str, ...) do { } while (0) +#define DBGTRACE(module, str, ...) do { } while (0) + #endif +/** + * Deprecate the interface + */ +#define DEPRECATE(x) __attribute__((deprecated(x))) + +/** + * Macros to bypass kernel address printing protection + */ +#define PRIKADDR "0x%08X%08X" +#define CASTKADDR(x) \ + static_cast(reinterpret_cast(x) >> 32), \ + static_cast(reinterpret_cast(x)) + +/** + * Macros to print the UUID + */ +#define PRIUUID "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X" +#define CASTUUID(uuid) \ + reinterpret_cast(uuid)[0], \ + reinterpret_cast(uuid)[1], \ + reinterpret_cast(uuid)[2], \ + reinterpret_cast(uuid)[3], \ + reinterpret_cast(uuid)[4], \ + reinterpret_cast(uuid)[5], \ + reinterpret_cast(uuid)[6], \ + reinterpret_cast(uuid)[7], \ + reinterpret_cast(uuid)[8], \ + reinterpret_cast(uuid)[9], \ + reinterpret_cast(uuid)[10], \ + reinterpret_cast(uuid)[11], \ + reinterpret_cast(uuid)[12], \ + reinterpret_cast(uuid)[13], \ + reinterpret_cast(uuid)[14], \ + reinterpret_cast(uuid)[15] + +/** + * Export function or symbol for linking + */ #define EXPORT __attribute__((visibility("default"))) +/** + * Remove padding between fields + */ +#define PACKED __attribute__((packed)) + /** * Two-way substring search * @@ -66,6 +251,16 @@ EXPORT const char *strstr(const char *stack, const char *needle, size_t len=0); */ EXPORT char *strrchr(const char *stack, int ch); +/** + * XNU kernel implementation of a C-standard qsort function normally not exported by the kernel. + * + * @param a array to sort + * @param n array length + * @param es array element size + * @param cmp array element comparator + */ +EXPORT void qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *)); + /** * Count array elements * @@ -85,22 +280,24 @@ extern "C" { void *kern_os_malloc(size_t size); void *kern_os_calloc(size_t num, size_t size); void kern_os_free(void *addr); - void kern_os_cfree(void *addr); void *kern_os_realloc(void *addr, size_t nsize); + // kern_os_free does not check its argument for nullptr + EXPORT void lilu_os_free(void *addr); } /** * Known kernel versions */ enum KernelVersion { - SnowLeopard = 10, - Lion = 11, - MountainLion = 12, - Mavericks = 13, - Yosemite = 14, - ElCapitan = 15, - Sierra = 16, - HighSierra = 17 + SnowLeopard = 10, + Lion = 11, + MountainLion = 12, + Mavericks = 13, + Yosemite = 14, + ElCapitan = 15, + Sierra = 16, + HighSierra = 17, + Mojave = 18, }; /** @@ -126,6 +323,18 @@ inline KernelMinorVersion getKernelMinorVersion() { return static_cast(version_minor); } +/** + * Check whether kernel boot argument is passed ignoring the value (e.g. -arg or arg). + * + * @param name argument name + * + * @return true if argument was passed + */ +inline bool checkKernelArgument(const char *name) { + int val[16]; + return PE_parse_boot_argn(name, val, sizeof(val)); +} + /** * Parse apple version at compile time * @@ -137,18 +346,149 @@ constexpr size_t parseModuleVersion(const char *version) { return (version[0] - '0') * 100 + (version[2] - '0') * 10 + (version[4] - '0'); } +/** + * Access struct member by its offset + * + * @param T pointer to the field you need + * @param that pointer to struct + * @param off offset in bytes to the member + * + * @return reference to the struct member + */ +template +inline T &getMember(void *that, size_t off) { + return *reinterpret_cast(static_cast(that) + off); +} + +/** + * Align value by align (page size by default) + * + * @param size value + * + * @return algined value + */ +template +inline T alignValue(T size, T align = 4096) { + return (size + align - 1) & (~(align - 1)); +} + +/** + * Obtain bit value of size sizeof(T) + * Warning, you are suggested to always pass the type explicitly! + * + * @param n bit no + * + * @return bit value + */ +template +constexpr T getBit(T n) { + return static_cast(1U) << n; +} + +/** + * Obtain bit mask of size sizeof(T) + * Warning, you are suggested to always pass the type explicitly! + * + * @param hi starting high bit + * @param lo ending low bit + * + * @return bit mask + */ +template +constexpr T getBitMask(T hi, T lo) { + return (getBit(hi)|(getBit(hi)-1U)) & ~(getBit(lo)-1U); +} + +/** + * Obtain bit field of size sizeof(T) + * Warning, you are suggested to always pass the type explicitly! + * + * @param so source + * @param hi starting high bit + * @param lo ending low bit + * + * @return bit field value + */ +template +constexpr T getBitField(T so, T hi, T lo) { + return (so & getBitMask(hi, lo)) >> lo; +} + +/** + * Set bit field of size sizeof(T) + * Warning, you are suggested to always pass the type explicitly! + * + * @param va value + * @param hi starting high bit + * @param lo ending low bit + * + * @return bit field value + */ +template +constexpr T setBitField(T so, T hi, T lo) { + return (so << lo) & getBitMask(hi, lo); +} + +/** + * This is an ugly replacement to std::find_if, allowing you + * to check whether a container consists only of value values. + * + * @param in container + * @param size container size + * @param value value to look for + * + * @return true if an element different from value was found + */ +template +inline bool findNotEquals(T &in, size_t size, Y value) { + for (size_t i = 0; i < size; i++) + if (in[i] != value) + return true; + return false; +} + +/** + * Returns non-null string when they can be null + * + * @param str original string + * + * @return non-null string + */ +inline const char *safeString(const char *str) { + return str ? str : "(null)"; +} + +/** + * A shorter form of writing reinterpret_cast(ptr) + */ +template +inline T FunctionCast(T org, mach_vm_address_t ptr) { + return reinterpret_cast(ptr); +} + /** * Typed buffer allocator */ namespace Buffer { template - T *create(size_t size) { - return new T[size]; + inline T *create(size_t size) { + return static_cast(kern_os_malloc(sizeof(T) * size)); } template - void deleter(T *buf) { - delete[] buf; + inline bool resize(T *&buf, size_t size) { + auto nbuf = static_cast(kern_os_realloc(buf, sizeof(T) * size)); + if (nbuf) { + buf = nbuf; + return true; + } + + return false; + } + + template + inline void deleter(T *buf) { + lilu_os_free(buf); } } @@ -217,6 +557,7 @@ struct ppair { /** * Embedded vector-like container * You muse call deinit before destruction + * Ugh, someone, please, port libc++ to XNU... * * @param T held type * @param deleter type destructor @@ -225,13 +566,14 @@ template > class evector { T *ptr {nullptr}; size_t cnt {0}; + size_t rsvd {0}; public: /** * Return evector size * * @return element count */ - const size_t size() const { + size_t size() const { return cnt; } @@ -250,7 +592,7 @@ class evector { * * @return element id */ - const size_t last() const { + size_t last() const { return cnt-1; } @@ -276,6 +618,27 @@ class evector { return ptr[index]; } + /** + * Reserve memory for at least N elements + * + * @param num amount of elements + * + * @return elements ptr or null + */ + T *reserve(size_t num) { + if (rsvd < num) { + T *nPtr = static_cast(kern_os_realloc(ptr, num * sizeof(T))); + if (nPtr) { + ptr = nPtr; + rsvd = num; + } else { + return nullptr; + } + } + + return ptr; + } + /** * Erase evector element * @@ -283,23 +646,15 @@ class evector { * * @return true on success */ - bool erase(size_t index) { - // Free the memory + bool erase(size_t index, bool free=true) { deleter(ptr[index]); - // Shift the items - for (size_t i = index+1; i < cnt; i++) ptr[i-1] = ptr[i]; - // Reduce the memory used - cnt--; - if (cnt == 0) { + if (--cnt != index) + lilu_os_memmove(&ptr[index], &ptr[index + 1], (cnt - index) * sizeof(T)); + + if (free && cnt == 0) { kern_os_free(ptr); ptr = nullptr; - } else { - T *nPtr = static_cast(kern_os_realloc(ptr, (cnt)*sizeof(T))); - if (nPtr) { - ptr = nPtr; - } else { - return false; - } + rsvd = 0; } return true; @@ -313,15 +668,13 @@ class evector { * @return true on success */ bool push_back(T &element) { - T *nPtr = static_cast(kern_os_realloc(ptr, (cnt+1)*sizeof(T))); - if (nPtr) { - ptr = nPtr; + if (reserve(cnt+1)) { ptr[cnt] = element; cnt++; return true; } - SYSLOG("evector @ insertion failure"); + SYSLOG("evector", "insertion failure"); return false; } @@ -333,15 +686,13 @@ class evector { * @return true on success */ bool push_back(T &&element) { - T *nPtr = static_cast(kern_os_realloc(ptr, (cnt+1)*sizeof(T))); - if (nPtr) { - ptr = nPtr; + if (reserve(cnt+1)) { ptr[cnt] = element; cnt++; return true; } - SYSLOG("evector @ insertion failure"); + SYSLOG("evector", "insertion failure"); return false; } @@ -354,14 +705,64 @@ class evector { */ void deinit() { if (ptr) { - for (size_t i = 0; i < cnt; i++) { + for (size_t i = 0; i < cnt; i++) deleter(ptr[i]); - } kern_os_free(ptr); ptr = nullptr; - cnt = 0; + cnt = rsvd = 0; } } }; +/** + * Slightly non-standard helpers to get the date in a YYYY-MM-DD format. + */ +template +inline constexpr char getBuildYear() { + static_assert(i < 4, "Year consists of four digits"); + return __DATE__[7+i]; +} + +template +inline constexpr char getBuildMonth() { + static_assert(i < 2, "Month consists of two digits"); + auto mon = *reinterpret_cast(__DATE__); + switch (mon) { + case ' naJ': + return "01"[i]; + case ' beF': + return "02"[i]; + case ' raM': + return "03"[i]; + case ' rpA': + return "04"[i]; + case ' yaM': + return "05"[i]; + case ' nuJ': + return "06"[i]; + case ' luJ': + return "07"[i]; + case ' guA': + return "08"[i]; + case ' peS': + return "09"[i]; + case ' tcO': + return "10"[i]; + case ' voN': + return "11"[i]; + case ' ceD': + return "12"[i]; + } + + return '0'; +} + +template +inline constexpr char getBuildDay() { + static_assert(i < 2, "Day consists of two digits"); + if (i == 0 && __DATE__[4+i] == ' ') + return '0'; + return __DATE__[4+i]; +} + #endif /* kern_util_hpp */ diff --git a/Lilu.kext/Contents/Resources/Headers/plugin_start.hpp b/Lilu.kext/Contents/Resources/Headers/plugin_start.hpp index 731b5e8..7920882 100644 --- a/Lilu.kext/Contents/Resources/Headers/plugin_start.hpp +++ b/Lilu.kext/Contents/Resources/Headers/plugin_start.hpp @@ -14,23 +14,26 @@ #include struct PluginConfiguration { - const char *product; // Product name (e.g. xStringify(PRODUCT_NAME)) - size_t version; // Product version (e.g. parseModuleVersion(xStringify(MODULE_VERSION))) - const char **disableArg; // Pointer to disabling boot arguments array - size_t disableArgNum; // Number of disabling boot arguments - const char **debugArg; // Pointer to debug boot arguments array - size_t debugArgNum; // Number of debug boot arguments - const char **betaArg; // Pointer to beta boot arguments array - size_t betaArgNum; // Number of beta boot arguments - KernelVersion minKernel; // Minimal required kernel version - KernelVersion maxKernel; // Maximum supported kernel version - void (*pluginStart)(); // Main function + const char *product; // Product name (e.g. xStringify(PRODUCT_NAME)) + size_t version; // Product version (e.g. parseModuleVersion(xStringify(MODULE_VERSION))) + uint32_t runmode; // Product supported environments (e.g. LiluAPI::AllowNormal) + const char **disableArg; // Pointer to disabling boot arguments array + size_t disableArgNum; // Number of disabling boot arguments + const char **debugArg; // Pointer to debug boot arguments array + size_t debugArgNum; // Number of debug boot arguments + const char **betaArg; // Pointer to beta boot arguments array + size_t betaArgNum; // Number of beta boot arguments + KernelVersion minKernel; // Minimal required kernel version + KernelVersion maxKernel; // Maximum supported kernel version + void (*pluginStart)(); // Main function }; #ifndef LILU_CUSTOM_KMOD_INIT extern PluginConfiguration ADDPR(config); +extern bool ADDPR(startSuccess); + #endif /* LILU_CUSTOM_KMOD_INIT */ #ifndef LILU_CUSTOM_IOKIT_INIT @@ -38,11 +41,13 @@ extern PluginConfiguration ADDPR(config); class EXPORT PRODUCT_NAME : public IOService { OSDeclareDefaultStructors(PRODUCT_NAME) public: - bool init(OSDictionary *dict) override; + IOService *probe(IOService *provider, SInt32 *score) override; bool start(IOService *provider) override; void stop(IOService *provider) override; }; +extern PRODUCT_NAME *ADDPR(selfInstance); + #endif /* LILU_CUSTOM_IOKIT_INIT */ #endif /* kern_start_hpp */ diff --git a/Lilu.kext/Contents/Resources/Library/plugin_start.cpp b/Lilu.kext/Contents/Resources/Library/plugin_start.cpp index 37d8c19..db14db0 100644 --- a/Lilu.kext/Contents/Resources/Library/plugin_start.cpp +++ b/Lilu.kext/Contents/Resources/Library/plugin_start.cpp @@ -9,65 +9,89 @@ #include #include +#ifndef LILU_CUSTOM_KMOD_INIT +bool ADDPR(startSuccess) = false; +#else +// Workaround custom kmod code and enable by default +bool ADDPR(startSuccess) = true; +#endif + +bool ADDPR(debugEnabled) = false; +uint32_t ADDPR(debugPrintDelay) = 0; + #ifndef LILU_CUSTOM_IOKIT_INIT +static const char kextVersion[] { +#ifdef DEBUG + 'D', 'B', 'G', '-', +#else + 'R', 'E', 'L', '-', +#endif + xStringify(MODULE_VERSION)[0], xStringify(MODULE_VERSION)[2], xStringify(MODULE_VERSION)[4], '-', + getBuildYear<0>(), getBuildYear<1>(), getBuildYear<2>(), getBuildYear<3>(), '-', + getBuildMonth<0>(), getBuildMonth<1>(), '-', getBuildDay<0>(), getBuildDay<1>(), '\0' +}; + OSDefineMetaClassAndStructors(PRODUCT_NAME, IOService) -bool PRODUCT_NAME::init(OSDictionary *dict) { - if (!IOService::init(dict)) { - SYSLOG("init @ failed to initalise the parent"); - return false; - } - - return true; +PRODUCT_NAME *ADDPR(selfInstance) = nullptr; + +IOService *PRODUCT_NAME::probe(IOService *provider, SInt32 *score) { + ADDPR(selfInstance) = this; + setProperty("VersionInfo", kextVersion); + auto service = IOService::probe(provider, score); + return ADDPR(startSuccess) ? service : nullptr; } bool PRODUCT_NAME::start(IOService *provider) { + ADDPR(selfInstance) = this; if (!IOService::start(provider)) { - SYSLOG("init @ failed to start the parent"); + SYSLOG("init", "failed to start the parent"); return false; } - return true; + return ADDPR(startSuccess); } void PRODUCT_NAME::stop(IOService *provider) { + ADDPR(selfInstance) = nullptr; IOService::stop(provider); } #endif /* LILU_CUSTOM_IOKIT_INIT */ -bool ADDPR(debugEnabled) = false; - #ifndef LILU_CUSTOM_KMOD_INIT EXPORT extern "C" kern_return_t ADDPR(kern_start)(kmod_info_t *, void *) { - kern_return_t ret = KERN_FAILURE; - LiluAPI::Error error = lilu.requestAccess(); - + // This is an ugly hack necessary on some systems where buffering kills most of debug output. + PE_parse_boot_argn("liludelay", &ADDPR(debugPrintDelay), sizeof(ADDPR(debugPrintDelay))); + + auto error = lilu.requestAccess(); if (error == LiluAPI::Error::NoError) { - error = lilu.shouldLoad(ADDPR(config).product, ADDPR(config).version, 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)); + error = lilu.shouldLoad(ADDPR(config).product, ADDPR(config).version, ADDPR(config).runmode, 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(startSuccess) = true; ADDPR(config).pluginStart(); - ret = KERN_SUCCESS; } else { - SYSLOG("init @ parent said we should not continue %d", error); + SYSLOG("init", "parent said we should not continue %d", error); } lilu.releaseAccess(); } else { - SYSLOG("init @ failed to call parent %d", error); + SYSLOG("init", "failed to call parent %d", error); } - - return ret; + + // Report success but actually do not start and let I/O Kit unload us. + // This works better and increases boot speed in some cases. + return KERN_SUCCESS; } EXPORT extern "C" kern_return_t ADDPR(kern_stop)(kmod_info_t *, void *) { - // It is not safe to unload Lilu plugins! - return KERN_FAILURE; + // It is not safe to unload Lilu plugins unless they were disabled! + return ADDPR(startSuccess) ? KERN_FAILURE : KERN_SUCCESS; } #endif /* LILU_CUSTOM_KMOD_INIT */ diff --git a/Lilu.kext/Contents/Resources/Library/wrappers/build.tool b/Lilu.kext/Contents/Resources/Library/wrappers/build.tool new file mode 100755 index 0000000..14c6dae --- /dev/null +++ b/Lilu.kext/Contents/Resources/Library/wrappers/build.tool @@ -0,0 +1,57 @@ +#!/bin/bash +# +# build.tool +# Lilu +# +# Copyright © 2018 vit9696. All rights reserved. +# + +cd $(dirname "$0") || exit 1 + +rm -f *.o *.bin wrappers.inc entry32 entry64 + +clang -m32 -c entry32.S || exit 1 +clang -m64 -c entry64.S || exit 1 + +clang -m32 entry32.o -o entry32 || exit 1 +clang -m64 entry64.o -o entry64 || exit 1 + +if [ "$(nm entry32.o | grep '00000000 T _main')" == "" ] || [ "$(nm entry64.o | grep '0000000000000000 T _main')" == "" ]; then + echo "Invalid main address" + exit 1 +fi + +otool -t entry32 | grep -E '^0000' | sed 's#^[0-9a-f]*##' | xxd -r -p > entry32.bin +otool -t entry64 | grep -E '^0000' | sed 's#^[0-9a-f]*##' | xxd -r -p > entry64.bin + +sz32=$(stat -f '%z' entry32.bin) +sz64=$(stat -f '%z' entry64.bin) + +btr32=$(nm entry32.o | grep -E 't booter$' | cut -f1 -d' ') +btr64=$(nm entry64.o | grep -E 't booter$' | cut -f1 -d' ') + +ep32=$(nm entry32.o | grep -E 't entrypoint$' | cut -f1 -d' ') +ep64=$(nm entry64.o | grep -E 't entrypoint$' | cut -f1 -d' ') + +echo '//' > wrappers.inc +echo '// wrappers.inc' >> wrappers.inc +echo '// Lilu' >> wrappers.inc +echo '//' >> wrappers.inc +echo '// Copyright © 2018 vit9696. All rights reserved.' >> wrappers.inc +echo '//' >> wrappers.inc +echo '' >> wrappers.inc +echo '// This is an autogenerated file, do not edit!' >> wrappers.inc +echo 'static uint8_t entryWrapper32[] = {' >> wrappers.inc +cat entry32.bin | xxd -i >> wrappers.inc +echo '};' >> wrappers.inc +echo 'static uint8_t entryWrapper64[] = {' >> wrappers.inc +cat entry64.bin | xxd -i >> wrappers.inc +echo '};' >> wrappers.inc +echo "static_assert(sizeof(entryWrapper32) == ${sz32}, \"Invalid entryWrapper32 size\");" >> wrappers.inc +echo "static_assert(sizeof(entryWrapper64) == ${sz64}, \"Invalid entryWrapper64 size\");" >> wrappers.inc +echo "static constexpr size_t EntryWrapper32Booter {0x${btr32}};" >> wrappers.inc +echo "static constexpr size_t EntryWrapper64Booter {0x${btr64}};" >> wrappers.inc +echo "static constexpr size_t EntryWrapper32Entry {0x${ep32}};" >> wrappers.inc +echo "static constexpr size_t EntryWrapper64Entry {0x${ep64}};" >> wrappers.inc + +rm -f *.o *.bin entry32 entry64 diff --git a/Lilu.kext/Contents/Resources/Library/wrappers/entry32.S b/Lilu.kext/Contents/Resources/Library/wrappers/entry32.S new file mode 100644 index 0000000..249172e --- /dev/null +++ b/Lilu.kext/Contents/Resources/Library/wrappers/entry32.S @@ -0,0 +1,41 @@ +# +# entry32.S +# Lilu +# +# Copyright © 2018 vit9696. All rights reserved. +# + +.text +.global _main +_main: + push %ebp + mov %esp, %ebp + # ensure 16-byte alignment + and $0xfffffff0, %esp + # int main(int argc, const char* argv[], const char* envp[], const char* apple[]); + push 20(%ebp) + push 16(%ebp) + push 12(%ebp) + push 8(%ebp) + call get_booter +# entrypoint-compatible wrapper +booter: + .word 0xFFFF + .word 0xFFFF +get_booter: + pop %edx + mov (%edx), %edx + call *%edx + xor %eax, %eax + mov %ebp, %esp + pop %ebp + call get_entrypoint +# original entrypoint (main) +entrypoint: + .word 0xFFFF + .word 0xFFFF +get_entrypoint: + pop %edx + mov (%edx), %edx + jmp *%edx +_end: diff --git a/Lilu.kext/Contents/Resources/Library/wrappers/entry64.S b/Lilu.kext/Contents/Resources/Library/wrappers/entry64.S new file mode 100644 index 0000000..01ccc45 --- /dev/null +++ b/Lilu.kext/Contents/Resources/Library/wrappers/entry64.S @@ -0,0 +1,41 @@ +# +# entry64.S +# Lilu +# +# Copyright © 2018 vit9696. All rights reserved. +# + +.text +.global _main +_main: + push %rbp + mov %rsp, %rbp + # ensure 16-byte alignment + and $0xfffffffffffffff0, %rsp + # int main(int argc, const char* argv[], const char* envp[], const char* apple[]); + push %rdi + push %rsi + push %rdx + push %rcx + call *booter(%rip) + xor %eax, %eax + pop %rcx + pop %rdx + pop %rsi + pop %rdi + mov %rbp, %rsp + pop %rbp + jmp *entrypoint(%rip) +# original entrypoint (main) +entrypoint: + .word 0xFFFF + .word 0xFFFF + .word 0xFFFF + .word 0xFFFF +# entrypoint-compatible wrapper +booter: + .word 0xFFFF + .word 0xFFFF + .word 0xFFFF + .word 0xFFFF +_end: diff --git a/Lilu.kext/Contents/Resources/Library/wrappers/wrappers.inc b/Lilu.kext/Contents/Resources/Library/wrappers/wrappers.inc new file mode 100644 index 0000000..62d919c --- /dev/null +++ b/Lilu.kext/Contents/Resources/Library/wrappers/wrappers.inc @@ -0,0 +1,28 @@ +// +// wrappers.inc +// Lilu +// +// Copyright © 2018 vit9696. All rights reserved. +// + +// This is an autogenerated file, do not edit! +static uint8_t entryWrapper32[] = { + 0x55, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0xff, 0x75, 0x14, 0xff, 0x75, 0x10, + 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xe8, 0x04, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x5a, 0x8b, 0x12, 0xff, 0xd2, 0x31, 0xc0, 0x89, 0xec, + 0x5d, 0xe8, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5a, 0x8b, + 0x12, 0xff, 0xe2 +}; +static uint8_t entryWrapper64[] = { + 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xe4, 0xf0, 0x57, 0x56, 0x52, 0x51, + 0xff, 0x15, 0x18, 0x00, 0x00, 0x00, 0x31, 0xc0, 0x59, 0x5a, 0x5e, 0x5f, + 0x48, 0x89, 0xec, 0x5d, 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff +}; +static_assert(sizeof(entryWrapper32) == 51, "Invalid entryWrapper32 size"); +static_assert(sizeof(entryWrapper64) == 50, "Invalid entryWrapper64 size"); +static constexpr size_t EntryWrapper32Booter {0x00000017}; +static constexpr size_t EntryWrapper64Booter {0x000000000000002a}; +static constexpr size_t EntryWrapper32Entry {0x0000002a}; +static constexpr size_t EntryWrapper64Entry {0x0000000000000022}; diff --git a/README.md b/README.md index 4f3e566..e44ffa2 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,19 @@ Boot args: - AR9565: -ath9565 +#### Installation +- This kext version requires LILU plugin version 1.2.6+ +- Download Lilu.kext, ATH9KInjector.kext and ATH9KFixup.kext +- Inject Lilu.kext and ATH9KFixup.kext using CLOVER bootloader. +- Install ATH9KInjector.kext to /System/Library/Extensions (CLOVER injection won't work). +- User -ath9485 boot arg for AR9485 and -ath9565 for AR9565 (If you don't use any boot args it will do the patching for AR946X by default) +- Optional (Rebuild Caches) + + #### Credits - [Apple](https://www.apple.com) for macOS -- [vit9696](https://github.com/vit9696) for [Lilu.kext](https://github.com/vit9696/Lilu) & for patch +- [Acidanthera](https://github.com/acidanthera) for [Lilu.kext](https://github.com/acidanthera/Lilu) & for patch - [Pike R. Alpha](https://github.com/Piker-Alpha) for patch - [lvs1974](https://applelife.ru/members/lvs1974.53809/) for original source code and idea - [chunnann](http://www.insanelymac.com/forum/user/1977171-chunnann/) for writing the software and maintaining it +- [black.dragon74](https://github.com/black-dragon74) for adding support for Lilu 1.2.0+ and macOS Mojave