Skip to content

Commit

Permalink
Add HDMI audio support (#129)
Browse files Browse the repository at this point in the history
Signed-off-by: Visual Ehrmanntraut <[email protected]>
  • Loading branch information
VisualEhrmanntraut committed Aug 7, 2023
1 parent 1444841 commit 189b852
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 2 deletions.
12 changes: 10 additions & 2 deletions NootedRed.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
40FC5FDE29BF996900367F9D /* kern_hwlibs.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 40FC5FDC29BF996900367F9D /* kern_hwlibs.hpp */; };
40FC5FE129BF9E2500367F9D /* kern_x6000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40FC5FDF29BF9E2500367F9D /* kern_x6000.cpp */; };
40FC5FE229BF9E2500367F9D /* kern_x6000.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 40FC5FE029BF9E2500367F9D /* kern_x6000.hpp */; };
6C1B36662A407C6100B184DD /* kern_hdmi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C1B36642A407C6100B184DD /* kern_hdmi.cpp */; };
6C1B36672A407C6200B184DD /* kern_hdmi.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 6C1B36652A407C6100B184DD /* kern_hdmi.hpp */; };
CE405ED91E4A080700AA0B3D /* plugin_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE405ED81E4A080700AA0B3D /* plugin_start.cpp */; };
CE8DA0832517C41A008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA0822517C41A008C44E8 /* libkmod.a */; };
CEA03B5E20EE825A00BA842F /* kern_nred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEA03B5C20EE825A00BA842F /* kern_nred.cpp */; };
Expand Down Expand Up @@ -74,6 +76,8 @@
40FC5FDC29BF996900367F9D /* kern_hwlibs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_hwlibs.hpp; sourceTree = "<group>"; };
40FC5FDF29BF9E2500367F9D /* kern_x6000.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = kern_x6000.cpp; sourceTree = "<group>"; };
40FC5FE029BF9E2500367F9D /* kern_x6000.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_x6000.hpp; sourceTree = "<group>"; };
6C1B36642A407C6100B184DD /* kern_hdmi.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = kern_hdmi.cpp; sourceTree = "<group>"; };
6C1B36652A407C6100B184DD /* kern_hdmi.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_hdmi.hpp; sourceTree = "<group>"; };
CE405EBA1E49DD7100AA0B3D /* kern_compression.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_compression.hpp; sourceTree = "<group>"; };
CE405EBB1E49DD7100AA0B3D /* kern_disasm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_disasm.hpp; sourceTree = "<group>"; };
CE405EBC1E49DD7100AA0B3D /* kern_file.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kern_file.hpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -130,8 +134,12 @@
408F201A288AC068002EEC15 /* Firmware */,
1C748C2E1C21952C0024EED2 /* Info.plist */,
CEB402A71F181D8300716912 /* kern_amd.hpp */,
4019EAE52A3488EC008D800B /* kern_dyld_patches.cpp */,
4019EAE32A348852008D800B /* kern_dyld_patches.hpp */,
408F201F288ACBE6002EEC15 /* kern_fw.cpp */,
408F201E288ACBB0002EEC15 /* kern_fw.hpp */,
6C1B36642A407C6100B184DD /* kern_hdmi.cpp */,
6C1B36652A407C6100B184DD /* kern_hdmi.hpp */,
40FC5FDB29BF996900367F9D /* kern_hwlibs.cpp */,
40FC5FDC29BF996900367F9D /* kern_hwlibs.hpp */,
40364DB529B79DFD0070A2B4 /* kern_model.hpp */,
Expand All @@ -149,8 +157,6 @@
40FC5FE029BF9E2500367F9D /* kern_x6000.hpp */,
40FC5FD329BF995000367F9D /* kern_x6000fb.cpp */,
40FC5FD429BF995000367F9D /* kern_x6000fb.hpp */,
4019EAE32A348852008D800B /* kern_dyld_patches.hpp */,
4019EAE52A3488EC008D800B /* kern_dyld_patches.cpp */,
);
path = NootedRed;
sourceTree = "<group>";
Expand Down Expand Up @@ -234,6 +240,7 @@
40FC5FDE29BF996900367F9D /* kern_hwlibs.hpp in Headers */,
4019EAE42A348852008D800B /* kern_dyld_patches.hpp in Headers */,
4068898C2A229BF600028D22 /* kern_patcherplus.hpp in Headers */,
6C1B36672A407C6200B184DD /* kern_hdmi.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -336,6 +343,7 @@
files = (
40FC5FDD29BF996900367F9D /* kern_hwlibs.cpp in Sources */,
40FC5FD529BF995000367F9D /* kern_x6000fb.cpp in Sources */,
6C1B36662A407C6100B184DD /* kern_hdmi.cpp in Sources */,
408F2020288ACBE6002EEC15 /* kern_fw.cpp in Sources */,
4068898B2A229BF600028D22 /* kern_patcherplus.cpp in Sources */,
40FC5FE129BF9E2500367F9D /* kern_x6000.cpp in Sources */,
Expand Down
44 changes: 44 additions & 0 deletions NootedRed/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,48 @@
<string>$(MODULE_VERSION)</string>
<key>IOKitPersonalities</key>
<dict>
<key>AMD</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.driver.AppleGFXHDA</string>
<key>DPAlwaysDisplayRouting</key>
<array>
<integer>3</integer>
<integer>33</integer>
<integer>35</integer>
<integer>88</integer>
</array>
<key>DPAudioDeviceExclusion</key>
<array>
<dict>
<key>ManufacturerID</key>
<integer>1552</integer>
<key>ProductID</key>
<integer>10130</integer>
</dict>
</array>
<key>HighFIFOLimitSupport</key>
<array/>
<key>IOClass</key>
<string>AppleGFXHDAEGController</string>
<key>IOPCIMatch</key>
<string>0x15DE1002 0x16371002</string>
<key>IOPCITunnelCompatible</key>
<true/>
<key>IOPCIUseDeviceMapper</key>
<true/>
<key>IOProviderClass</key>
<string>IOPCIDevice</string>
<key>RequireMaxBusStall</key>
<array>
<dict>
<key>Layouts</key>
<array/>
<key>MaxBusStall</key>
<integer>15000</integer>
</dict>
</array>
</dict>
<key>AMDGPUWrangler</key>
<dict>
<key>CFBundleIdentifier</key>
Expand Down Expand Up @@ -51,6 +93,8 @@
<string>0x15DD1002 0x15D81002 0x15E71002 0x164C1002 0x16381002 0x16361002</string>
<key>IOPCITunnelCompatible</key>
<true/>
<key>IOPCIUseDeviceMapper</key>
<true/>
<key>IOProbeScore</key>
<integer>6000</integer>
<key>IOPropertyMatch</key>
Expand Down
63 changes: 63 additions & 0 deletions NootedRed/kern_hdmi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright © 2022-2023 ChefKiss Inc. Licensed under the Thou Shalt Not Profit License version 1.0. See LICENSE for
// details.

