Skip to content

Commit

Permalink
Add HDMI 2.0 patches
Browse files Browse the repository at this point in the history
  • Loading branch information
vit9696 committed Jul 12, 2018
1 parent 308e9da commit a1e1b7c
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 24 deletions.
4 changes: 3 additions & 1 deletion README.md
Expand Up @@ -51,10 +51,12 @@ Read [FAQs](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/) an
- [Apple](https://www.apple.com) for macOS
- [AMD](https://www.amd.com) for ATOM VBIOS parsing code
- [The PCI ID Repository](http://pci-ids.ucw.cz) for multiple GPU model names
- [Floris497](https://github.com/Floris497) for the CoreDisplay [patches](https://github.com/Floris497/mac-pixel-clock-patch-v2)
- [igork](https://applelife.ru/members/igork.564/) for power-gating patch discovery
- [lvs1974](https://applelife.ru/members/lvs1974.53809) for continuous implementation of Intel and NVIDIA fixing code
- [mologie](https://github.com/mologie/NVWebDriverLibValFix) for creating NVWebDriverLibValFix.kext which forces macOS to recognize NVIDIA's web drivers as platform binaries
- [PMheart](https://github.com/PMheart) for CoreDisplay patching code and Intel fix backporting
- [RemB](https://applelife.ru/members/remb.8064/) for continuing sleep-wake research and finding the right register for AMD issues
- [Vandroiy](https://applelife.ru/members/vandroiy.83653/) for maintaining the GPU model detection database
- [YungRaj](https://github.com/YungRaj), [PMheart](https://github.com/PMheart), [syscl](https://github.com/syscl) for Intel fix backporting
- [YungRaj](https://github.com/YungRaj) and [syscl](https://github.com/syscl) for Intel fix backporting
- [vit9696](https://github.com/vit9696) for writing the software and maintaining it
8 changes: 8 additions & 0 deletions WhateverGreen.xcodeproj/project.pbxproj
Expand Up @@ -26,6 +26,8 @@
CEA03B5E20EE825A00BA842F /* kern_weg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEA03B5C20EE825A00BA842F /* kern_weg.cpp */; };
CEA03B5F20EE825A00BA842F /* kern_weg.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CEA03B5D20EE825A00BA842F /* kern_weg.hpp */; };
CEB402A61F17F5C400716912 /* kern_con.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CEB402A41F17F5C400716912 /* kern_con.hpp */; };
CEC8E2F020F765E700D3CA3A /* kern_cdf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEC8E2EE20F765E700D3CA3A /* kern_cdf.cpp */; };
CEC8E2F120F765E700D3CA3A /* kern_cdf.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CEC8E2EF20F765E700D3CA3A /* kern_cdf.hpp */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -114,6 +116,8 @@
CEAEA1191F26905A00918651 /* Sample.dsl */ = {isa = PBXFileReference; lastKnownFileType = text; path = Sample.dsl; sourceTree = "<group>"; };
CEB402A41F17F5C400716912 /* kern_con.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kern_con.hpp; sourceTree = "<group>"; };
CEB402A71F181D8300716912 /* kern_atom.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_atom.hpp; sourceTree = "<group>"; };
CEC8E2EE20F765E700D3CA3A /* kern_cdf.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = kern_cdf.cpp; sourceTree = "<group>"; };
CEC8E2EF20F765E700D3CA3A /* kern_cdf.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_cdf.hpp; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -162,6 +166,8 @@
children = (
1C748C2C1C21952C0024EED2 /* kern_start.cpp */,
CEB402A71F181D8300716912 /* kern_atom.hpp */,
CEC8E2EE20F765E700D3CA3A /* kern_cdf.cpp */,
CEC8E2EF20F765E700D3CA3A /* kern_cdf.hpp */,
CEB402A41F17F5C400716912 /* kern_con.hpp */,
CE7FC0AC20F5622700138088 /* kern_igfx.cpp */,
CE7FC0AD20F5622700138088 /* kern_igfx.hpp */,
Expand Down Expand Up @@ -290,6 +296,7 @@
CE7FC0AF20F5622700138088 /* kern_igfx.hpp in Headers */,
CE7FC0B520F6809600138088 /* kern_shiki.hpp in Headers */,
1C9CB7B11C789FF500231E41 /* kern_rad.hpp in Headers */,
CEC8E2F120F765E700D3CA3A /* kern_cdf.hpp in Headers */,
CEB402A61F17F5C400716912 /* kern_con.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -410,6 +417,7 @@
buildActionMask = 2147483647;
files = (
CE7FC0AE20F5622700138088 /* kern_igfx.cpp in Sources */,
CEC8E2F020F765E700D3CA3A /* kern_cdf.cpp in Sources */,
1C9CB7B01C789FF500231E41 /* kern_rad.cpp in Sources */,
CE7FC0B420F6809600138088 /* kern_shiki.cpp in Sources */,
CE7FC0B120F563CA00138088 /* kern_ngfx_asm.S in Sources */,
Expand Down
243 changes: 243 additions & 0 deletions WhateverGreen/kern_cdf.cpp
@@ -0,0 +1,243 @@
//
// kern_cdf.cpp
// WhateverGreen
//
// Copyright © 2018 vit9696. All rights reserved.
//

#include "kern_cdf.hpp"

#include <Headers/kern_api.hpp>
#include <Headers/kern_iokit.hpp>

// NVDAGK100Hal.kext - system built-in, for Kepler
static const char *pathGKHal[] = {
"/System/Library/Extensions/NVDAGK100Hal.kext/Contents/MacOS/NVDAGK100Hal"
};

// NVDAGK100HalWeb.kext - from web driver, for Kepler
static const char *pathGKWeb[] = {
"/Library/Extensions/NVDAGK100HalWeb.kext/Contents/MacOS/NVDAGK100HalWeb",
"/System/Library/Extensions/NVDAGK100HalWeb.kext/Contents/MacOS/NVDAGK100HalWeb"
};

// NVDAGM100HalWeb.kext - from web driver, for Maxwell
static const char *pathGMWeb[] = {
"/Library/Extensions/NVDAGM100HalWeb.kext/Contents/MacOS/NVDAGM100HalWeb",
"/System/Library/Extensions/NVDAGM100HalWeb.kext/Contents/MacOS/NVDAGM100HalWeb"
};

// NVDAGP100HalWeb.kext - from web driver, for Pascal
static const char *pathGPWeb[] = {
"/Library/Extensions/NVDAGP100HalWeb.kext/Contents/MacOS/NVDAGP100HalWeb",
"/System/Library/Extensions/NVDAGP100HalWeb.kext/Contents/MacOS/NVDAGP100HalWeb"
};

static KernelPatcher::KextInfo kextList[] {
{ "com.apple.nvidia.driver.NVDAGK100Hal", pathGKHal, arrsize(pathGKHal), {}, {}, KernelPatcher::KextInfo::Unloaded },
{ "com.nvidia.web.NVDAGK100HalWeb", pathGKWeb, arrsize(pathGKWeb), {}, {}, KernelPatcher::KextInfo::Unloaded },
{ "com.nvidia.web.NVDAGM100HalWeb", pathGMWeb, arrsize(pathGMWeb), {}, {}, KernelPatcher::KextInfo::Unloaded },
{ "com.nvidia.web.NVDAGP100HalWeb", pathGPWeb, arrsize(pathGPWeb), {}, {}, KernelPatcher::KextInfo::Unloaded },
};

enum : size_t {
KextGK100HalSys,
KextGK100HalWeb,
KextGM100HalWeb,
KextGP100HalWeb
};

// target framework for 10.10.x and 10.11.x
static const char *binaryIOKitFramework = "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit";
// target framework as of 10.12.x
static const char *binaryCoreDisplayFramework = "/System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay";
// accompanied process for 10.10.x or 10.11.x
static const char *procWindowServerOld = "/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/WindowServer";
static uint32_t procWindowServerOldLen = sizeof("/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Resources/WindowServer") - 1;
// accompanied process for 10.12.x
static const char *procWindowServerNew = "/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/Resources/WindowServer";
static uint32_t procWindowServerNewLen = sizeof("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/Resources/WindowServer") - 1;

enum : uint32_t {
SectionYosEC = 1,
SectionSieHS = 2,
SectionHS1034 = 3
};

// Patches
//
// for NVDAGK100Hal and NVDAGK100HalWeb
//
// Reference:
// https://github.com/Floris497/mac-pixel-clock-patch-V2/blob/master/NVIDIA-patcher.command
//
static const uint8_t gk100Find[] = { 0x88, 0x84, 0x02, 0x00 };
static const uint8_t gk100Repl[] = { 0x80, 0x1A, 0x06, 0x00 };
//
// for NVDAGM100HalWeb and NVDAGP100HalWeb
//
// Reference:
// https://github.com/Floris497/mac-pixel-clock-patch-V2/blob/master/NVIDIA-WEB-MAXWELL-patcher.command
//
static const uint8_t gmp100Find[] = { 0x88, 0x84, 0x02, 0x00 };
static const uint8_t gmp100Repl[] = { 0x40, 0x42, 0x0F, 0x00 };
//
// for frameworks
//
// Reference:
// https://github.com/Floris497/mac-pixel-clock-patch-V2/blob/master/CoreDisplay-patcher.command
//
// Modified by PMheart (jmpq adress optimisations)
//
static const uint8_t frameworkOldFind[] {
0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 0x1
0xF6, 0xC1, 0x01, // test cl, 0x1
0x0F, 0x85 // jne "somewhere" ; Don't care for the exact offset!
};

static const uint8_t frameworkOldRepl[] {
0x33, 0xC0, // xor eax, eax ; 0
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop (7x) ; placeholders
0xE9 // jmp "somewhere" ; Don't care for the exact offset!
};

// 10.13.4+
static const uint8_t frameworkNewFind[] {
0xBB, 0x01, 0x00, 0x00, 0x00, // mov ebx, 0x1
0xA8, 0x01, // test al, 0x1
0x0F, 0x85 // jne <somewhere>
};

static const uint8_t frameworkNewRepl[] {
0x31, 0xDB, // xor ebx, ebx
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop (6x)
0xE9 // jmp <somewhere>
};

static UserPatcher::BinaryModPatch frameworkPatchOld {
CPU_TYPE_X86_64,
frameworkOldFind,
frameworkOldRepl,
arrsize(frameworkOldFind),
0, // skip = 0 -> replace all occurrences
1, // count = 1 -> 1 set of hex inside the target binaries
UserPatcher::FileSegment::SegmentTextText,
SectionHS1034 // 10.10.x till 10.13.3 (all universal)
};

static UserPatcher::BinaryModPatch frameworkPatchNew {
CPU_TYPE_X86_64,
frameworkNewFind,
frameworkNewRepl,
arrsize(frameworkNewFind),
0, // skip = 0 -> replace all occurrences
1, // count = 1 -> 1 set of hex inside the target binaries
UserPatcher::FileSegment::SegmentTextText,
SectionHS1034 // 10.13.4+
};

// 10.10.x and 10.11.x
static UserPatcher::BinaryModInfo binaryModYosEC { binaryIOKitFramework, &frameworkPatchOld, 1 };
// 10.12.x and 10.13.0-10.13.3
static UserPatcher::BinaryModInfo binaryModSieHS { binaryCoreDisplayFramework, &frameworkPatchOld, 1 };
// 10.13.4+
static UserPatcher::BinaryModInfo binaryModHS1034 { binaryCoreDisplayFramework, &frameworkPatchNew, 1 };

// 10.10.x and 10.11.x
static UserPatcher::ProcInfo procInfoYosEC { procWindowServerOld, procWindowServerOldLen, SectionYosEC };
// 10.12.x and 10.13.x
static UserPatcher::ProcInfo procInfoSieHS { procWindowServerNew, procWindowServerNewLen, SectionSieHS };

CDF *CDF::callbackCDF;

void CDF::init() {
callbackCDF = this;
lilu.onKextLoadForce(kextList, arrsize(kextList));

if (getKernelVersion() == KernelVersion::Yosemite || getKernelVersion() == KernelVersion::ElCapitan) {
// 10.10, 10.11
currentProcInfo = &procInfoYosEC;
currentModInfo = &binaryModYosEC;
} else if (getKernelVersion() == KernelVersion::Sierra || (getKernelVersion() == KernelVersion::HighSierra && getKernelMinorVersion() < 5)) {
// 10.12, 10.13.0-10.13.3
currentProcInfo = &procInfoSieHS;
currentModInfo = &binaryModSieHS;
} else if ((getKernelVersion() == KernelVersion::HighSierra && getKernelMinorVersion() >= 5) || getKernelVersion() == KernelVersion::Mojave) {
// 10.13.4+
currentProcInfo = &procInfoSieHS;
currentModInfo = &binaryModHS1034;
}

if (currentProcInfo && currentModInfo)
lilu.onProcLoadForce(currentProcInfo, 1, nullptr, nullptr, currentModInfo, 1);
}

void CDF::deinit() {

}

void CDF::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
bool hasNVIDIA = false;
for (size_t i = 0; i < info->videoExternal.size(); i++) {
if (info->videoExternal[i].vendor == WIOKit::VendorID::NVIDIA) {
hasNVIDIA = true;
break;
}
}

if (!hasNVIDIA) {
for (size_t i = 0; i < arrsize(kextList); i++)
kextList[i].switchOff();
}

if (!hasNVIDIA && !info->videoBuiltin && currentProcInfo && currentModInfo) {
currentProcInfo->section = UserPatcher::ProcInfo::SectionDisabled;
for (size_t i = 0; i < currentModInfo->count; i++)
currentModInfo->patches[i].section = UserPatcher::ProcInfo::SectionDisabled;
}
}

bool CDF::processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
if (kextList[KextGK100HalSys].loadIndex == index) {
KernelPatcher::LookupPatch patch {&kextList[KextGK100HalSys], gk100Find, gk100Repl, sizeof(gk100Find), 1};
patcher.applyLookupPatch(&patch);
if (patcher.getError() != KernelPatcher::Error::NoError) {
SYSLOG("cdf", "failed to apply gk100 patch %d", patcher.getError());
patcher.clearError();
}
return true;
}

if (kextList[KextGK100HalWeb].loadIndex == index) {
KernelPatcher::LookupPatch patch {&kextList[KextGK100HalWeb], gk100Find, gk100Repl, sizeof(gk100Find), 1};
patcher.applyLookupPatch(&patch);
if (patcher.getError() != KernelPatcher::Error::NoError) {
SYSLOG("cdf", "failed to apply gk100 web patch %d", patcher.getError());
patcher.clearError();
}
return true;
}

if (kextList[KextGM100HalWeb].loadIndex == index) {
KernelPatcher::LookupPatch patch {&kextList[KextGM100HalWeb], gmp100Find, gmp100Repl, sizeof(gmp100Find), 1};
patcher.applyLookupPatch(&patch);
if (patcher.getError() != KernelPatcher::Error::NoError) {
SYSLOG("cdf", "failed to apply gm100 web patch %d", patcher.getError());
patcher.clearError();
}
return true;
}

if (kextList[KextGP100HalWeb].loadIndex == index) {
KernelPatcher::LookupPatch patch {&kextList[KextGP100HalWeb], gmp100Find, gmp100Repl, sizeof(gmp100Find), 1};
patcher.applyLookupPatch(&patch);
if (patcher.getError() != KernelPatcher::Error::NoError) {
SYSLOG("cdf", "failed to apply gp100 web patch %d", patcher.getError());
patcher.clearError();
}
return true;
}

return false;
}

57 changes: 57 additions & 0 deletions WhateverGreen/kern_cdf.hpp
@@ -0,0 +1,57 @@
//
// kern_cdf.hpp
// WhateverGreen
//
// Copyright © 2018 vit9696. All rights reserved.
//

#ifndef kern_cdf_hpp
#define kern_cdf_hpp

#include <Headers/kern_patcher.hpp>
#include <Headers/kern_devinfo.hpp>
#include <Headers/kern_user.hpp>

class CDF {
public:
void init();
void deinit();

/**
* Property patching routine
*
* @param patcher KernelPatcher instance
* @param info device info
*/
void processKernel(KernelPatcher &patcher, DeviceInfo *info);

/**
* Patch kext if needed and prepare other patches
*
* @param patcher KernelPatcher instance
* @param index kinfo handle
* @param address kinfo load address
* @param size kinfo memory size
*
* @return true if patched anything
*/
bool processKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size);

private:
/**
* Private self instance for callbacks
*/
static CDF *callbackCDF;

/**
* Current proc info containing the right path to WindowServer
*/
UserPatcher::ProcInfo *currentProcInfo {nullptr};

/**
* Current binary modification containing the right framework mod
*/
UserPatcher::BinaryModInfo *currentModInfo {nullptr};
};

#endif /* kern_cdf_hpp */
8 changes: 6 additions & 2 deletions WhateverGreen/kern_igfx.cpp
Expand Up @@ -92,11 +92,15 @@ void IGFX::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
if (!connectorLessFrame && ((getKernelVersion() == KernelVersion::Sierra && getKernelMinorVersion() >= 5) ||
(getKernelVersion() == KernelVersion::HighSierra && getKernelMinorVersion() < 5)) &&
(cpuGeneration == CPUInfo::CpuGeneration::Skylake || cpuGeneration == CPUInfo::CpuGeneration::KabyLake)) {
blackScreenPatch = true;
blackScreenPatch = info->firmwareVendor != DeviceInfo::FirmwareVendor::Apple;
}

// GuC firmware is just fine on Apple hardware
if (info->firmwareVendor == DeviceInfo::FirmwareVendor::Apple)
avoidFirmwareLoading = false;

// PAVP patch is only necessary when we have no discrete GPU
pavpDisablePatch = !connectorLessFrame;
pavpDisablePatch = !connectorLessFrame && info->firmwareVendor != DeviceInfo::FirmwareVendor::Apple;

int gl = info->videoBuiltin->getProperty("disable-metal") != nullptr;
PE_parse_boot_argn("igfxgl", &gl, sizeof(gl));
Expand Down
5 changes: 5 additions & 0 deletions WhateverGreen/kern_shiki.cpp
Expand Up @@ -102,6 +102,11 @@ void SHIKI::deinit() {
}

void SHIKI::processKernel(KernelPatcher &patcher, DeviceInfo *info) {
if (info->firmwareVendor == DeviceInfo::FirmwareVendor::Apple) {
// DRMI is just fine on Apple hardware
disableSection(SectionNDRMI);
}

if (autodetectGFX) {
bool hasExternalNVIDIA = false;
bool hasExternalAMD = false;
Expand Down

0 comments on commit a1e1b7c

Please sign in to comment.