#include "kern_hdmi.hpp"
#include "kern_nred.hpp"
#include "kern_patcherplus.hpp"
#include "kern_patches.hpp"
#include "kern_patterns.hpp"
#include <Headers/kern_api.hpp>

static const char *pathAppleGFXHDA = "/System/Library/Extensions/AppleGFXHDA.kext/Contents/MacOS/AppleGFXHDA";
static const char *pathAppleHDA = "/System/Library/Extensions/AppleHDA.kext/Contents/MacOS/AppleHDA";

static KernelPatcher::KextInfo kextAppleGFXHDA {"com.apple.driver.AppleGFXHDA", &pathAppleGFXHDA, 1, {true}, {},
KernelPatcher::KextInfo::Unloaded};
static KernelPatcher::KextInfo kextAppleHDA {"com.apple.driver.AppleHDA", &pathAppleHDA, 1, {true}, {},
KernelPatcher::KextInfo::Unloaded};

HDMI *HDMI::callback = nullptr;

void HDMI::init() {
callback = this;
lilu.onKextLoadForce(&kextAppleGFXHDA);
lilu.onKextLoadForce(&kextAppleHDA);
}

bool HDMI::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size) {
if (kextAppleGFXHDA.loadIndex == id) {
const uint32_t probeFind = 0xAB381002;
const uint32_t probeRepl = NRed::callback->deviceId <= 0x15DD ? 0x15DE1002 : 0x16371002;
LookupPatchPlus patches[] = {
{&kextAppleGFXHDA, reinterpret_cast<const uint8_t *>(&probeFind),
reinterpret_cast<const uint8_t *>(&probeRepl), sizeof(probeFind), 1},
{&kextAppleGFXHDA, kCreateAppleHDAFunctionGroup1Original, kCreateAppleHDAFunctionGroup1Patched, 1},
{&kextAppleGFXHDA, kCreateAppleHDAFunctionGroup2Original, kCreateAppleHDAFunctionGroup2Patched, 1},
{&kextAppleGFXHDA, kCreateAppleHDAWidget1Original, kCreateAppleHDAWidget1OriginalMask,
kCreateAppleHDAWidget1Patched, kCreateAppleHDAWidget1PatchedMask, 1},
{&kextAppleGFXHDA, kCreateAppleHDAWidget2Original, kCreateAppleHDAWidget2OriginalMask,
kCreateAppleHDAWidget2Patched, 1},
{&kextAppleGFXHDA, kCreateAppleHDAOriginal, kCreateAppleHDAOriginalMask, kCreateAppleHDAPatched,
kCreateAppleHDAPatchedMask, 2},
{&kextAppleGFXHDA, kCreateAppleHDA2Original, kCreateAppleHDA2OriginalMask, kCreateAppleHDA2Patched,
kCreateAppleHDA2PatchedMask, 2},
};
PANIC_COND(!LookupPatchPlus::applyAll(patcher, patches, slide, size), "agfxhda", "Failed to apply patches: %d",
patcher.getError());

return true;
} else if (kextAppleHDA.loadIndex == id) {
LookupPatchPlus patches[] = {
{&kextAppleHDA, kAHDACreate1Original, kAHDACreate1Patched, 2},
{&kextAppleHDA, kAHDACreate2Original, kAHDACreate2OriginalMask, kAHDACreate2Patched,
kAHDACreate2PatchedMask, 2},
{&kextAppleHDA, kAHDACreate3Original, kAHDACreate3Mask, kAHDACreate3Patched, 2},
};
PANIC_COND(!LookupPatchPlus::applyAll(patcher, patches, slide, size), "ahda", "Failed to apply patches: %d",
patcher.getError());

return true;
}

return false;
}
14 changes: 14 additions & 0 deletions NootedRed/kern_hdmi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright © 2022-2023 ChefKiss Inc. Licensed under the Thou Shalt Not Profit License version 1.0. See LICENSE for
// details.

#pragma once
#include "kern_amd.hpp"
#include <Headers/kern_patcher.hpp>
#include <Headers/kern_util.hpp>

class HDMI {
public:
static HDMI *callback;
void init();
bool processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size);
};
5 changes: 5 additions & 0 deletions NootedRed/kern_nred.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "kern_nred.hpp"
#include "kern_dyld_patches.hpp"
#include "kern_hdmi.hpp"
#include "kern_hwlibs.hpp"
#include "kern_model.hpp"
#include "kern_patcherplus.hpp"
Expand Down Expand Up @@ -32,6 +33,7 @@ static X5000HWLibs hwlibs;
static X5000 x5000;
static X6000 x6000;
static DYLDPatches dyldpatches;
static HDMI agfxhda;

void NRed::init() {
SYSLOG("nred", "Copyright 2022-2023 ChefKiss Inc. If you've paid for this, you've been scammed.");
Expand All @@ -40,6 +42,7 @@ void NRed::init() {
lilu.onKextLoadForce(&kextAGDP);
lilu.onKextLoadForce(&kextBacklight);
lilu.onKextLoadForce(&kextMCCSControl);
agfxhda.init();
dyldpatches.init();
x6000fb.init();
hwlibs.init();
Expand Down Expand Up @@ -216,6 +219,8 @@ void NRed::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slid
};
patcher.routeMultiple(id, requests, slide, size);
patcher.clearError();
} else if (agfxhda.processKext(patcher, id, slide, size)) {
DBGLOG("nred", "Processed AppleGFXHDA");
} else if (x6000fb.processKext(patcher, id, slide, size)) {
DBGLOG("nred", "Processed AMDRadeonX6000Framebuffer");
} else if (hwlibs.processKext(patcher, id, slide, size)) {
Expand Down
1 change: 1 addition & 0 deletions NootedRed/kern_nred.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static bool checkAtomBios(const uint8_t *bios, size_t size) {
}

class NRed {
friend class HDMI;
friend class DYLDPatches;
friend class X6000FB;
friend class X5000HWLibs;
Expand Down
103 changes: 103 additions & 0 deletions NootedRed/kern_patches.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,106 @@ static const uint8_t kGetHWEngineCallPatched[] = {0x00, 0x00, 0x00, 0xFF, 0x90,
*/
static const uint8_t kGetAMDHWHandlerCallOriginal[] = {0xFF, 0x90, 0xD0, 0x02, 0x00, 0x00};
static const uint8_t kGetAMDHWHandlerCallPatched[] = {0xFF, 0x90, 0xC8, 0x02, 0x00, 0x00};

/**
* `AppleGFXHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* AppleGFXHDA.kext
*/
static const uint8_t kCreateAppleHDAFunctionGroup1Original[] = {0x3D, 0xD7, 0xAA, 0x00, 0x00};
static const uint8_t kCreateAppleHDAFunctionGroup1Patched[] = {0x3D, 0x00, 0x00, 0x00, 0x00};
static_assert(arrsize(kCreateAppleHDAFunctionGroup1Original) == arrsize(kCreateAppleHDAFunctionGroup1Patched));

/**
* `AppleGFXHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* AppleGFXHDA.kext
*/
static const uint8_t kCreateAppleHDAFunctionGroup2Original[] = {0x3D, 0xF7, 0xAA, 0x00, 0x00, 0x7F};
static const uint8_t kCreateAppleHDAFunctionGroup2Patched[] = {0x3D, 0xF7, 0xAA, 0x00, 0x00, 0xEB};
static_assert(arrsize(kCreateAppleHDAFunctionGroup2Original) == arrsize(kCreateAppleHDAFunctionGroup2Patched));

/**
* `AppleGFXHDAWidgetFactory::createAppleHDAWidget`
* AppleGFXHDA.kext
* Force else path for `deviceID < 0xAA88` and `deviceID < 0xAAE0` check
*/
static const uint8_t kCreateAppleHDAWidget1Original[] = {0x3D, 0x87, 0xAA, 0x00, 0x00, 0x7E, 0x00, 0x3D, 0xDF, 0xAA,
0x00, 0x00, 0x7F, 0x00};
static const uint8_t kCreateAppleHDAWidget1OriginalMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00};
static const uint8_t kCreateAppleHDAWidget1Patched[] = {0x66, 0x90, 0x66, 0x90, 0x66, 0x90, 0x90, 0x66, 0x90, 0x66,
0x90, 0x90, 0xEB, 0x00};
static const uint8_t kCreateAppleHDAWidget1PatchedMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00};
static_assert(arrsize(kCreateAppleHDAWidget1Original) == arrsize(kCreateAppleHDAWidget1OriginalMask));
static_assert(arrsize(kCreateAppleHDAWidget1Patched) == arrsize(kCreateAppleHDAWidget1PatchedMask));
static_assert(arrsize(kCreateAppleHDAWidget1Original) == arrsize(kCreateAppleHDAWidget1Patched));

/**
* `AppleGFXHDAWidgetFactory::createAppleHDAWidget`
* AppleGFXHDA.kext
* Force else path for `deviceID < 0xAB20` check
*/
static const uint8_t kCreateAppleHDAWidget2Original[] = {0x3D, 0x1F, 0xAB, 0x00, 0x00, 0x7E, 0x00};
static const uint8_t kCreateAppleHDAWidget2OriginalMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static const uint8_t kCreateAppleHDAWidget2Patched[] = {0x66, 0x90, 0x66, 0x90, 0x66, 0x90, 0x90};
static_assert(arrsize(kCreateAppleHDAWidget2Original) == arrsize(kCreateAppleHDAWidget2OriginalMask));
static_assert(arrsize(kCreateAppleHDAWidget2Original) == arrsize(kCreateAppleHDAWidget2Patched));

/**
* `AppleGFXHDAWidgetFactory::createAppleHDAWidget`
* `AppleGFXHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* AppleGFXHDA.kext
* Force else path for `0x18 < deviceID - 0xAB20` check
*/
static const uint8_t kCreateAppleHDAOriginal[] = {0x8D, 0x88, 0xE0, 0x54, 0xFF, 0xFF, 0x83, 0xF9, 0x18, 0x77, 0x00};
static const uint8_t kCreateAppleHDAOriginalMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static const uint8_t kCreateAppleHDAPatched[] = {0x66, 0x90, 0x66, 0x90, 0x66, 0x90, 0x66, 0x90, 0x90, 0xEB, 0x00};
static const uint8_t kCreateAppleHDAPatchedMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static_assert(arrsize(kCreateAppleHDAOriginal) == arrsize(kCreateAppleHDAOriginalMask));
static_assert(arrsize(kCreateAppleHDAPatched) == arrsize(kCreateAppleHDAPatchedMask));
static_assert(arrsize(kCreateAppleHDAOriginal) == arrsize(kCreateAppleHDAPatched));

/**
* `AppleGFXHDAWidgetFactory::createAppleHDAWidget`
* `AppleGFXHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* AppleGFXHDA.kext
* Force `deviceID == 0xA*F8` path
*/
static const uint8_t kCreateAppleHDA2Original[] = {0x3D, 0xF8, 0xA0, 0x00, 0x00, 0x74, 0x00};
static const uint8_t kCreateAppleHDA2OriginalMask[] = {0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0x00};
static const uint8_t kCreateAppleHDA2Patched[] = {0x66, 0x90, 0x66, 0x90, 0x90, 0xEB, 0x00};
static const uint8_t kCreateAppleHDA2PatchedMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static_assert(arrsize(kCreateAppleHDA2Original) == arrsize(kCreateAppleHDA2OriginalMask));
static_assert(arrsize(kCreateAppleHDA2Patched) == arrsize(kCreateAppleHDA2PatchedMask));
static_assert(arrsize(kCreateAppleHDA2Original) == arrsize(kCreateAppleHDA2Patched));

/**
* `AppleHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* `AppleHDAWidgetFactory::createAppleHDAWidget`
* AppleHDA.kext
*/
static const uint8_t kAHDACreate1Original[] = {0x87, 0xAA, 0x00, 0x00, 0x0F, 0x8F};
static const uint8_t kAHDACreate1Patched[] = {0x66, 0x90, 0x66, 0x90, 0x48, 0xE9};
static_assert(arrsize(kAHDACreate1Original) == arrsize(kAHDACreate1Patched));

/**
* `AppleHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* `AppleHDAWidgetFactory::createAppleHDAWidget`
* AppleHDA.kext
*/
static const uint8_t kAHDACreate2Original[] = {0x83, 0x00, 0x38, 0x77, 0x00, 0xB0};
static const uint8_t kAHDACreate2OriginalMask[] = {0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xF0};
static const uint8_t kAHDACreate2Patched[] = {0x66, 0x90, 0x90, 0xEB, 0x00, 0x00};
static const uint8_t kAHDACreate2PatchedMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
static_assert(arrsize(kAHDACreate2Original) == arrsize(kAHDACreate2Patched));

/**
* `AppleHDAFunctionGroupFactory::createAppleHDAFunctionGroup`
* `AppleHDAWidgetFactory::createAppleHDAWidget`
* AppleHDA.kext
*/
static const uint8_t kAHDACreate3Original[] = {0xD8, 0xAA, 0x00, 0x00, 0x75, 0x00};
static const uint8_t kAHDACreate3Mask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static const uint8_t kAHDACreate3Patched[] = {0x66, 0x90, 0x66, 0x90, 0x66, 0x90};
static_assert(arrsize(kAHDACreate3Original) == arrsize(kAHDACreate3Mask));
static_assert(arrsize(kAHDACreate3Original) == arrsize(kAHDACreate3Patched));
1 change: 1 addition & 0 deletions Scripts/NRedWrapGen.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def locate_line(lines: list[str], needle: str) -> int:
"x5000": "X5000",
"x6000": "X6000",
"x6000fb": "X6000FB",
"agfxhda": "AppleGFXHDA"
}

module: str = input("Filename without extension: ./NootedRed/kern_")
Expand Down

0 comments on commit 189b852

Please sign in to comment.